docs(reset): clarify exam-corpus scope
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
kcar 2026-06-08 00:57:57 +01:00
parent 25d02aedeb
commit 5da108df13
2 changed files with 34 additions and 14 deletions

View File

@ -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"):

View File

@ -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)