43 Commits

Author SHA1 Message Date
CC Worker
e83873e822 fix(exam): dedupe all AI auto-map rows by id before insert
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
B1-4 live-route validation: continuation bands re-emit the same stable AI id for
response_areas/boundaries/layout (not just questions), causing duplicate-pkey insert
failures. Add _dedupe_rows_by_id applied to all four tables in _refresh_ai_rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 18:02:51 +00:00
150b915282 [verified] fix exam auto-map duplicate continued parts
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
(cherry picked from commit 31c51cb7aa33d7f2e1102cea4ffabfefee259faa)
2026-06-08 17:47:56 +00:00
76e11b0b06 feat(docling): B1-2 AQA label normalization + missing-.1 inference + MCQ gap (salvaged)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
(cherry picked from commit a707a5afd92c5c9fb042486229d0ef11549a3f53)
2026-06-08 04:03:17 +00:00
52d1ece212 [verified] generalize B1 response regions and marks gap fill
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-08 04:49:21 +01:00
CC Worker
34fc7edd68 [verified] add exam-board signed URL endpoint
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
(cherry picked from commit c65d18ca6badab193469d88e8e8b32279cca8f98)
2026-06-08 01:51:55 +00:00
c69451fba2 [verified] add upload size and MIME guards
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
(cherry picked from commit f5e05376f637f55b73e474cac8199529682ca398)
2026-06-08 01:18:39 +00:00
e98fed661f [verified] fix files list owner scoping
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-08 02:08:38 +01:00
7f7e843563 [verified] add user subset reset scope
(cherry picked from commit e1e3ec96a2d314d39e35ce2c34f6f67df1c2f182)
2026-06-08 00:25:46 +00:00
7819e6e346 fix(seed): unseed user-subset storage objects
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
(cherry picked from commit 9328ec2e062d039c0bcfabb086ce0693fe1ebe50)
2026-06-08 00:13:40 +00:00
CC Worker
2ac892c291 Merge S5-2 auto-map endpoint + upsert mapper
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-07 19:50:30 +00:00
2678d0be42 [verified] add exam template auto-map endpoint 2026-06-07 20:48:08 +01:00
CC Worker
4dd6f0f674 Merge S5-5 centralized part-box synthesis (template.py)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-07 19:39:51 +00:00
621d283ceb S5-5: centralized part-box synthesis (band-y x content-margins)
Add synthesize_part_box() as the single authoritative S5 part-box projection
(T3 swap point): content-margin x-extent x part-band y-extent, BOTTOMLEFT
coords; label_box retained as a separate anchor. build() attaches box per part.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 20:38:25 +01:00
CC Worker
2ebbfc1cf4 Merge S5-6 schema layout/provenance surface (API)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-07 19:21:35 +00:00
CC Worker
71ddceb19e Merge S5-4 regions.py onto docling package (S5-1)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-07 19:10:48 +00:00
43f0a9104c [verified] round-trip S5 exam layout fields 2026-06-07 20:05:47 +01:00
5938613893 [verified] add docling auto-map package wrapper
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-07 20:03:06 +01:00
0b1496fff5 feat(docling): detect response regions with OpenCV 2026-06-07 19:57:22 +01:00
28aafaa60f feat(exam): add metadata patch for templates 2026-06-07 00:33:01 +01:00
CC Worker
115ecd2351 test(exam): mock service-role files read in source-pdf download test (S4-8.1)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
The download path now resolves the files row via SupabaseServiceRoleClient (to
sidestep the cabinet_memberships RLS recursion); the test must mock it like the
upload test does. Test-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 22:56:45 +00:00
CC Worker
c58df6715c feat(exam): template source PDF at create + GET /templates/{id}/source-pdf (S4-8.1)
Recovered from cc-worker WIP that was left uncommitted in the dev-centre clone
(card t_0055b89b). Multipart source_pdf upload at create -> source_file_id;
source-pdf download endpoint resolves from exam_id (catalogue) or source_file_id.
NOT yet human-reviewed/merged; preserving + verifying so it isn't clobbered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 22:29:32 +00:00
CC Worker
9c1aee28e2 feat(exam): persist S4-9 region kinds + Part geometry; keep metadata out of graph
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
Backend follow-on to migration 73:
- schemas: ResponseAreaPayload.kind extended to response|context|question_number|
  mark_area|reference|furniture + context_type; QuestionPayload gains bounds+page.
- PUT serialization persists Part bounds/page and region context_type.
- Neo4j projection only emits Region nodes for response/context regions; the
  metadata kinds (question_number/mark_area/reference/furniture) are physical-layer
  only and stay out of cc.public.exams.
- Unit test: new kinds + Part geometry + context_type round-trip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 21:14:20 +00:00
CC Worker
93972a62f7 fix: revert explicit apikey header (caused Kong duplicate-apikey 401)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
The previous commit added apikey to _create_base_client headers, but supabase-py
already sets apikey from the key arg → two apikey headers → Kong rejected every
as-user call with 401 'Duplicate API key found' (exam API 502'd on auth). Revert
to Authorization-only; fix the two header unit tests to assert the real contract
(apikey via the key arg; options.headers carries only the user Authorization).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:30:36 +00:00
CC Worker
f3da9f3b59 fix: explicit apikey header + resilient dev-stack seed-count baselines
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
- client.py: set apikey explicitly in _create_base_client headers (Kong needs it
  on every request; for per-user clients apikey stays anon while Authorization
  carries the user JWT). Fixes the 2 stale header unit tests that asserted apikey
  in options.headers, and is robust against supabase-py default-header changes.
- test_dev_stack: exact == seed counts → >= baselines. The greenfield seed sets a
  floor; additive exam-marker fixtures (S4-4 cohort) legitimately push live .94
  counts above the old snapshot. >= still catches a broken/missing seed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:25:39 +00:00
CC Worker
e269e67f27 fix(exam): block destructive template PUT once marks recorded (review #1)
PUT full-replace deletes exam_questions, and mark_entries.question_id cascades
ON DELETE — so re-saving the setup canvas after marking began would silently
wipe recorded marks. Guard: 409 if any mark_entry exists for the template's
batches. Mark-scheme edits (PATCH /questions/{id}) are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:15:35 +00:00
CC Worker
77bb0766ff feat(exam): Neo4j projection on template save + neo4j-sync (S4-7)
modules/database/services/exam_projection.py projects a saved template into
cc.public.exams: ExamPaper -> Question/Part -> Region + Part-[:ASSESSES]->
SpecPoint, joined by shared UUIDs (exam_questions.id, exam_response_areas.id,
exam_code, spec_code). Full re-sync per exam_code (idempotent). Reads via
service role + writes via system Neo4j driver (R3.5.1 documented graph-writer).

Wiring (R3.5.4/R5.3):
- PUT /templates/{id} enqueues project_template_safe via BackgroundTasks
  (swallows failures so a graph hiccup never fails the canvas save).
- POST /templates/{id}/neo4j-sync — manual trigger, as-user auth + owner check,
  runs synchronously and returns projection counts.

Unit tests: projection scheduled on PUT; neo4j-sync owner/403/404.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:02:18 +00:00
CC Worker
62234dbbcb fix(exam): blank total only for absent AND unmarked; flip status on mark
A roster student starts 'absent' and a direct mark would otherwise still show a
blank total. Now total is blank only when absent with no marks; recording a mark
advances the submission out of absent/unmatched to 'marking'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 18:43:09 +00:00
CC Worker
a1d297ac30 test(exam): replace StorageAdmin with fake class in scan tests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 18:41:23 +00:00
CC Worker
5ad9c01cde feat(exam): batches, scans, marks, results, CSV (S4-6)
Adds routers/exam/batches.py (mounted alongside templates under /api/exam):
- POST/GET /batches — batch creation seeds the cohort from class_students AS
  THE USER (cs_read requires caller teaches/admins the class); each active
  enrollee becomes a student_submissions row (status='absent') so no student
  is ever dropped from results (A7). Display names denormalised via a
  documented service-role profiles read (deny-all as-user, E4).
- GET /batches/{id}/queue — submissions + per-submission mark counts + progress.
- GET /batches/{id}/results + /csv — every roster student incl. absent (blank
  marks/total); CSV row always present (A7 baked into the contract).
- PUT /marks/{id} — upsert; batch_id derived server-side from the submission
  (client never supplies the RLS scoping key).
- POST /batches/{id}/scans — E3 guards: MIME check, hard size ceiling (chunked
  read), %PDF magic-byte sniff; owner-only; stores via service-role storage;
  manual/ordered matching (QR-decode is a follow-on, no QR fixtures yet).

Unit tests cover batch/roster-seed/list, queue, results+CSV A7, mark upsert
round-trip, and all scan guards + owner check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 18:40:10 +00:00
CC Worker
96f9fb2446 test(exam): accept 401 or 403 for unauthenticated request
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 17:50:55 +00:00
CC Worker
f52c3267ca feat(exam): /api/exam template CRUD router (as-user RLS, E1 fix)
S4-5: new routers/exam/ package mounted at /api/exam (R5.1/E5, not under
/database/). Template CRUD with hybrid persistence (R5.2):

- POST/GET/GET{id}/PUT{id}/DELETE{id} /templates + PATCH /questions/{qid}
- Calls Supabase AS THE USER via SupabaseAnonClient.for_user (E1 fix), so the
  RLS in 72-exam-marker.sql is enforced; no service-role for user-facing ops.
- Institute resolved/validated via the user_institute_ids() SECURITY DEFINER
  RPC (institute_memberships is deny-all as-user per E4); client-supplied
  institute_id is validated, never trusted (R5.5).
- Ownership pre-checked before writes (E2); out-of-scope ids read back as 404
  under RLS (IDOR-safe). Soft-delete archives, never hard-deletes.
- PUT full-replace preserves client UUIDs as Neo4j join keys (spec §2).
- eb_exams.exam_code denormalised via a documented service-role catalogue
  lookup (eb_exams is shared reference data, deny-all as-user per E4).

Unit tests cover auth, CRUD, ownership/IDOR, institute validation, soft-delete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 17:49:58 +00:00
abc90fa1b6 test: align Supabase user client header expectation
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-05-28 19:19:05 +01:00
39ad1818ae Merge branch agent/p0-correctness-security
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
# Conflicts:
#	modules/database/supabase/utils/client.py
2026-05-28 19:17:22 +01:00
1738af0e3d Merge branch agent/tlsync-token-t_a69128a1 (TLSync JWT token endpoint)
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-05-28 18:04:25 +01:00
7808a0ae56 Add TLSync token endpoint 2026-05-28 17:55:37 +01:00
88a3193e01 Keep platform bootstrap permissions additive 2026-05-28 15:10:54 +01:00
4f6634e088 Implement Supabase-first me bootstrap 2026-05-28 14:14:35 +01:00
54760083b5 fix: tighten API P0 auth and route handling 2026-05-28 12:42:42 +01:00
310e273aa5 feat: expose API runtime identity in health 2026-05-28 11:32:04 +01:00
7fede4d082 fix: run API dev stack in dev mode 2026-05-28 10:15:33 +01:00
b452c9f593 test: add dev stack integration checks
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
2026-05-27 23:24:28 +01:00
3758c7572a latest 2025-11-14 14:47:19 +00:00
e0c489f625 Initial commit 2025-07-11 13:52:19 +00:00