106 lines
5.5 KiB
Markdown
106 lines
5.5 KiB
Markdown
# Classroom Copilot Supabase migrations and deterministic dev seed
|
|
|
|
Status: branch implementation validated on Supabase dev host 192.168.0.94 using an isolated throwaway database.
|
|
|
|
## Consolidated init chain
|
|
|
|
The Docker Compose `db` service now mounts a single ordered Classroom Copilot chain:
|
|
|
|
1. `volumes/db/cc/61-gais-reference.sql` — GAIS reference table schema and open-data read policies only.
|
|
2. `volumes/db/cc/62-application-schema.sql` — canonical app schema, storage/file metadata tables, class/lesson/CIS tables, indexes, and base RLS.
|
|
3. `volumes/db/cc/63-academic-calendar.sql` — school timetable, academic year/term/week/day, teacher timetable, and teacher slot tables.
|
|
4. `volumes/db/cc/64-extended-schema.sql` — term breaks, academic periods, invitations, taught lessons, and week-cycle slot uniqueness.
|
|
5. `volumes/db/cc/65-phase-c.sql` — Phase C cleanup after taught lessons exist; links lesson deliveries to taught lessons.
|
|
6. `volumes/db/cc/66-taught-lessons-nullable.sql` — nullable taught lesson `class_id` and teacher slot class FK.
|
|
7. `volumes/db/cc/67-dev-seed.sql` — deterministic, non-sensitive dev fixtures.
|
|
|
|
The old `61-core-schema.sql` through `70-add-directory-support.sql` bootstrap files were removed from the active chain because they represented an older ClassConcepts/filesystem schema and stale role vocabulary. The Git history remains the archive.
|
|
|
|
## Deterministic dev seed contents
|
|
|
|
`67-dev-seed.sql` creates only fixture data:
|
|
|
|
- 1 platform admin in `admin_profiles`.
|
|
- 1 school/institute.
|
|
- 1 school admin, 2 teachers, 3 students.
|
|
- institute memberships for the school admin, teachers, and students.
|
|
- 2 classes with class-teacher and class-student rows.
|
|
- 1 school timetable, 1 academic year, 1 term, 1 week, 4 academic days, and 16 academic periods.
|
|
- 2 teacher timetables, 3 teacher timetable slots, and 3 taught lessons.
|
|
- 2 planned lessons and 1 delivered lesson fixture.
|
|
- Storage buckets `cc.users`, `cc.public.snapshots`, and `cc.examboards`.
|
|
- TLDraw default snapshot paths on the teacher whiteboard rooms; object rows are not pre-created.
|
|
|
|
Fixture emails use the `classroomcopilot.dev` domain and are not real users. Do not replace this seed with live student/teacher data.
|
|
|
|
## Validation pattern used on Supabase dev
|
|
|
|
Do not run schema experiments on production. To validate this branch without mutating the live dev database, create a throwaway database on the Supabase dev Postgres container, clone only the `auth` and `storage` schema definitions from dev, apply the ordered chain, check row counts, then drop the throwaway database.
|
|
|
|
The 2026-05-28 validation used this shape on `ubuntu-ct-supabase-dev` (`192.168.0.94`):
|
|
|
|
```bash
|
|
DB=cc_mig_validate_<timestamp>
|
|
BASE=/tmp/cc-supabase-migration-validate
|
|
|
|
docker exec supabase-db psql -U postgres -d postgres -v ON_ERROR_STOP=1 -c "DROP DATABASE IF EXISTS $DB WITH (FORCE);"
|
|
docker exec supabase-db psql -U postgres -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE $DB;"
|
|
|
|
# The dev auth schema has a trigger that references public.handle_new_user();
|
|
# create a no-op stub before restoring auth/storage schema-only into the throwaway DB.
|
|
cat >/tmp/create_dummy.sql <<'SQL'
|
|
create or replace function public.handle_new_user()
|
|
returns trigger
|
|
language plpgsql
|
|
as $$
|
|
begin
|
|
return new;
|
|
end;
|
|
$$;
|
|
SQL
|
|
docker exec -i supabase-db psql -U postgres -d "$DB" -v ON_ERROR_STOP=1 < /tmp/create_dummy.sql
|
|
|
|
docker exec supabase-db pg_dump -U postgres -d postgres --schema-only --no-owner --no-privileges -n auth -n storage > /tmp/${DB}_auth_storage_schema.sql
|
|
docker exec -i supabase-db psql -U postgres -d "$DB" -v ON_ERROR_STOP=1 < /tmp/${DB}_auth_storage_schema.sql
|
|
|
|
for f in \
|
|
"$BASE"/volumes/db/cc/61-gais-reference.sql \
|
|
"$BASE"/volumes/db/cc/62-application-schema.sql \
|
|
"$BASE"/volumes/db/cc/63-academic-calendar.sql \
|
|
"$BASE"/volumes/db/cc/64-extended-schema.sql \
|
|
"$BASE"/volumes/db/cc/65-phase-c.sql \
|
|
"$BASE"/volumes/db/cc/66-taught-lessons-nullable.sql \
|
|
"$BASE"/volumes/db/cc/67-dev-seed.sql; do
|
|
docker exec -i supabase-db psql -U postgres -d "$DB" -v ON_ERROR_STOP=1 < "$f"
|
|
done
|
|
|
|
# Smoke counts, then cleanup.
|
|
docker exec supabase-db psql -U postgres -d "$DB" -Atc "select 'profiles='||count(*) from public.profiles union all select 'institutes='||count(*) from public.institutes union all select 'memberships='||count(*) from public.institute_memberships union all select 'classes='||count(*) from public.classes union all select 'academic_periods='||count(*) from public.academic_periods union all select 'teacher_timetable_slots='||count(*) from public.teacher_timetable_slots union all select 'taught_lessons='||count(*) from public.taught_lessons union all select 'planned_lessons='||count(*) from public.planned_lessons union all select 'lesson_deliveries='||count(*) from public.lesson_deliveries union all select 'buckets='||count(*) from storage.buckets where id like 'cc.%';"
|
|
docker exec supabase-db psql -U postgres -d postgres -v ON_ERROR_STOP=1 -c "DROP DATABASE IF EXISTS $DB WITH (FORCE);"
|
|
```
|
|
|
|
Expected smoke counts from the deterministic seed:
|
|
|
|
```text
|
|
profiles=7
|
|
institutes=1
|
|
memberships=6
|
|
classes=2
|
|
academic_periods=16
|
|
teacher_timetable_slots=3
|
|
taught_lessons=3
|
|
planned_lessons=2
|
|
lesson_deliveries=1
|
|
buckets=3
|
|
```
|
|
|
|
## Production rule
|
|
|
|
This branch is not a production migration by itself. Before production use:
|
|
|
|
1. Take a production schema/data backup.
|
|
2. Compare live production schema drift against this consolidated chain.
|
|
3. Prepare explicit forward migrations for any live-only objects or data transforms.
|
|
4. Validate those forward migrations on Supabase dev first.
|
|
5. Only apply to production after human approval.
|