Appearance
Exam Attempt Public Proof
Status: accepted bounded local contract proof; no default-route promotion.
This proof closes the SVC-009-exam-attempt-public-proof contract slice while keeping attempt creation and public exam/start promotion gated.
Evidence
| Requirement | Evidence | Result |
|---|---|---|
| Exam-attempt contract proof | A real in-memory exam-service created and published a one-question snapshot. Gateway-authenticated runtime-access used the configured verifier fixture, verified the password, and returned an allowed exam-service decision for the trusted attempt handoff; student calls without the internal Gateway token are rejected at both the Exam resolver and Attempt start hop before snapshot state is exposed or written. | Passed locally |
| Profile ownership guard | Caller-supplied studentInfo is rejected before the runtime decision and cannot be copied into attempt snapshots or analytics. A future profile projection must use a trusted profile-service integration. | Passed locally |
| Sensitive student projection | The proof found isCorrect in public start/replay responses. attempt-service now projects Start/replay through the student view; focused HTTP regression covers option correctness, answer keys, and explanations before result visibility. | Passed after fix |
| Live/browser proof | Candidate Gateway at 127.0.0.1:18085 passed list/start/detail/save/event/submit/result plus post-grade replay. Chromium fetched read routes from a same-origin /healthz shell and captured route headers. It was not a student UI journey. | Passed local API/browser shell; UI gate remains open |
| Rollback notes | The unchanged default deploy/gateway/routes.json with LEGACY_API_BASE_URL=http://127.0.0.1:59999 returned 502 with exams/legacy_proxy for start and attempts/legacy_proxy for result. | Passed |
Artifacts:
output/qa/exam-attempt-public-proof-20260713/authoring/output/qa/exam-attempt-public-proof-20260713/gateway-live/output/qa/exam-attempt-public-proof-20260713/rollback-default/output/playwright/exam-attempt-public-proof-20260713/
Ownership Boundary
exam-serviceowns exam authoring, publish snapshots, access-link policy, assignments, and runtime access decisions.- Question content is stored by value in exam snapshots; exam-service never joins question-service storage.
attempt-serviceowns attempt creation, answers, grading, and result state.- Classroom/IAM membership checks use service contracts or verifiers; exam- service does not read those databases directly.
- Access-link codes and password hashes are never exposed in runtime responses.
- Before result visibility, attempt question snapshots hide answer keys, scoring metadata, source snapshots, explanations, and option
isCorrect. Post-submit answer scoring follows the exam result-visibility policy.
Verification
bash
GOTOOLCHAIN=go1.25.11 go test ./services/exam-service/... -count=1
GOTOOLCHAIN=go1.25.11 go test ./services/exam-service/internal/usecase ./services/exam-service/internal/http -run 'TestExamRuntimeAccess|TestRuntimeAccessRouteReturnsAttemptStartInput' -count=1 -v
make test-exam-authoring-routes
make test-attempt-routes
GOTOOLCHAIN=go1.25.11 go test ./services/attempt-service/internal/http -run TestStartAttemptHTTP -count=1 -v
GOTOOLCHAIN=go1.25.11 go test ./services/attempt-service/internal/usecase -count=1All listed commands passed for this bounded slice.
Live/Browser Gate
The local live/browser proof is claimed only at its actual scope: real local services, a verifier fixture, and Chromium API fetches. Any public promotion still requires seeded deployed data, real IAM/classroom decisions, Gateway route headers, and an actual student frontend journey with artifacts under output/playwright/.
Route State And Rollback
- Default
/api/exams*,/api/attempts*, and fallback routes remainlegacy_proxy. - Native exam authoring/runtime-access contracts remain internal or non-default rehearsals.
- Rollback is
GATEWAY_ROUTE_TABLE=deploy/gateway/routes.json; rerunmake test-exam-authoring-routesandmake test-attempt-routesafter switching back. - No public attempt-start route promotion is part of this handoff.