Skip to content

Handoff: SVC-010-attempt-public-idempotency-proof

Scope

  • Dispatch ID: SVC-010
  • Service: attempt-service
  • Task pack: docs/agents/service-tasks/attempt-service.md
  • Next task: SVC-010-attempt-public-idempotency-proof
  • Goal: prove the native attempt workflow and idempotency/result policy before public route promotion.
  • Status: accepted bounded contract slice, not service completion.

Docs Read

  • docs/agents/service-tasks/attempt-service.md
  • docs/agents/handoffs/SVC-010-timeout-retake-result-visibility.md
  • docs/agents/service-agent-next-slice-queue.json
  • docs/agents/service-agent-next-slice-closeout-ledger.json
  • docs/qa/attempt-live-smoke.md
  • docs/qa/attempt-browser-smoke.md
  • docs/api/attempt-service.md

Legacy Evidence Read

  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/attempts/attempts.controller.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/app-data/app-data.exams-attempts.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/app-data/app-data.exam-runtime-core.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/prisma/schema.prisma

Legacy source was read-only evidence. No file under /Users/velikho/Desktop/WORKING/HOCTAPAZ/ was changed.

Behavior Implemented

  • TestStartAttemptHTTP proves the HTTP workflow from trusted runtime start through copied snapshots, answer save, event write, submit/grading, and result read with answer-key redaction.
  • TestStartAttemptHTTPReplaysIdempotencyKeyAfterSubmit proves exact replay returns the original graded attempt with created=false.
  • Usecase tests prove open-attempt reuse, submitted-attempt retake counting, durable idempotency, timeout submission, and IMMEDIATE, AFTER_CLOSE, and MANUAL result visibility.
  • Direct public-compatible start bodies remain rejected unless the gateway or BFF supplies the exam-service decision marker and idempotency context.
  • On 2026-07-13, a disposable local proof ran a trusted runtime-access fixture on 127.0.0.1:8090, in-memory attempt-service on 127.0.0.1:8091, and Gateway with the non-default attempt table on 127.0.0.1:18085. A separately signed student JWT passed list -> start -> detail -> answer save -> event -> submit -> result through the Gateway. The submitted attempt was GRADED and its IMMEDIATE result was visible without answer-key leakage.
  • Replaying the exact X-Correlation-Id after grading returned the same attempt with created=false and GRADED status. Chromium then read the list/detail/events/result routes through the same native Gateway table.
  • Gateway rollback was rehearsed by restarting it with deploy/gateway/routes.json and LEGACY_API_BASE_URL=http://127.0.0.1:59999: native candidates returned 502 through exams/legacy_proxy and attempts/legacy_proxy. Default routes were not changed.
  • Required evidence: attempt route proof, idempotency proof, and live/browser rollback proof are recorded by the bounded local artifacts below. They do not remove the real exam-service or student UI parity gates.

Files Changed

  • docs/qa/attempt-public-idempotency-proof.md
  • docs/agents/handoffs/SVC-010-attempt-public-idempotency-proof.md
  • docs/agents/service-tasks/attempt-service.md
  • docs/qa/attempt-live-smoke.md
  • docs/qa/attempt-browser-smoke.md
  • scripts/test/attempt-live-smoke.sh
  • scripts/test/attempt-browser-smoke.mjs
  • docs/agents/service-agent-next-slice-closeout-ledger.json
  • docs/agents/service-agent-next-slice-closeout-ledger.md
  • docs/agents/service-agent-accepted-handoffs.md
  • docs/agents/service-tasks/attempt-service.md
  • docs/api/attempt-service.md
  • docs/index.md
  • docs/.vitepress/config.ts
  • docs/qa/service-agent-goal-completion-audit.md
  • docs/qa/service-agent-readiness-smoke.md

Tests And Verification

  • GOTOOLCHAIN=go1.25.11 go test ./services/attempt-service/... -count=1
  • make test-attempt-routes
  • ATTEMPT_LIVE_SELF_TEST=1 bash scripts/test/attempt-live-smoke.sh
  • ATTEMPT_BROWSER_SELF_TEST=1 bash scripts/test/attempt-browser-smoke.sh
  • Non-default runtime artifacts: output/qa/attempt-public-idempotency-proof-20260713/final-live/ and output/playwright/attempt-public-idempotency-proof-20260713/.
  • Default rollback artifact: output/qa/attempt-public-idempotency-proof-20260713/rollback-default/.

The focused tests, route guards, self-tests, local Gateway workflow, browser read smoke, exact replay assertion, and default rollback assertion passed.

Route State

  • Default /api/exams/*/start, /api/student/attempts, and /api/attempts* remain legacy-proxied.
  • Native attempt routes remain non-default rehearsals.
  • Route state: public attempt route promotion requires route, live, browser, idempotency, and rollback proof; it remains an explicit review decision and the default table still routes attempt surfaces to legacy.
  • Rollback uses GATEWAY_ROUTE_TABLE=deploy/gateway/routes.json; rerun make test-attempt-routes and the relevant smoke checks.

Risks / Blockers

  • The runtime-access response came from a disposable fixture, not a seeded running exam-service instance.
  • Browser evidence uses the Gateway health page as a same-origin shell and verifies fetches/headers; it is not a student exam-room UI parity test.
  • Attempt-service is not complete migration proof; legacy parity and default route promotion remain open.
  • Future adapters must preserve exam-service ownership of access decisions and never hydrate attempts from current question-service rows.

Next Step

Seed a published exam through a running exam-service and exercise the actual student exam-room frontend before proposing any default route promotion.

Go-platform documentation is generated from repository Markdown.