From 5da108df13d4f672d240d609c83db2f28cf8c8fe Mon Sep 17 00:00:00 2001 From: kcar Date: Mon, 8 Jun 2026 00:57:57 +0100 Subject: [PATCH] docs(reset): clarify exam-corpus scope --- .../database/tools/platform_admin_router.py | 10 +++-- run/initialization/reset_environment.py | 38 +++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/routers/database/tools/platform_admin_router.py b/routers/database/tools/platform_admin_router.py index f427cdf..2513c67 100644 --- a/routers/database/tools/platform_admin_router.py +++ b/routers/database/tools/platform_admin_router.py @@ -132,9 +132,13 @@ async def reset_environment( """DESTRUCTIVE: wipe test data. Platform admin only. scope (query param): - - all : full wipe (Neo4j + Supabase data + auth users) AND exam subsystem + storage. - - exam-corpus : ONLY the exam corpus — eb_*/exam_* tables + cc.examboards storage objects - (load/unload the public corpus without touching schools/users). + - all : full wipe (Neo4j + Supabase data + auth users) AND the entire + exam-marker subsystem below. + - exam-corpus : ONLY the entire exam-marker subsystem, not just public papers: + public corpus/eb_* data, cc.examboards storage objects, exam + templates, template layouts, questions, boundaries, response + areas, marking batches, student submissions, and mark entries + (without touching schools/users). - timetable : ONLY timetable/calendar materialization tables. """ if scope not in ("all", "exam-corpus", "timetable"): diff --git a/run/initialization/reset_environment.py b/run/initialization/reset_environment.py index b06e076..aca34ca 100644 --- a/run/initialization/reset_environment.py +++ b/run/initialization/reset_environment.py @@ -82,8 +82,11 @@ SUPABASE_TABLES_TO_CLEAR = [ "admin_profiles", ] -# Exam subsystem tables, FK child-first. NOT in the list above — the previous full reset() -# never cleared exam data or storage at all; the granular scopes below fold it in. +# Exam-marker subsystem tables, FK child-first. scope="exam-corpus" is deliberately +# broader than "public papers": it wipes public corpus eb_* rows, templates, layouts, +# questions, boundaries, response areas, marking batches, student submissions, and mark +# entries. NOT in the list above — the previous full reset() never cleared exam data +# or storage at all; the granular scopes below fold it in. EXAM_CORPUS_TABLES = [ "mark_entries", "student_submissions", @@ -114,7 +117,8 @@ TIMETABLE_TABLES = [ "planned_lessons", ] -# Buckets whose objects the exam-corpus reset clears (Storage API — protect_delete blocks raw SQL). +# Bucket whose objects scope="exam-corpus" clears for the whole exam-marker subsystem +# (Storage API — protect_delete blocks raw SQL). EXAM_STORAGE_BUCKET = "cc.examboards" @@ -217,8 +221,13 @@ def _clear_tables(url: str, headers: dict, tables: List[str]) -> "tuple[List[str def _clear_exam_storage() -> Dict[str, Any]: - """Remove cc.examboards objects via the Storage API (protect_delete blocks raw SQL deletes). - Gathers storage_loc from eb_exams/eb_specifications BEFORE the rows are cleared.""" + """Remove cc.examboards objects for the exam-marker subsystem. + + scope="exam-corpus" is not limited to public-paper metadata: it also removes the + storage objects that back exam board corpus files and any downstream exam-marker + artifacts referenced from eb_exams/eb_specifications. Gathers storage_loc from + eb_exams/eb_specifications BEFORE the rows are cleared. + """ try: from modules.database.supabase.utils.client import SupabaseServiceRoleClient from modules.database.supabase.utils.storage import StorageAdmin @@ -257,8 +266,12 @@ def _clear_exam_storage() -> Dict[str, Any]: def reset(scope: str = "all") -> Dict[str, Any]: """Destructive reset. scope ∈ {all, exam-corpus, timetable}. - - all : full wipe (Neo4j + Supabase data + auth users) AND the exam subsystem + storage. - - exam-corpus : ONLY eb_*/exam_* tables + cc.examboards storage objects (load/unload the corpus). + - all : full wipe (Neo4j + Supabase data + auth users) AND the entire + exam-marker subsystem listed below. + - exam-corpus : ONLY the entire exam-marker subsystem, not just public papers: + public corpus/eb_* data, cc.examboards storage objects, exam + templates, template layouts, questions, boundaries, response + areas, marking batches, student submissions, and mark entries. - timetable : ONLY timetable/calendar materialization tables. """ scope = (scope or "all").lower() @@ -268,7 +281,7 @@ def reset(scope: str = "all") -> Dict[str, Any]: _assert_reset_allowed(url, scope) if scope == "exam-corpus": - logger.info("RESET (scope=exam-corpus) — exam tables + cc.examboards storage") + logger.info("RESET (scope=exam-corpus) — entire exam-marker subsystem: public corpus/eb_* data, cc.examboards storage, templates/layout/questions/boundaries/response areas, marking batches, submissions, mark entries") storage = _clear_exam_storage() cleared, failed = _clear_tables(url, headers, EXAM_CORPUS_TABLES) return {"scope": scope, "exam_storage": storage, "tables_cleared": cleared, "tables_failed": failed} @@ -342,9 +355,12 @@ def reset(scope: str = "all") -> Dict[str, Any]: ) logger.info(" kcar → admin_profiles restored ✓") - # ── 5. Exam subsystem: storage objects (Storage API) + exam tables ─────────── - # (The legacy full reset cleared neither exam tables nor storage — folded in here.) - logger.info("\n[Supabase] Clearing exam subsystem (storage + eb_*/exam_* tables)...") + # ── 5. Exam-marker subsystem: storage objects (Storage API) + all exam tables ── + # This is the same destructive surface as scope="exam-corpus": public corpus/eb_* + # rows, cc.examboards storage, templates/layout/questions/boundaries/response + # areas, marking batches, submissions, and mark entries. (The legacy full reset + # cleared neither exam tables nor storage — folded in here.) + logger.info("\n[Supabase] Clearing entire exam-marker subsystem (public corpus, storage, templates/layout/questions/boundaries/response areas, marking batches, submissions, mark entries)...") exam_storage = _clear_exam_storage() exam_cleared, exam_failed = _clear_tables(url, headers, EXAM_CORPUS_TABLES)