Last updated: 2026-04-07 22:27:51 HKT
This directory contains the schema migrations, local Supabase configuration, and Edge Functions that support the STEM Learning Platform. Supabase is not just the database layer for this project. It also provides auth, storage, queue-backed background processing, guest sandbox lifecycle data, and Edge Function runtime support.
- the confirmation email source of truth lives at
supabase/templates/confirmation.html - the recovery email source of truth lives at
supabase/templates/recovery.html - local Supabase uses both templates through
auth.email.template.confirmationandauth.email.template.recoveryinsupabase/config.toml - hosted Supabase still needs the same HTML pasted into Auth -> Email Templates -> Confirm signup and Auth -> Email Templates -> Reset password
- the confirmation button is intentionally wired to the app SSR route:
{{ .RedirectTo }}/auth/confirm?token_hash={{ .TokenHash }}&type=email&next=/login&email={{ .Email }} - the recovery button is intentionally wired to the same callback route:
{{ .RedirectTo }}/auth/confirm?token_hash={{ .TokenHash }}&type=recovery&email={{ .Email }} - the template depends on publicly served brand assets under
web/public/email/ - after changing the local template config, restart local Supabase so the auth service reloads it
- confirmation and recovery email links are expected to expire after 5 minutes; keep local
auth.email.otp_expiryand the hosted project's Email OTP Expiration dashboard setting aligned at300
| Path | Purpose |
|---|---|
migrations/ |
active SQL migrations applied by supabase db push |
migrations_archive/ |
historical archived migration files not used by the active CLI path |
functions/material-worker/ |
material processing worker |
functions/guest-sandbox-cleanup/ |
guest sandbox cleanup worker |
templates/confirmation.html |
branded confirmation email template — paste into Supabase Dashboard → Auth → Email Templates |
templates/recovery.html |
branded reset-password email template — paste into Supabase Dashboard → Auth → Email Templates |
config.toml |
local Supabase configuration |
- email/password auth
- anonymous auth for guest mode
- Postgres schema and RLS
- private materials storage
- queue-backed material processing with
pgmq - cron-backed dispatch and SQL helper functions
- snapshot storage for class intelligence and teaching briefs
- guest sandbox persistence and cleanup support
The migration history reflects several major architectural shifts.
0001_init.sql- baseline schema
- core tables
- RLS
- material processing jobs
- assignment recipient model
- AI request logging
0002_quiz_integrity_and_review_performance.sql0003_auth_account_hardening.sql0004_blueprint_canonical_snapshot.sql
0005_always_on_class_chat.sql0006_class_chat_assistant_insert_hardening.sql0007_class_chat_context_compaction.sql0008_material_queue_worker.sql0009_remove_vision_legacy_artifacts.sql
0010_frontend_route_performance_indexes.sql0011_fix_publish_blueprint_advisory_lock.sql0012_materials_delete_policy.sql0013_add_class_insights_snapshots.sql0014_add_class_teaching_brief_snapshots.sql
0015_guest_mode_schema.sql0016_guest_seed_data.sql0017_guest_mode_enforcement.sql0018_guest_entry_rate_limit.sql(legacy per-IP entry limiting, later retired)0019_guest_mode_alignment_fixes.sql0020_fix_guest_clone_profile_bootstrap.sql0021_fix_guest_seed_insight_scores.sql0022_fix_guest_quota_state_cleanup.sql0023_guest_quota_redesign.sql
flowchart LR
Web[Next.js Web App] --> SB[(Supabase)]
Py[Python Backend] --> SB
SB --> Auth[Auth]
SB --> DB[(Postgres + RLS)]
SB --> Storage[Storage]
SB --> Queue[pgmq Queue]
SB --> Cron[pg_cron]
SB --> Edge[Edge Functions]
Queue --> Edge
Cron --> Edge
Edge --> MW[material-worker]
Edge --> GC[guest-sandbox-cleanup]
npx supabase link --project-ref <PROJECT_REF>
npx supabase db push- active migrations are read from
supabase/migrations/*.sql - archived migration files are not part of the active CLI migration path
- local
config.tomlalready encodes important behavior like email confirmations and anonymous sign-ins
The hosted project should support the capabilities used by the migrations:
pgcryptovectorpgmqpg_netpg_cronvault
- email/password auth only
- email confirmation enabled
- immutable account type in
profiles - verification emails use a custom branded confirmation template and should resolve through the app's
/auth/confirmroute for SSR-safe verification
- guest mode depends on Supabase Anonymous Auth
- anonymous users still get real auth identities
- guest sandboxes store ownership and lifecycle state in
guest_sandboxes - session creation is now governed by
guest_session_quota, not the retiredguest_entry_rate_limitstable - current defaults are 60 active guest sessions globally and 20 new guest sessions per hour
- active sandboxes expire after 32 hours max or 8 hours of inactivity
- cleanup removes guest class data and anonymous auth users
- stale guest sessions are reconciled before new session cap checks so expired rows cannot block fresh guest entry indefinitely
The current guest quota model lives in 0023_guest_quota_redesign.sql.
guest_session_quotais the global control table for active guest sessions, hourly creation count, and in-flight AI requestsacquire_guest_session_serviceis called before sandbox creation and enforces the current active-session and hourly-creation capsrelease_guest_session_slot_serviceis called when a session slot needs to be returned because provisioning failed or a sandbox timed out before frontend cleanup ranrelease_guest_sandbox_quotaandguest-sandbox-cleanupkeep the AI and session counters aligned when expired or discarded sandboxes are deletedreconcile_guest_session_quota_servicemarks stale active rows as expired and recomputes the global quota counters before the active-session cap is enforced
- materials are stored in the private
materialsbucket - the baseline schema creates the bucket if it does not exist
material_chunks.embeddingcurrently usesvector(1536)- if embedding dimension changes, keep migration logic and runtime
EMBEDDING_DIMaligned
Material processing is asynchronous and queue-backed.
sequenceDiagram
participant Web as Next.js App
participant PY as Python Backend
participant DB as Postgres
participant Queue as pgmq
participant Cron as pg_cron
participant Worker as material-worker
Web->>DB: Insert material row
Web->>PY: Request /v1/materials/dispatch
PY->>DB: Call enqueue_material_job RPC
DB->>Queue: Enqueue work item
Note over PY,Worker: Backend can wake the worker immediately
Cron->>Worker: Dispatch worker run
Worker->>DB: Claim job
Worker->>Worker: Extract, chunk, embed
Worker->>DB: Persist chunks and mark status
- material work is not driven by Vercel cron
- dispatch relies on SQL-side queue and cron helpers
material-workerneeds its own secrets in Supabase- provider embedding models must be configured for the worker to complete successfully
guest-sandbox-cleanup is responsible for cleaning expired or discarded guest sandboxes.
Cleanup dispatch is now scheduled from Supabase itself, matching the material worker pattern:
- SQL wrapper:
run_guest_sandbox_cleanup_dispatch - cron job:
guest-sandbox-cleanup-dispatch-5m - cadence: every 5 minutes
- find expired or discarded guest sandboxes
- remove guest material storage paths
- release any remaining guest quota counters before row deletion
- delete sandbox-scoped class data
- delete anonymous auth users
- remove
guest_sandboxesrows
Set these in Supabase for the functions that need them:
MATERIAL_WORKER_TOKENGUEST_SANDBOX_CLEANUP_TOKENGUEST_SANDBOX_CLEANUP_BATCHif you need to tune the cleanup batch sizeGUEST_SANDBOX_CLEANUP_MAX_TOTALif you need to cap total deletions per invocation- provider API keys and model env vars for worker execution
Material dispatch expects Vault secrets such as:
project_urlmaterial_worker_tokenguest_sandbox_cleanup_tokenwhen the cleanup Edge Function is protected by a bearer token
These are used by SQL-side dispatch helpers and should be configured in each hosted environment.
- RLS is enabled across application tables
- policies enforce teacher ownership, enrollment-based access, and guest sandbox isolation
- guest-mode migrations extend many tables with
sandbox_idso cloned demo data can live alongside real product data safely
npx supabase functions deploy material-worker
npx supabase functions deploy guest-sandbox-cleanupmaterial-worker- process queued materials
- extract text
- chunk text
- generate embeddings
- update processing state
guest-sandbox-cleanup- clean expired or discarded guest sandboxes
- release leaked quota counters and stale active-session counts
- run on a recurring Supabase cron schedule rather than an app-host cron
- reclaim expired guest data
- remove storage artifacts
- delete anonymous users
Use this directory as the primary source of truth when you need to understand:
- schema changes
- guest-mode persistence
- background job behavior
- storage rules
- SQL-side operational assumptions
../README.md— project overview../ARCHITECTURE.md— deep technical architecture../DESIGN.md— product and system design../DEPLOYMENT.md— hosted deployment runbook../UIUX.md— frontend language and interface system../backend/README.md— backend service behavior../web/README.md— frontend behavior and envs