Skip to content

Task Breakdown

Phase: 1 Architecture Plan Status: backlog before Go implementation

Phase 0 Audit Tasks

IDTaskOutputStatus
P0-001Inventory repo structure, backend entrypoints, runtime rolescurrent-system-audit.mdDone
P0-002Extract grouped legacy API route maplegacy-api-map.mdDone
P0-003Inventory Prisma models/enums and ownership bucketslegacy-database-inventory.mdDone
P0-004Capture auth, tenant, import, question, exam, attempt ruleslegacy-business-rules.mdDone
P0-005Draft legacy DB ownership maplegacy-database-map.mdDone

Phase 1 Planning Tasks

IDTaskOutputStatus
P1-001Define target Go service topologytarget-go-microservices.mdDone
P1-002Define service boundariesservice-boundaries.mdDone
P1-003Define DB-per-service strategydatabase-per-service-strategy.mdDone
P1-004Define service database implementation rulesdatabase-strategy.mdDone
P1-005Define gateway/API contract strategyapi-contract-strategy.mdDone
P1-006Define migration phasesmigration-plan.mdDone
P1-007Define migration/data validation/rollback docsdocs/migration/*Done
P1-008Define agent orchestration and handoff formatdocs/agents/*Done
P1-009Maintain decision log and risk registerdecision-log.md, risk-register.mdDone

Phase 2 Platform Skeleton Tasks

These are the first implementation tasks after docs are accepted.

IDTaskService/AreaStatusDefinition Of Done
P2-001Initialize Go workspace/module under go-platform/platformDonego test ./... passes with no legacy file changes.
P2-002Add shared config packageplatformDoneEnv loading and service defaults exist. Production secret guards remain for domain services.
P2-003Add shared logging/request context packageplatformDoneJSON logs include request and correlation IDs.
P2-004Add shared error/envelope packageplatformDoneGateway can map internal errors to JSON responses.
P2-005Add health/ready/metrics helpersplatformDoneEvery service skeleton exposes /healthz, /readyz, /metrics.
P2-006Build proxy-only api-gatewayapi-gatewayDone/api/* forwards to legacy; /api/health/* compatibility present.
P2-007Add gateway route state tableapi-gatewayDoneRoutes can be marked legacy_proxy, shadow_read, native_read, native_write.
P2-008Add Docker Compose for Go platform dependenciesplatformDoneCompose syntax validates for gateway, sample service, Postgres, Redis, MinIO, and NATS.
P2-009Add service skeletonsall servicesDoneEach target service has cmd, health, config, logger.
P2-010Add OpenAPI generation placeholderplatformDonePlaceholder contracts exist for gateway and all target services.

Phase 3 First Route Tasks

IDTaskService/AreaDefinition Of Done
P3-001Capture legacy OpenAPI/route snapshotapi-gatewayDone. Static NestJS controller route snapshot is stored under go-platform/docs/contracts/legacy/ as JSON plus Markdown, covering all 430 legacy controller routes across 36 controller files with method/path/handler/source evidence, global /api prefix, /api/v1 compatibility alias, grouped counts, and a reproducible make test-legacy-route-snapshot check. Full Nest Swagger export can still be added later for request/response schemas, but route migration has an immutable legacy path inventory.
P3-002Implement document-service media asset read paritydocument-servicePartial. Metadata create/list/get, legacy-shaped /v1/storage/presigned-upload, /v1/storage/media-assets, content streaming with `variant=trim
P3-003Implement question type list parityquestion-bank-servicePartial. Native GET /v1/question-types returns the legacy success envelope, active core system definitions, actor-scoped custom definitions, summary/status/q filters, OpenAPI, tests, service-owned question_type_definitions migration, pgx/memory stores, and gateway shadow/native read examples. P3-012 adds opt-in browser-route evidence tooling for /teacher/questions/types. Full default cutover remains pending on executing live browser parity against a running gateway/native service and approving default route promotion.
P3-004Implement shadow-read diff runnerapi-gatewayDone. Gateway returns legacy response, calls native target for safe read methods, and logs status match/diff without affecting response.
P3-005Implement DOCX import job status read modeldocx-import-servicePartial. Native /v1/import/docx/teacher-library, /v1/import/docx/jobs/events, and /v1/import/docx/jobs/{id}/status now project service-owned DOCX jobs into legacy-shaped summary/status/SSE fields for stored jobs. P3-007 adds non-default gateway adapter examples, and P3-008 adds opt-in gateway auth/header injection for selected native routes. P4-001 adds in-process live SSE fanout, P4-008 adds Redis multi-process fanout, P4-009 adds native queue snapshots, P4-010 adds durable payload refs/recovery, P4-026 wires the queued payload spool to persistent offline K8s/Helm storage, P4-027 adds a read-only BullMQ snapshot bridge for legacy queue depth/position during cutover, P4-028 adds opt-in live-smoke tooling for the status route plus bridge queue fields, P4-029 adds browser-route smoke tooling for /teacher/exams/library, and P4-030 adds static import-status route coverage. Default gateway cutover and executing live browser verification remain pending.
P3-006Add method-aware gateway routesapi-gatewayDone. Gateway route entries support methods, exact, and suffix_segments, so read-only routes such as GET /api/questions and GET /api/questions/:id can be shadowed independently while write methods and nested subroutes remain on legacy. Rollback is deleting the specific route entry or setting it back to legacy_proxy.
P3-007Add DOCX import status/history gateway adapter examplesapi-gateway, docx-import-serviceDone. Added non-default Compose/localhost route-table examples and gateway regression coverage for GET /api/exam-import/teacher-library, GET /api/exam-import/algorithm-jobs/events, GET /api/exam-import/jobs/:id/status, and GET /api/imports/:jobId/status rewriting to native P3-005 endpoints while sibling import routes and the default route table stay legacy.
P3-008Add gateway auth header adapter foundationapi-gatewayDone. Route entries can opt into require_auth, required_roles, and require_organization; the gateway verifies legacy-shaped access tokens from Authorization/cookie, enforces route roles, derives organization context, and forwards native identity/organization headers while default routes stay legacy.
P3-009Add question type GET native route rehearsalapi-gateway, question-bank-serviceDone. Added non-default GET-only exact shadow/native route examples and static coverage for /api/question-types read rehearsal, while keeping POST/PATCH/DELETE and nested question-type routes on the broad legacy fallback. Default route table remains legacy until native write parity and browser cutover evidence are available. Verified by route JSON parse, shell syntax, make test-question-types-routes, focused gateway tests, full Go tests, go vet, and no legacy diff.
P3-010Add native question type write foundationquestion-bank-service, api-gatewayDone. Added native POST /v1/question-types, PATCH /v1/question-types/{id}, DELETE /v1/question-types/{id}, PATCH /v1/question-types/bulk-status, and POST /v1/question-types/bulk-delete; preserved legacy validation, actor-scoped custom conflicts, system-type admin guard, unused custom hard-delete vs archive behavior, OpenAPI/docs, service-owned actor-scope migration, focused service/gateway tests, and non-default native write route examples. Default /api/question-types remains legacy until browser parity and route promotion are proven. Verified by focused question-bank tests, focused gateway tests, route coverage, OpenAPI parse/mirror diff, full Go tests, go vet, diff check, and no legacy diff.
P3-011Add question type write live gateway smokescripts, docsDone. Added scripts/test/question-types-live-smoke.sh and make test-question-types-live as an opt-in live smoke for the non-default native question-type write route. The script verifies /v1/routes, creates a custom type through /api/question-types, updates it, bulk-archives it, hard-deletes it, confirms nested GET manager paths still route to legacy, requires explicit auth/org context, and includes a hermetic self-test path. Live write execution remains pending on a running gateway with native route table plus real auth. Verified by shell syntax, self-test, route coverage, focused gateway tests, full Go tests, go vet, diff check, and no legacy diff.
P3-012Add question type browser-route smokescripts, docsDone. Added scripts/test/question-types-browser-smoke.sh, Playwright runner, QA doc, and make test-question-types-browser as an opt-in browser smoke for the real /teacher/questions/types page. The smoke seeds browser auth/org state, requires the web app to point NEXT_PUBLIC_API_URL at the gateway, verifies browser-observed GET /api/question-types includes question-types-read/native_read gateway headers, checks core question-type codes, writes artifacts, and leaves the default route table unchanged. Verified by self-test, script syntax, route coverage, full Go tests, go vet, diff check, and no legacy diff.
P3-013Add storage media real-sample parity smokescripts, docsDone. Added scripts/test/storage-media-parity-smoke.sh, Python runner, QA doc, and make test-storage-media-parity as an opt-in read-only smoke for P3-002. The smoke fetches legacy media detail/content, compares native document-service or gateway content bytes by SHA-256, supports original, trim, and formula variants when native metadata exists, supports storage-key object reads before backfill, writes artifacts, and leaves default routing unchanged. Verified by self-test, script syntax, full Go tests, go vet, diff check, and no legacy diff.

Phase 4 High-Risk Domain Tasks

IDTaskService/AreaDefinition Of Done
P4-001Model DOCX import job state and eventsdocx-import-servicePartial. Job/status/event endpoints, in-memory repository, pgx repository, tests, Postgres schema, stored-job SSE replay, in-process live event fanout, Redis pub/sub multi-process fanout, native bounded worker queue snapshots, read-only BullMQ legacy queue snapshot bridge, durable queued upload payload refs/recovery, periodic SSE heartbeat, logging middleware flush support, offline K8s/Helm persistent payload spool wiring, BullMQ status live-smoke tooling, and import-library browser smoke tooling exist. Executing browser cutover verification remains pending; shared native/legacy worker execution remains deferred unless needed for cutover.
P4-002Wrap existing Go Formula DOCX endpointdocx-import-serviceDone. Current docx-import-service wraps the existing Go Formula DOCX runtime through /v1/import/docx/simple, sends legacy-compatible multipart flags, maps parser latency, stats, question fields, warnings, answer hints, annotated fallback rows, media references, renderable-image counts, and warning-safe review signals into native QAS output. Later P4/P5 slices added internal runtime wiring, materialization, corpus checks, warning parity, and benchmark coverage. Default public DOCX routes remain legacy until browser cutover evidence is complete. Verified by focused Go Formula parser tests, DOCX import service tests, runtime/corpus/warning coverage scripts, full Go tests, go vet, and no legacy diff.
P4-003Preserve import review save/reloaddocx-import-serviceManual type overrides survive save/reload in browser verification.
P4-004Implement import approval sagadocx-import, question-bank, examPartial. Native internal approval boundary now approves completed DOCX jobs into question-bank and optional draft exam snapshots, and a non-default gateway adapter example now covers legacy-compatible POST /api/exam-import/jobs/:id/approve with opt-in gateway auth/header injection. Default public cutover, browser review verification, and full legacy taxonomy/folder/link parity remain pending.
P4-005Implement attempt save/submit parityattempt-serviceDone. Native POST /v1/attempts/{attemptId}/answers preserves legacy attempt-owner checks, client/server answer version conflict behavior, and SAVE_ANSWER events. Native POST /v1/attempts/{attemptId}/submit grades from attempt-owned snapshots, updates answer scores plus attempt totals, records SUBMIT/TIMEOUT, and stores answer/grading state in the attempt-service database. Public /api/attempts/* remains legacy until adapter, browser parity, and default route cutover evidence are complete. Verified by focused attempt tests, HTTP tests, full Go tests, go vet, OpenAPI mirror checks, and no legacy diff.
P4-006Add native import approval orchestrator boundarydocx-import-serviceDone. docx-import-service accepts approval for a completed import job, stores idempotency through import events, calls question-bank-service POST /v1/questions/import-docx-output, and optionally creates/updates an exam draft through exam-service without joining other service databases. Verified by focused approval tests, full Go tests/vet, OpenAPI/YAML parse, compose config, K8s/Helm coverage, and no legacy diff.
P4-007Add import approval gateway adapter exampleapi-gateway, docx-import-serviceDone. Added route-table suffix guard, non-default Compose/localhost examples with opt-in auth/header injection, and gateway regression coverage for POST /api/exam-import/jobs/:id/approve rewriting to POST /v1/import/docx/jobs/{id}/approve without capturing sibling job actions. Default /api/exam-import* stays legacy until browser review verification and full approval parity are proven.
P4-008Add DOCX import Redis multi-process fanoutdocx-import-serviceDone. Added Redis-backed event bus around P4-001 in-process fanout, runtime REDIS_URL setup with in-process fallback, self-echo suppression, redacted Redis payloads, deploy/env docs, and fake-broker tests so native SSE subscribers can receive job.updated events across service processes. Default routes remain legacy and real worker queue position parity remains pending.
P4-009Add native DOCX import queue snapshot foundationdocx-import-serviceDone. Added a bounded in-process native worker queue, async POST /v1/import/docx/qas/jobs, job.queued lifecycle events, legacy-shaped job.queue snapshots for waiting/active native import jobs, worker concurrency env/deploy docs, and queue snapshot tests. P4-027 adds a read-only BullMQ fallback snapshot bridge for jobs still visible only in the legacy queue. Browser verification and public cutover remain pending.
P4-010Add durable DOCX import payload spool and restart recoverydocx-import-serviceDone. Uploaded DOCX payloads are stored outside queue memory with opaque job payload_refs, PENDING/PROCESSING jobs recover on startup when the payload exists, missing payload refs fail explicitly with DOCX_IMPORT_PAYLOAD_MISSING, DOCX_IMPORT_PAYLOAD_DIR is documented for Compose/K8s/Helm, and default routes remain legacy. P4-026 adds persistent offline K8s/Helm storage for the payload spool before public cutover.
P4-011Add DOCX Fast legacy create-job adapter foundationdocument-service, docx-import-service, api-gatewayDone. Preserves legacy POST /api/exam-import/docx-fast-jobs JSON shape by reading uploaded DOCX bytes from questionStorageKey through document-service, enqueueing the native DOCX import job without direct storage/database coupling, returning a legacy success envelope, and adding non-default authenticated gateway route examples while default routes remain legacy. Browser cutover verification plus temp asset content parity remain pending.
P4-012Add DOCX Fast create idempotency paritydocx-import-serviceDone. Preserves legacy 15-minute idempotency behavior for POST /api/exam-import/docx-fast-jobs by storing idempotencyKey plus questionStorageKey, returning the recent matching native job before re-fetching storage or enqueueing, and keeping default routes legacy. Adds scoped service-owned migration/index, OpenAPI docs, and regression coverage. Verified by focused/full Go tests, vet, YAML parse, compose config, Helm lint/template, and no legacy diff.
P4-013Add DOCX Fast auto-approval trigger foundationdocx-import-serviceDone. Preserves the legacy autoApproveToQuestionBank path for native DOCX Fast jobs by storing request metadata, triggering native QUESTION_BANK approval after successful parse, recording auto_approval.completed/auto_approval.failed events, and keeping default routes legacy. Adds service-owned metadata migration, OpenAPI docs, and regression coverage. Verified by focused/full Go tests, vet, YAML parse, compose config, Helm lint/template, and no legacy diff.
P4-014Add DOCX Fast materialized temp-draft read adapterdocx-import-service, api-gatewayDone. Preserves the legacy materialized temp-draft read shape for native completed DOCX Fast jobs by returning a legacy success envelope with parseResult and empty temp assets, while temp asset content stays legacy. Adds non-default gateway routes, OpenAPI/docs, and regression coverage. Verified by focused/full Go tests, vet, YAML/JSON parse, compose config, Helm lint/template, and no legacy diff.
P4-015Add DOCX Fast reprocess adapter foundationdocx-import-service, api-gatewayDone. Preserves the legacy POST /api/exam-import/docx-fast-jobs/{id}/reprocess path for native DOCX Fast jobs by re-reading the stored source DOCX, requeueing the same native job id, clearing previous parse output, returning the legacy success envelope, and keeping default routes legacy. Adds non-default gateway routes, OpenAPI/docs, and regression coverage. Verified by focused/full Go tests, vet, YAML/JSON parse, compose config, Helm lint/template, and no legacy diff.
P4-016Add DOCX Fast materialized asset content adapterdocx-import-service, api-gatewayDone. Preserves the legacy temp asset content guard for native materialized jobs by serving only media assets referenced by the completed native job parse result through document-service, keeping the materialized temp-draft payload assets: [], and adding non-default gateway route examples. Verified by focused/full Go tests, vet, YAML/JSON parse, compose config, Helm lint/template, and no legacy diff.
P4-017Add Go Formula DOCX internal runtime wiringdeploy, docx-import-serviceDone. Keeps apps/go-formula-docx source read-only while building and deploying it as an internal parser runtime for local Compose, offline K8s, and Helm. Wires docx-import-service to http://go-formula-docx:8080, adds runtime image coverage, and keeps the default public gateway routes legacy until browser parity is verified. Verified by runtime coverage, compose config, K8s service coverage, Helm render coverage, shell/YAML parse, full Go tests/vet, and no legacy diff.
P4-018Add import review save/reload backend foundationdocx-import-service, api-gatewayDone. Preserves reviewed parse payloads, including manual question-type override metadata, in service-owned storage through a native PATCH /v1/import/docx/jobs/{id}/review endpoint and non-default gateway route example. Materialized DOCX Fast temp-draft reads prefer the saved reviewed payload for reload parity. Source-text reparse, temp-draft token materialization, default public cutover, and real browser verification remain under P4-003. Verified by focused review-save and gateway tests, full Go tests/vet, OpenAPI/route JSON parse, compose config, K8s migration coverage, Helm render coverage, and no legacy diff.
P4-019Add import job detail reload adapterdocx-import-service, api-gatewayDone. Returns legacy-compatible job detail fields, including reviewed parseResultJson, from native GET /v1/import/docx/jobs/{id} and adds a non-default gateway route for GET /api/exam-import/jobs/{id}. Sibling paths such as /status, /review, and /approve stay legacy unless separately routed. Default public cutover and browser save/reload proof remain under P4-003. Verified by focused detail reload and gateway tests, full Go tests/vet, OpenAPI/route JSON parse, compose config, Helm render coverage, and no legacy diff.
P4-020Add combined import review save/detail route smokeapi-gateway, scriptsDone. Combines the P4-018 review-save and P4-019 detail-reload gateway carve-outs into one non-default route table so save then reload can be smoke-tested through the gateway before any browser/default cutover. Status, approve, stop, nested review, and unrelated import siblings stay legacy unless explicitly routed. Verified by JSON parse, static route coverage script, focused gateway regression test, full gateway package tests, full Go tests, go vet, shell syntax check, and no legacy diff.
P4-021Add live import review save/detail smoke scriptscripts, docsDone. Adds an opt-in live gateway smoke that fetches a real import job detail, saves a reviewed parse payload through PATCH /api/exam-import/jobs/{id}/review, reloads GET /api/exam-import/jobs/{id}, and verifies manual question-type review markers. The script requires explicit job/auth inputs, defaults to restoring the original parse payload, supports artifacts and custom payloads, and does not claim browser parity or default cutover. Verified by self-test, shell syntax checks, route coverage, Makefile smoke targets, full Go tests, go vet, and no legacy diff.
P4-022Preserve reviewed sourceText on native review reloaddocx-import-serviceDone. When PATCH /v1/import/docx/jobs/{id}/review receives a reviewed parseResult plus sourceText, native save response, detail reload, and DOCX Fast materialized temp-draft reload expose that source text as parseResultJson.sourceText without mutating the stored raw reviewed payload shape. SourceText-only parser reprocess and non-materialized temp-draft token asset materialization remain separate P4-003 gaps. Verified by focused HTTP test, docx-import HTTP package test, full Go tests, go vet, and no legacy diff.
P4-023Add sourceText-only review reparse baselinedocx-import-serviceDone. Adds a native baseline for PATCH /v1/import/docx/jobs/{id}/review requests that include sourceText but no parseResult, parsing simple Câu n source text with A/B/C/D options into a legacy-shaped parseResultJson and explicit SOURCE_TEXT_REPARSE_BASELINE warning. This is a compatibility foundation, not full legacy parseAlgorithmExamImport parity. Verified by focused usecase/HTTP tests, full Go tests, go vet, and no legacy diff.
P4-024Accept native DOCX Fast materialized temp-draft review tokendocx-import-serviceDone. Exposes native materialized DOCX Fast temp-draft metadata on job detail and accepts the native materialized-{jobId} token on PATCH /v1/import/docx/jobs/{id}/review so review save does not fail when the editor includes a materialized token. This does not implement the legacy non-materialized temp-draft file store or client asset upload materialization. Verified by focused usecase/HTTP tests, full Go tests, go vet, OpenAPI YAML parse, and no legacy diff.
P4-025Add import review browser-route smokescripts, docsDone. Adds an opt-in Playwright browser smoke that opens the real import editor route, seeds existing auth/organization state, verifies gateway GET detail and PATCH review routes hit native carve-outs, reloads the editor, and checks manual review markers survive in browser-observed responses. This is browser evidence tooling, not default public cutover. Verified by self-test, route coverage, script syntax checks, full Go tests, go vet, and no legacy diff.
P4-026Add DOCX import payload PVC deployment wiringdeploy, scripts, docsDone. Added a docx-import-payloads PersistentVolumeClaim to the static offline K8s manifest, switched the docx-import-service payload spool mount from emptyDir to the PVC, added Helm service-level persistence rendering with the same claim and 5Gi request, and added make test-docx-payload-persistence coverage to reject ephemeral payload storage. Verified by payload persistence coverage, Helm render coverage, K8s service coverage, Compose config, full Go tests, go vet, diff check, and no legacy diff.
P4-027Add DOCX import BullMQ snapshot bridgedocx-import-service, deploy, scriptsDone. Added an opt-in read-only BullMQ snapshot bridge for legacy exam-import-algorithm queue state. When enabled with DOCX_IMPORT_BULLMQ_BRIDGE_ENABLED=1, native status/list summaries fall back from the in-process native queue to BullMQ Redis keys and preserve legacy waiting/active/delayed/prioritized/waitingChildren/failed/totalPending/waitingPosition/jobsAhead/workerConcurrency fields for matching data.jobId. The bridge never enqueues, removes, retries, or claims BullMQ jobs. Verified by focused usecase/http tests, bridge config coverage, Helm/K8s/Compose coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-028Add DOCX import BullMQ status live smokescripts, docsDone. Added scripts/test/docx-import-bullmq-status-smoke.sh, make test-docx-bullmq-status, and QA/runbook docs for opt-in live verification of the non-default import status route table plus BullMQ queue fields on GET /api/exam-import/teacher-library?q=<jobId>. The smoke is read-only, supports direct native service mode, includes a hermetic self-test, and does not claim default route cutover. Verified by script syntax, self-test, diff check, and no legacy diff.
P4-029Add DOCX import library browser-route smokescripts, docsDone. Added scripts/test/docx-import-library-browser-smoke.sh, Playwright runner, make test-docx-import-library-browser, and QA/runbook docs for the real /teacher/exams/library page. The smoke seeds browser auth/org state, verifies browser-observed GET /api/exam-import/teacher-library uses exam-import-teacher-library/native_read, optionally searches by job id and asserts the row's BullMQ queue snapshot, and leaves default routes unchanged. Verified by script syntax, Node syntax, self-test, full Go tests, go vet, diff check, and no legacy diff.
P4-030Add import status route-table coveragescripts, api-gatewayDone. Added scripts/test/import-status-route-coverage.sh and make test-import-status-routes to statically validate the default, Compose, and localhost import-status route tables. Coverage requires teacher-library, algorithm events, and both status aliases to be GET-only native reads with auth/org guards and expected targets, while broad /api/exam-import, /api/imports, and fallback routes remain legacy-proxied and ordered after native carve-outs. Verified by script syntax, route coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-031Add DOCX Fast create route-table coveragescripts, api-gatewayDone. Added scripts/test/import-create-route-coverage.sh and make test-import-create-routes to statically validate the default, Compose, and localhost DOCX Fast create route tables. Coverage requires exact POST create, scoped GET temp-draft, scoped GET materialized asset content, and scoped POST reprocess to target docx-import-service with auth/org/role guards, while broad /api/exam-import and fallback routes remain legacy-proxied and ordered after the native carve-outs. Verified by script syntax, route coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-032Add DOCX Fast create live gateway smokescripts, api-gateway, docx-import-serviceDone. Added scripts/test/import-create-live-smoke.sh and make test-import-create-live as an opt-in write smoke for the non-default DOCX Fast create route table. The smoke requires explicit confirmation, auth/org context, and a caller-supplied DOCX questionStorageKey; verifies /v1/routes, asserts POST /api/exam-import/docx-fast-jobs hits exam-import-docx-fast-create as native_write, checks a sibling job detail route still uses broad legacy routing, and validates the legacy success envelope without changing default routing. Verified by script syntax, hermetic self-test, route coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-033Add DOCX Fast create browser-route smokescripts, api-gateway, docx-import-serviceDone. Added scripts/test/import-create-browser-smoke.sh, Playwright runner, QA doc, and make test-import-create-browser for opt-in browser evidence on the real DOCX Fast create surface. The smoke opens the import UI with browser auth/org state, verifies the non-default import-create route table, creates a DOCX Fast job either through the UI file input or through a browser-context POST using an existing questionStorageKey, asserts browser-observed gateway headers exam-import-docx-fast-create/native_write, validates the legacy success envelope, writes artifacts, and keeps default routing unchanged. Verified by shell/Node syntax, hermetic self-test, static route coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-034Add DOCX Fast reprocess live gateway smokescripts, api-gateway, docx-import-serviceDone. Added scripts/test/import-reprocess-live-smoke.sh, make test-import-reprocess-live, QA/API/runbook docs, and handoff notes for the opt-in DOCX Fast reprocess live smoke. The smoke requires explicit confirmation, a native DOCX Fast job id, auth/org context, verifies /v1/routes, asserts a sibling job detail route stays broad legacy, checks POST /api/exam-import/docx-fast-jobs/{id}/reprocess hits exam-import-docx-fast-reprocess as native_write, and validates the legacy success envelope keeps the same job id with message DOCX Fast import reprocessed. Verified by script syntax, hermetic self-test, Make target self-test, static route coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-035Add DOCX Fast temp-draft live gateway smokescripts, api-gateway, docx-import-serviceDone. Added scripts/test/import-temp-draft-live-smoke.sh, make test-import-temp-draft-live, QA/API/runbook docs, and handoff notes for the read-only DOCX Fast materialized temp-draft live smoke. The smoke requires a completed native DOCX Fast job id plus auth/org context, verifies /v1/routes, asserts GET /api/exam-import/docx-fast-jobs/{id}/temp-draft hits exam-import-docx-fast-temp-draft as native_read, validates the legacy materialized draft envelope with token materialized-{id}, and proves sibling temp-draft asset metadata stays on the broad legacy import route. Verified by script syntax, hermetic self-test, Make target self-test, static route coverage, full Go tests, go vet, diff check, and no legacy diff.
P4-036Add DOCX Fast temp asset content live gateway smokescripts, api-gateway, docx-import-serviceDone. Added scripts/test/import-temp-asset-live-smoke.sh, make test-import-temp-asset-live, QA/API/runbook docs, and handoff notes for the read-only materialized temp asset content live smoke. The smoke requires a completed native DOCX Fast job id, materialized temp asset id, and auth/org context; verifies /v1/routes; asserts GET /api/exam-import/docx-fast-jobs/{id}/temp-draft/assets/{asset}/content hits exam-import-docx-fast-asset-content as native_read; validates binary content headers/body size; and proves sibling asset metadata stays on the broad legacy import route. Verified by script syntax, hermetic self-test, Make target self-test, static route coverage, full Go tests, go vet, diff check, and no legacy diff.

Phase 5 DOCX Import Service Tasks

IDTaskService/AreaStatusDefinition Of Done
P5-001Create DOCX parser interface and required parser package layoutdocx-import-serviceDoneinternal/parser/docx, question, formula, media, table, classifier, output exist.
P5-002Implement required QAS endpoint shelldocx-import-serviceDonePOST /v1/import/docx/qas validates upload and returns warning-safe output.
P5-003Implement stream endpoint shelldocx-import-serviceDonePOST /v1/import/docx/qas/stream returns NDJSON events.
P5-004Add upload validationdocx-import-serviceDoneEnforces .docx, ZIP-based Office magic header, 50MB limit, timeout.
P5-005Port audited parser behaviordocx-import-serviceDoneGo Formula /v1/import/docx/simple adapter maps direct output, materializes extractable package images through document-service, applies payload-level DOCX style answer hints, builds annotated fallback QAS when Go returns 0 questions, has a deterministic classifier baseline, runs native OOXML style-hint extraction for Math/English/DGNL template-gated DOCX files, builds DGNL QAS fallback questions from native option/answer rows, reports renderable images before raw OLE/formula artifacts, has opt-in live document-service materialization and native warning artifact capture scripts, and includes native warning coverage for missing answer markers, template review-only, media fallback review, and image metadata review. The filtered live corpus warning comparison against output/import-audit-20260702/api passes with DOCX_WARNING_PARITY_ALLOW_EXTRA_NATIVE=1, because native emits additional review-safety warnings. Verified by focused parser tests, live capture/comparator, full Go tests, go vet, and no legacy diff.
P5-006Add fixtures from real DOCX corpusdocx-import-serviceDonePortable mixed-output/style-hint/annotated-fallback fixtures plus generated OOXML style-hint/DGNL fallback DOCX tests lock QAS/media/warning/native answer mapping; opt-in corpus integration verifies Physics 28Q (28, 18/4/6, 7 renderable images, 84 formulas), Math 22Q (22, 12/4/6, 7 renderable images, 125 formulas), English 40Q (40, all single-choice), and DGNL 102Q (102, 9 answer-only/review-required rows); opt-in materialization integration verifies Physics 28Q 7 images become fetchable MediaAsset content; filtered warning comparison against output/import-audit-20260702/api passes with DOCX_WARNING_PARITY_ALLOW_EXTRA_NATIVE=1. Verified by live make test-docx-corpus, live make test-docx-materialization, live warning capture/comparator, full Go tests, go vet, and no legacy diff.
P5-007Benchmark parser latencydocx-import-serviceDoneHandler benchmark exists, external parser latency is passed through from Go Formula response when available, and BenchmarkMapGoFormulaResult now covers mixed fixture mapping, annotated fallback mapping, and warning parity mapping with allocation metrics. Verified by focused benchmark, parser tests, full Go tests, go vet, and no legacy diff.
P5-008Add DOCX parser warning parity baselinedocx-import-serviceDoneAdded deterministic Go Formula warning coverage for missing answer markers after style hints/fallback and image metadata that lacks rendered HTML, while avoiding false positives for WMF/OLE formula previews. Verified by focused parser tests, docx-import-service tests, full Go tests, go vet, and no legacy diff.
P5-009Add DOCX corpus warning parity comparatorscripts, docsDoneAdded opt-in tooling that compares legacy audit warning categories against native DOCX import response warnings from caller-supplied JSON artifacts, with a hermetic self-test and no hard-coded claim that corpus parity has passed. Verified by shell/Python syntax checks, self-test target, full Go tests, go vet, and no legacy diff.
P5-010Add native DOCX warning artifact capture runnerscripts, docsDoneAdded an opt-in runner that posts the real Physics/Math/English/DGNL DOCX corpus to live docx-import-service /v1/import/docx/qas and writes stable physics.json, math.json, english.json, and dgnl.json native artifacts for the P5-009 comparator. The runner documents live-service prerequisites, supports subset/per-fixture path overrides plus dry-run corpus resolution, avoids committing binary DOCX files or generated artifacts, and does not claim warning parity until compared with legacy audit JSON. Verified by script syntax, dry-run against the local corpus, comparator self-test, full Go tests, go vet, and no legacy diff.
P5-011Normalize native DOCX warning comparator categoriesscripts, docsDoneUpdated the warning comparator so native GO_FORMULA_DOCX_INCOMPLETE_QUESTION records count toward missing-answer review coverage, native DOCX_NATIVE_DGNL_FALLBACK counts toward annotated fallback coverage, and live comparisons can explicitly filter to the fixture stems captured by P5-010. The comparator still fails on true missing legacy warning categories and does not claim corpus warning parity; the filtered live report now shows remaining DGNL media/missing-answer and Physics template-review gaps. Verified by comparator self-test, filtered live report, full Go tests, go vet, and no legacy diff.
P5-012Cover remaining native DOCX corpus warning categoriesdocx-import-serviceDoneAdded native review-safety warnings for the live corpus categories still missing after P5-011: DGNL fallback questions without answer evidence, DGNL package media/fallback review evidence when native fallback replaces a zero-question Go Formula result, and Physics template/type mismatch review-only evidence when parser types already conflict with the THPT template expectation. Parser output stays deterministic and does not coerce semantic type. The filtered live warning comparator now passes with DOCX_WARNING_PARITY_ALLOW_EXTRA_NATIVE=1, because native emits additional review-safety warnings beyond legacy. Verified by focused parser tests, live capture/comparator, full Go tests, go vet, and no legacy diff.

Phase 6 Question Bank Service Tasks

IDTaskService/AreaStatusDefinition Of Done
P6-001Add native question core schemaquestion-bank-serviceDoneService-owned migration 000003_question_core.sql creates questions, question_versions, question_options, grouping, tags, media refs, and formula refs with indexes and rollback.
P6-002Ingest DOCX import output into question-bankquestion-bank-servicePartialNative POST /v1/questions/import-docx-output writes Question + QuestionVersion + QuestionOption rows transactionally from DOCX QAS output, preserving media refs, formula HTML/LaTeX, answer keys, source metadata, and grouping metadata without mutating semantic type from group detection alone. docx-import-service now has an internal approval boundary that calls this endpoint, and P4-007 adds a non-default approval gateway adapter example; default public cutover and full exam-import approval parity remain pending.
P6-003Add read/list/detail parity for native questionsquestion-bank-servicePartialGET /v1/questions returns hydrated items/meta rows with current version, options, group refs, media refs, formula refs, tags, pagination metadata, core scalar filters, nullable taxonomy/source reference filters, unclassifiedOnly, missingExplanationOnly, fidelityStatus, sourceMetadataSource, safe actor scoping, admin-only allOrgs, and legacy-compatible relation/count placeholders. Native reads now hydrate customType from question_type_definitions and taxonomy named refs from question_taxonomy_refs when read-model rows exist. GET /v1/questions/{id} returns one hydrated row, accepts view=editor, preserves legacy archived-detail visibility within actor/tenant scope, and returns 404 QUESTION_NOT_FOUND for missing/out-of-scope reads. P6-032 adds opt-in browser-route evidence tooling for the real /teacher/questions list page and optional editor detail page through the legacy projection adapter; P6-033 adds admin /admin/questions allOrgs=1 browser-query evidence tooling. Full /api/questions cutover still requires executing teacher/admin browser smoke against real backfilled data, final taxonomy/user/org/usage backfill acceptance, and write parity.
P6-004Add legacy adapter/cutover route planapi-gateway, question-bank-servicePartialAdded GET /api/questions and GET /api/questions/:id shadow/native-read route examples plus live smoke scripts for legacy-vs-gateway shadow parity and direct-native-adapter-vs-gateway native parity. Detail routing uses suffix_segments: 1 so /api/questions/ai-classify/*, writes, and deeper subroutes remain legacy_proxy. P6-032/P6-033 add opt-in browser smokes that verify browser-observed questions-list/questions-detail gateway headers and admin allOrgs=1 query routing while leaving the default route table legacy-proxied. Native read cutover still requires executing live admin/browser parity with real backfilled data and final default-route approval.
P6-005Add native AI classification job foundationai-classifier-serviceDoneAdded service-owned classification job/status/error/SSE foundation with deterministic mock provider, usage event persistence shape, native migrations, OpenAPI contracts, and legacy-compatible success envelope. Public /api/questions/ai-classify/* stays legacy-proxied until real provider, question-bank apply adapter, RBAC, and browser parity are proven. Verified by focused service tests, full Go tests, go vet, OpenAPI YAML parse, and no legacy diff.
P6-006Add AI classifier persistent job storeai-classifier-serviceDoneAdded pgx-backed persistence for classification_jobs and provider_usage_events using the service-owned schema, with DATABASE_URL runtime selection, ping-verified Postgres setup, in-memory fallback, JSONB scope/progress/result scanning, focused repository tests, full Go tests, go vet, OpenAPI YAML parse, and no legacy diff. Public /api/questions/ai-classify/* remains legacy-proxied.
P6-007Add native AI classification apply foundationquestion-bank-serviceDoneAdded internal PATCH /v1/questions/ai-classify/apply accepting legacy-shaped apply items, updating service-owned question classification fields, recording sourceMetadataJson.aiClassification audit/history, preserving tenant/owner scope, syncing OpenAPI/contracts/docs, and keeping public /api/questions/ai-classify/apply legacy-proxied. Verified by focused question-bank tests, full Go tests, go vet, OpenAPI YAML parse, and no legacy diff.
P6-008Add taxonomy-aware AI classification apply parityquestion-bank-serviceDoneExtended native AI classification apply with taxonomy-backed id/code/name normalization and derived field parity: native question_type_definitions maps customTypeId to base type, taxonomy gradeId maps to numeric gradeLevel, and taxonomy difficultyLevelId maps to engine difficulty. Public /api/questions/ai-classify/apply remains legacy-proxied. Verified by focused question-bank tests, full Go tests, go vet, OpenAPI YAML parse, and no legacy diff.
P6-009Add AI classification apply gateway adapter exampleapi-gateway, question-bank-serviceDoneAdded non-default gateway route-table examples and regression tests for PATCH /api/questions/ai-classify/apply mapping to native PATCH /v1/questions/ai-classify/apply, while leaving other /api/questions/ai-classify/* routes legacy-proxied until auth/RBAC/browser parity are proven. Verified by focused gateway/question-bank tests, full Go tests, go vet, route JSON parse, and no legacy diff.
P6-010Enrich native question reads with custom type definitionsquestion-bank-serviceDoneHydrated list/detail customType from native question_type_definitions when customTypeId or core type matches a definition, preserving placeholder fallbacks and keeping /api/questions public cutover pending. Verified by focused question-bank tests, full Go tests, go vet, and no legacy diff.
P6-011Strengthen question read shadow legacy guard smokescripts, api-gatewayDoneExtended the opt-in question-read shadow parity smoke to assert the route table keeps the broad /api/questions fallback on legacy_proxy and byte-compares a nested AI-classification read subroute through legacy vs gateway. Verified by shell syntax, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-012Add native taxonomy reference read-model foundationquestion-bank-serviceDoneAdded service-owned taxonomy ref storage and internal list/upsert endpoints for legacy Subject, Chapter, Topic, EducationLevel, Grade, Curriculum, CurriculumNode, ExamTrack, QuestionSource, and DifficultyLevel, then hydrated question read subject/chapter/topic from that read model with placeholder fallback. Verified by focused question-bank tests, full Go tests, go vet, OpenAPI YAML parse, and no legacy diff.
P6-013Use taxonomy refs for native AI classification apply contextquestion-bank-serviceDoneNative AI classification apply now builds taxonomy context from active service-owned question_taxonomy_refs with global fallback, so subjectId, educationLevelId, gradeId, curriculumId, curriculumNodeId, examTrackId, questionSourceId, and difficultyLevelId normalize by id/code/name without relying on client-supplied taxonomy payloads. Verified by focused question-bank tests, full Go tests, go vet, and no legacy diff.
P6-014Hydrate native question reads with extended taxonomy refsquestion-bank-serviceDoneAdded service-owned named refs to native list/detail question payloads for educationLevel, grade, curriculum, curriculumNode, examTrack, questionSource, and difficultyLevel from question_taxonomy_refs, preserving existing ID fields and placeholder fallback. Public /api/questions stays on the current route plan until legacy adapter projection and browser parity are proven. Verified by focused question-bank tests, full Go tests, go vet, and no legacy diff.
P6-015Add question read native gateway rehearsal routesapi-gateway, question-bank-serviceDoneAdded non-default native-read gateway route-table examples for GET /api/questions and GET /api/questions/:id rewriting to native /v1/questions, preserving legacy fallback for writes and nested subroutes. Default /api/questions remains legacy-proxied until real backfill, adapter projection, auth/RBAC, browser parity, and rollback evidence are proven. Verified by JSON parse, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-016Add native question usage-count read modelquestion-bank-serviceDoneAdded a service-owned question_usage_counts projection plus internal PUT /v1/questions/usage-counts so native question reads hydrate _count.examItems, _count.attemptItems, and _count.answers without querying exam/attempt databases. Missing projections remain zero-compatible placeholders, and public /api/questions stays on the current route plan until backfill, adapter projection, browser parity, and rollback evidence are proven. Verified by focused/full Go tests, OpenAPI YAML parse, go vet, and no legacy diff.
P6-017Add native question relation read modelsquestion-bank-serviceDoneAdded service-owned question_user_refs and question_organization_refs projections plus internal PUT /v1/questions/relation-refs so native question reads hydrate legacy createdBy and organization fields without joining user-service, school-service, or legacy databases. Missing projections retain placeholder fallback, and public /api/questions stays on the current route plan until backfill, adapter projection, browser parity, and rollback evidence are proven. Verified by focused/full Go tests, OpenAPI YAML parse, go vet, and no legacy diff.
P6-018Add question read-model backfill dry-run SQLquestion-bank-service, migrationsDoneExpanded the question-bank legacy migration script with read-only extraction queries for taxonomy refs, usage counts, user refs, and organization refs that feed the P6-012/P6-016/P6-017 service-owned read models. Added SQL coverage validation to keep the script read-only and warning queries for rows that need manual handling before native read cutover. Verified by coverage script, migrator plan/dry-run, full Go tests, go vet, and no legacy diff.
P6-019Add native question editor detail projectionquestion-bank-serviceDoneNative GET /v1/questions/{id}?view=editor returns the legacy editor-selected shape used by GET /api/questions/:id?view=editor, including rich content/explanation JSON, taxonomy/source IDs, group passage fields, current-version answer keys/sub-items, and ordered editor option fields, while normal detail reads keep the hydrated native row. Public /api/questions/:id stays on the current route plan until browser parity and rollback evidence are proven. Verified by focused question-bank tests, full Go tests, OpenAPI YAML parse, go vet, and no legacy diff.
P6-020Add native question editor projection parity smoke assertionscripts, question-bank-serviceDoneExtended the opt-in question read shadow parity smoke so QUESTION_READ_PARITY_REQUIRE_NATIVE=1 verifies native GET /v1/questions/{id}?view=editor returns the editor projection shape, including currentVersion.answerKeysJson, currentVersion.subItemsJson, ordered option editor fields, optional group passage fields, and no full-row _count/createdBy/organization leakage. Gateway shadow mode still returns byte-identical legacy responses, and default /api/questions routes stay legacy. Verified by script syntax, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-021Add question read native rollback rehearsalscripts, api-gatewayDoneAdded a no-legacy-edit rollback rehearsal for the non-default question read native route table: statically validates the native-read table can be reverted to the default legacy table, asserts the rollback route table leaves broad /api/questions on legacy_proxy, rejects active rollback carve-outs, and provides an opt-in live gateway check that verifies list/detail requests are routed through the broad legacy route after rollback. Verified by shell syntax, script self-test, static rehearsal, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-022Add native legacy question read projection endpointsquestion-bank-serviceDoneAdded internal compatibility projection endpoints for future /api/questions native cutover without changing the native service contract: /v1/legacy/questions returns the legacy list envelope shape over the native read model, /v1/legacy/questions/{id} returns the legacy normal detail shape, and /v1/legacy/questions/{id}?view=editor preserves the editor projection already proven by P6-019/P6-020. Default gateway routes remain legacy until route-table cutover evidence is updated. Verified by focused HTTP projection tests, question-bank service tests, OpenAPI YAML parse, full Go tests, go vet, and no legacy diff.
P6-023Retarget question read native route examples to legacy projection adapterapi-gateway, scriptsDoneUpdated only the non-default question read native route-table examples so future /api/questions native-read rehearsals rewrite to /v1/legacy/questions instead of raw /v1/questions, kept the default route table legacy-proxied, and updated rollback/static validation tooling to require the adapter target prefix by default. Verified by route JSON parse, shell syntax, rollback rehearsal self/static tests, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-024Add question read adapter parity smoke assertionsscripts, question-bank-serviceDoneUpdated the opt-in question read shadow parity smoke so native checks target the compatibility adapter /v1/legacy/questions by default, while still allowing raw /v1/questions checks for older experiments. The smoke now asserts adapter list/detail/editor shapes before any public cutover and keeps gateway shadow responses byte-identical to legacy. Verified by script syntax, hermetic assertion self-test, full Go tests, go vet, and no legacy diff.
P6-025Retarget question read shadow route examples to legacy projection adapterapi-gateway, scriptsDoneAligned the non-default question-read shadow route-table examples with the P6-022 compatibility adapter by rewriting shadow requests to /v1/legacy/questions, and added a parity smoke guard that fails if /v1/routes points questions-list or questions-detail at an unexpected target prefix. Verified by route JSON parse, shell syntax, parity self-test, rollback rehearsal, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-026Add legacy adapter admin all-org read coveragequestion-bank-serviceDoneAdded focused compatibility-adapter coverage proving /v1/legacy/questions?allOrgs=1 preserves the native admin-only all-organization rule before any /api/questions cutover. Documented the live admin all-org shadow-smoke command. Verified by focused question-bank HTTP tests, question-bank service tests, full Go tests, go vet, and no legacy diff.
P6-027Add question read-model backfill report metadatatools/migrator, docs/migrationDoneExtended migrator report --service question-bank-service so it emits explicit read-only report items for the question read-model backfill projections required before /api/questions cutover: taxonomy refs, usage counts, user refs, organization refs, and warning counts. Verified by migrator unit tests, report JSON assertion, read-only SQL coverage, full Go tests, go vet, and no legacy diff.
P6-028Add static question-read route-table coveragescripts, api-gatewayDoneAdded a static coverage script and Make target that validates default, shadow, and native question-read route-table examples keep writes/nested routes on legacy and rewrite only list/detail reads to the legacy projection adapter. Verified by shell syntax, make test-question-read-routes, rollback rehearsal, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-029Add question-read native gateway parity smokescripts, api-gatewayDoneAdded an opt-in live smoke that runs against the non-default native-read route table and byte-compares gateway /api/questions list/detail/editor responses with direct /v1/legacy/questions adapter responses while verifying writes and nested routes remain legacy-routed. Verified by shell syntax, hermetic self-test, static route coverage, rollback rehearsal, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-030Add import approval route-table coveragescripts, api-gatewayDoneAdded static coverage for the non-default import approval native route examples so only POST /api/exam-import/jobs/{id}/approve is carved out to docx-import-service and sibling import job actions stay on the broad legacy route. Verified by shell syntax, make test-import-approval-routes, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-031Add import approval live gateway smokescripts, api-gateway, docx-import-serviceDoneAdded an opt-in live smoke for the non-default native approval route that requires explicit write confirmation, a completed import job, auth/org context, and native dependencies before calling POST /api/exam-import/jobs/{id}/approve. The smoke asserts the gateway route table/header/state, validates native approval response fields, keeps sibling import detail on the broad legacy route, and leaves the default route table unchanged. Verified by shell syntax, hermetic self-test, Make target self-test, route-table coverage, focused gateway tests, full Go tests, go vet, and no legacy diff.
P6-032Add question read browser-route smokescripts, api-gateway, question-bank-serviceDoneAdded scripts/test/question-read-browser-smoke.sh, Playwright runner, QA doc, and make test-question-read-browser as an opt-in browser smoke for the real /teacher/questions page and optional /teacher/questions/{id}/edit detail page. The smoke seeds browser auth/org state, requires the web app to point NEXT_PUBLIC_API_URL at the gateway, verifies browser-observed GET /api/questions uses questions-list/native_read, optionally verifies GET /api/questions/{id}?view=editor uses questions-detail/native_read, checks legacy-compatible list/detail payload shapes, writes artifacts, and leaves the default route table unchanged. Verified by self-test, script syntax, static route coverage, native gateway self-test, rollback rehearsal, full Go tests, go vet, diff check, and no legacy diff.
P6-033Add question read admin all-org browser smokescripts, api-gateway, question-bank-serviceDoneExtended scripts/test/question-read-browser-smoke.mjs with QUESTION_READ_BROWSER_EXPECT_QUERY and added make test-question-read-browser-admin for the real /admin/questions page. The admin target seeds admin browser auth/org state, waits for browser-observed GET /api/questions with allOrgs=1, verifies questions-list/native_read gateway headers, checks the legacy-compatible list payload shape, and leaves the default route table unchanged. Verified by self-test, script syntax, static route coverage, native gateway self-test, rollback rehearsal, full Go tests, go vet, diff check, and no legacy diff.
P6-034Add AI classification apply live gateway smokescripts, api-gateway, question-bank-serviceDoneAdded scripts/test/question-classification-apply-live-smoke.sh, make test-question-classification-apply-live, QA/API/runbook docs, and handoff notes for the opt-in native AI classification apply live smoke. The smoke requires explicit confirmation, a real native question id or caller-supplied apply body, auth/org context, verifies /v1/routes, asserts PATCH /api/questions/ai-classify/apply hits question-classification-apply as native_write, validates the legacy-shaped apply result counts and question id, proves sibling AI classification job routes stay on the broad legacy questions route, and keeps default routing unchanged. Verified by script syntax, hermetic self-test, Make target self-test, focused gateway/question-bank tests, full Go tests, go vet, diff check, and no legacy diff.
P6-035Add AI classification apply route-table coveragescripts, api-gatewayDoneAdded scripts/test/question-classification-apply-route-coverage.sh, make test-question-classification-apply-routes, API/runbook/QA docs, and handoff notes for static AI classification apply route-table coverage. The coverage proves the default table has no active apply carve-out, native examples route only exact PATCH /api/questions/ai-classify/apply to question-bank-service with auth/org/role guards, broad /api/questions and fallback remain legacy-proxied, and the apply route is ordered before broad legacy routes. Verified by shell syntax, route coverage, live-smoke self-test, focused gateway tests, full Go tests, go vet, diff check, and no legacy diff.
P6-036Add AI classification job route guard coveragescripts, api-gateway, ai-classifier-serviceDoneAudited legacy and native AI classification job contracts, kept POST /api/questions/ai-classify/suggestions, /api/questions/ai-classify/jobs*, job SSE, error history, and cancel routes legacy-proxied because ai-classifier-service still uses the deterministic mock provider and lacks BullMQ/provider/runtime parity, while preserving the existing exact PATCH /api/questions/ai-classify/apply carve-out to question-bank-service. Verified by shell syntax, make test-ai-classification-job-route-guard, existing apply route coverage, focused gateway/ai-classifier tests, full Go tests, go vet, and no legacy diff.
P6-037Add AI classifier provider adapter foundationai-classifier-serviceDoneAdded env-configured provider adapters for mock, OpenAI-compatible chat completions, native Gemini generateContent, and local/Ollama chat while preserving mock as the default, recording provider usage telemetry for success/failure, and enforcing timeout, retry, and circuit breaker behavior. Wired runtime env docs/deploy defaults for AI_CLASSIFIER_PROVIDER, AI_PROVIDER_TIMEOUT_MS, retry, and circuit settings. Public /api/questions/ai-classify/suggestions and job routes remain legacy-proxied until BullMQ/runtime, taxonomy prompt context, RBAC, and browser parity are proven. Verified by focused provider/service tests, gateway tests, route guards, full Go tests, go vet, YAML/OpenAPI parse, Helm render, whitespace scan, and no legacy diff.
P6-038Add AI classification input context endpointquestion-bank-serviceDoneAdded internal POST /v1/questions/ai-classify/context for bounded provider prompt input: scoped question content, explanation, options, current classification, question-type candidates, taxonomy candidates, candidate grades, and candidate curriculum nodes. Mirrored the legacy AI job onlyUnclassified predicate, including deterministic legacy difficulty reclassification, without changing public /api/questions/ai-classify/suggestions or job routing. Verified by question-bank and ai-classifier tests, route guards, full Go tests, go vet, OpenAPI parse, whitespace scan, and no legacy diff.

Phase 7 Exam And Attempt Service Tasks

IDTaskService/AreaStatusDefinition Of Done
P7-001Add native exam question snapshot foundationexam-serviceDoneexam-service owns a service-local exam_question_snapshots table plus internal PUT /v1/exams/{examId}/question-snapshots and GET /v1/exams/{examId}/question-snapshots APIs. The write contract accepts already-hydrated question payloads from question-bank-service or an import approval saga, preserves content JSON, options, sub-items, answer keys, scoring rule, media/formula refs, option order, section/order metadata, and never joins the question-bank database directly. Rollback keeps /api/exams/:id/questions and /api/exams/:id/publish on legacy proxy routes.
P7-002Implement native exam authoring CRUDexam-serviceDoneNative exams table plus POST /v1/exams, GET /v1/exams, GET /v1/exams/{id}, PATCH /v1/exams/{id}, and DELETE /v1/exams/{id} preserve owner/tenant scope, workflow/status/folder filters, duration/access/result-mode fields, access password hashing, password-hash redaction, direct-publish rejection, closed/published update guards, draft-only delete, and rollback by keeping /api/exams routes legacy-proxied.
P7-003Implement native publish workflowexam-serviceDoneNative POST /v1/exams/{id}/publish publishes only draft exams, requires at least one stored or supplied snapshot, optionally refreshes snapshots through the native snapshot contract before status change, creates the default access link with legacy guest/login attempt limits, records a service-local exam.published outbox event for later attempt-service/notification dispatch, keeps legacy-compatible error messages, and rolls back by keeping /api/exams/:id/publish legacy-proxied.
P7-004Implement attempt start snapshot copyattempt-serviceDoneNative POST /v1/exams/{examId}/attempts validates student/runtime/access state from a supplied exam runtime snapshot, copies exam question snapshots into attempt-owned rows, records START events, applies question/option shuffle behavior, never reads live question rows or another service database for attempt content, and rolls back by keeping /api/exams/:examId/start and /api/attempts/* legacy-proxied.
P7-005Implement answer save and submit grading parityattempt-serviceDoneNative POST /v1/attempts/{attemptId}/answers preserves attempt-owner checks, clientVersion/serverVersion conflict behavior, and SAVE_ANSWER events; native POST /v1/attempts/{attemptId}/submit grades from attempt-owned snapshots only, updates answer correctness/scores plus attempt totals, records SUBMIT/TIMEOUT events, adds 000003_attempt_answers_grading.sql, and rolls back by keeping /api/attempts/* legacy-proxied. Verified by focused/full Go tests, vet, OpenAPI parse, compose config, and runtime smoke.
P7-006Implement attempt event and result read parityattempt-serviceDoneNative POST /v1/attempts/{attemptId}/events, GET /v1/attempts/{attemptId}/events, and GET /v1/attempts/{attemptId}/result preserve exam-room event history, TIMEOUT submit delegation, ascending event listing, result visibility redaction, hidden reasons, unrounded scorePercent, and rollback by keeping /api/attempts/* legacy-proxied. Adds attempt-local exam result policy snapshot fields via 000004_attempt_result_events.sql instead of querying exam-service DB. Verified by focused/full Go tests, vet, OpenAPI parse, compose config, and runtime smoke.
P7-007Add attempt route-table rehearsal coverageapi-gateway, attempt-service, scriptsDoneAdded a native attempt start compatibility alias at POST /v1/exams/{examId}/start, non-default Compose/localhost attempt route-table examples, static route-table coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes. Coverage proves default routing stays legacy, POST /api/exams/:examId/start rewrites safely to attempt-service, exact attempt detail/save/submit/events/result routes reach attempt-service with auth/role/org guards, broad /api/exams, broad /api/attempts, and fallback remain legacy-proxied, and native carve-outs are ordered before broad legacy routes. Verified by route JSON parse, shell syntax, make test-attempt-routes, OpenAPI parse/mirror diff, focused attempt/gateway tests, full Go tests, go vet, and no legacy diff.

Phase 8 Auth User School Classroom Course Tasks

IDTaskService/AreaStatusDefinition Of Done
P8-001Add native auth credential/session foundationauth-serviceDoneNative POST /v1/auth/register, POST /v1/auth/login, POST /v1/auth/refresh, POST /v1/auth/logout, and GET /v1/auth/me preserve the legacy session envelope, bcrypt password verification, refresh-token jti hash/revoke behavior, access-token payload fields required by current guards/frontend, and rollback by keeping /api/auth/* legacy-proxied. Adds service-owned identities, identity_memberships, and refresh_tokens via 000002_auth_identity.sql; native refresh tokens are SHA-256 digested before bcrypt hashing to avoid raw token storage and Go bcrypt long-input limits. Verified by focused/full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, and runtime smoke.
P8-002Add native user profile foundationuser-serviceDoneNative PUT /v1/users/{userId}/profile-snapshot, GET /v1/users/{userId}/profile, PATCH /v1/users/{userId}/profile, and role-specific teacher/student/parent profile PATCH endpoints preserve legacy profile hydration, base profile validation, email/phone uniqueness, nullable role-profile payloads, and rollback by keeping /api/auth/me* legacy-proxied. Adds service-owned users, teacher_profiles, student_profiles, parent_profiles, teacher_kyc, and parent_students via 000002_user_profiles.sql; credentials and password changes remain auth-service-owned. Verified by focused user-service tests, full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, and runtime smoke.
P8-003Add native school organization/member foundationschool-serviceDoneNative organization, unit, member, user-membership, and tenant resolve/validate APIs preserve legacy organization CRUD, admin/non-admin list scoping, default organization fallback, unit-code uniqueness, member upsert, and last active OWNER protection. Adds service-owned organizations, organization_units, and organization_members; public /api/organizations* remains legacy-proxied until gateway adapters enforce auth/RBAC and legacy response compatibility. Verified by focused school-service tests, full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, no-legacy-diff check, and runtime smoke.
P8-004Add native classroom/member foundationclassroom-serviceDoneNative classroom CRUD, status, delete-impact, purge, member, student, join, and placeholder progress APIs preserve legacy manager/member scoping, teacher-member creation, teacher transfer guard, student join by code/id, member upsert, primary-teacher reassignment, and archive-vs-delete behavior for service-owned data. Adds service-owned classrooms and classroom_members; public /api/classrooms* and /api/admin/classrooms* remain legacy-proxied until gateway adapters enforce auth/RBAC, cross-service validation, and response hydration. Verified by focused classroom-service tests, full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, no-legacy-diff check, and runtime smoke.
P8-005Add native course content/enrollment foundationcourse-serviceDoneNative course, section, lesson, material metadata, enrollment, student progress, and public course projection APIs preserve legacy manager scoping, course archive semantics, section ordering, lesson/material publish flags, enrollment upsert, active enrollment checks, progress status derivation, video progress completion, and material view counting for service-owned data. Adds service-owned courses, course_sections, course_lessons, course_materials, course_enrollments, course_lesson_progress, course_video_progress, and course_material_views; public /api/courses*, /api/student/courses*, and /api/public/catalog* remain legacy-proxied until gateway adapters enforce auth/RBAC, cross-service validation, wallet purchase, file streaming, question/quiz contracts, and response hydration. Verified by focused/full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, no-legacy-diff check, and runtime smoke.
P8-006Add auth route-table rehearsal coverageapi-gateway, auth-service, scriptsDoneAdded non-default auth route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 8 native auth session foundation while default routing stays legacy. Coverage proves only POST /api/auth/register, POST /api/auth/login, POST /api/auth/refresh, POST /api/auth/logout, and GET /api/auth/me rewrite to auth-service, sibling auth routes such as Google, test-login, forgot/reset password, profile, KYC, and email-change stay on broad legacy auth routing, native auth routes do not use the gateway auth adapter, and native carve-outs are ordered before broad /api/auth plus fallback. Verified by route JSON parse, shell syntax, make test-auth-routes, OpenAPI parse/mirror diff, focused auth/gateway tests, full Go tests, go vet, and no legacy diff.
P8-007Add organization read route-table rehearsal coverageapi-gateway, school-service, scriptsDoneAdded non-default read-only organization route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 8 native school-service foundation while default routing stays legacy. Coverage proves only GET /api/organizations, GET /api/organizations/:id, GET /api/organizations/:id/units, and GET /api/organizations/:id/members rewrite to school-service with gateway auth/organization header injection and no global role adapter; organization writes, purge, unit/member mutations, student-imports, broad /api/organizations, and fallback remain legacy-proxied until RBAC/tenant adapters and response hydration are explicit. Verified by route JSON parse, shell syntax, make test-organization-routes, focused gateway/school-service tests, full Go tests, go vet, and no legacy diff.
P8-008Add student course read route-table rehearsal coverageapi-gateway, course-service, scriptsDoneAdded non-default student-course route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 8 native course-service foundation while default routing stays legacy. Coverage proves only GET /api/student/courses and GET /api/student/courses/{courseId} rewrite to course-service with gateway auth, global STUDENT role checks, and organization header injection. Student recommendation, purchase, progress/video/material writes, broad /api/student/courses, broad /api/courses, broad /api/public, and fallback remain legacy-proxied until recommendation, wallet, progress-write, file-streaming, and response hydration adapters are explicit. Verified by route JSON parse, shell syntax, make test-student-course-routes, focused gateway/course-service tests, full Go tests, go vet, and no legacy diff.
P8-009Add student course progress route-table rehearsal coverageapi-gateway, course-service, scriptsDoneAdded non-default student-course progress route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 8 native course-service foundation while default routing stays legacy. Coverage proves only POST /api/student/courses/{courseId}/lessons/{lessonId}/progress, POST /api/student/courses/{courseId}/lessons/{lessonId}/video-progress, and POST /api/student/courses/{courseId}/materials/{materialId}/view rewrite to course-service with gateway auth, global STUDENT role checks, and organization header injection. Student course list/detail are covered by P8-008 but remain legacy in this progress-only table; mastery, recommendation, purchase, broad /api/student/courses, broad /api/courses, broad /api/public, and fallback remain legacy-proxied until response hydration, recommendation, wallet, and file-streaming adapters are explicit. Verified by route JSON parse, shell syntax, make test-student-course-progress-routes, focused gateway/course-service tests, full Go tests, go vet, and no legacy diff.
P8-010Add classroom gateway adapter preflight guard coverageapi-gateway, classroom-service, scriptsDoneAudited legacy and native classroom contracts, kept /api/classrooms* and /api/admin/classrooms* legacy-proxied because current native rows still lack cross-service validation, response hydration, and deferred counts, added static guard coverage so default and rehearsal route tables cannot accidentally promote classroom public/admin routes, and made classroom-service accept gateway-injected X-User-* actor headers as a compatibility preflight for future adapters. Verified by shell syntax, make test-classroom-route-guard, focused classroom-service/gateway tests, full Go tests, go vet, and no legacy diff.

Phase 9 Notification Analytics Admin Tasks

IDTaskService/AreaStatusDefinition Of Done
P9-001Add native notification inbox/preferences foundationnotification-serviceDoneNative notification list/detail/create/batch/event, mark-read, delete, preference, parent-alert, and weak-topic alert APIs preserve legacy inbox paging, ALL/UNREAD/READ/SUPPORT filters, summary counts, admin-vs-owner scoping, parent alert rows, weak-topic alert fanout input, default-allow preferences, and service-owned notification events. Adds service-owned notifications, notification_preferences, and notification_events; public /api/notifications*, /api/parent/alerts*, /api/alerts*, and /api/admin/inbox* remain legacy-proxied until gateway adapters enforce auth/RBAC, recipient resolution, role broadcast, email delivery, support ticket integration, and admin audit logging. Verified by focused/full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, no-legacy-diff check, and runtime smoke.
P9-002Add native analytics result/event foundationanalytics-serviceDoneNative analytics result snapshot, result list, weak-topic rollup, exam/classroom/student summary, and event ingestion APIs preserve legacy result row shape, filters, paging defaults, weak-topic rollup formula, and service-local event capture for already-hydrated attempt data. Adds service-owned analytics_attempt_results and analytics_events; public /api/analytics*, /api/students*, /api/parents*, /api/exams/*/analytics, and classroom report export remain legacy-proxied until gateway adapters enforce auth/RBAC, parent-child/classroom access, result visibility, export formatting, and cross-service hydration. Verified by focused/full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, no-legacy-diff check, and runtime smoke.
P9-003Add native admin feature-maintenance and audit-log foundationadmin-serviceDoneNative feature maintenance list/public/update APIs preserve the legacy feature registry, active-key public payload, admin update shape, message trimming, and read-only AI classification job bypass contract for gateway/consumer use. Native audit-log create/list APIs preserve action/entity/entityId/actorId/organizationId/metadata fields, newest-first listing, and legacy limit/skip filter defaults. Adds service-owned feature_maintenance and audit_logs; public /api/feature-maintenance* and /api/admin/feature-maintenance* remain legacy-proxied until gateway auth/RBAC and maintenance guard adapters are explicit. Public /api/admin/operations*, users, AI settings, wallet, support, and admin dashboard routes remain legacy-proxied. Verified by focused/full Go tests, vet, OpenAPI parse/diff, compose/K8s YAML checks, no-legacy-diff check, and runtime smoke.
P9-004Add notification inbox/preferences route-table rehearsal coverageapi-gateway, notification-service, scriptsDoneAdded non-default notification route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 9 native notification foundation while default routing stays legacy. Coverage proves notification inbox list/detail, read/delete, read-all/delete-all, and both preferences aliases (/api/notifications/preferences and /api/alerts/preferences) rewrite to notification-service with gateway auth header injection and no organization requirement, while notification create/batch/snapshot, parent alerts, weak-topic alerts, admin inbox, broad /api/notifications, broad /api/alerts, broad /api/admin, and fallback remain legacy-proxied until recipient resolution, role broadcast, support-ticket, and audit adapters are explicit. Verified by route JSON parse, shell syntax, make test-notification-routes, focused gateway/notification-service tests, full Go tests, go vet, and no legacy diff.
P9-005Add admin feature-maintenance route-table rehearsal coverageapi-gateway, admin-service, scriptsDoneAdded non-default feature-maintenance route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 9 native admin feature-maintenance foundation while default routing stays legacy. Coverage proves only GET /api/feature-maintenance/public, GET /api/admin/feature-maintenance, and PATCH /api/admin/feature-maintenance/{key} rewrite to admin-service; admin routes require gateway auth plus global ADMIN role header injection, while public status stays unauthenticated. Broad /api/feature-maintenance, broad /api/admin, AI classification job reads, operations/audit routes, admin users/settings/wallet/support/dashboard, broad /api/questions, and fallback remain legacy-proxied until maintenance guard, RBAC, audit, and response compatibility adapters are explicit. Verified by route JSON parse, shell syntax, make test-feature-maintenance-routes, focused gateway/admin-service tests, full Go tests, go vet, and no legacy diff.
P9-006Add analytics results/weak-topics route-table rehearsal coverageapi-gateway, analytics-service, scriptsDoneAdded non-default analytics route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 9 native analytics foundation while default routing stays legacy. Coverage proves only GET /api/analytics/results and GET /api/analytics/weak-topics rewrite to analytics-service with gateway auth, global ADMIN/TEACHER role checks, and organization header injection. Analytics snapshot/event writes, exam/classroom/student/parent analytics, classroom export, broad /api/analytics, broad /api/exams, broad /api/classrooms, broad /api/students, broad /api/parents, and fallback remain legacy-proxied until summary path adapters, parent-child access, report export, result visibility, and cross-service hydration are explicit. Verified by route JSON parse, shell syntax, make test-analytics-routes, focused gateway/analytics-service tests, full Go tests, go vet, and no legacy diff.
P9-007Add admin operations audit route-table rehearsal coverageapi-gateway, admin-service, scriptsDoneAdded non-default admin audit route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 9 native admin audit-log foundation while default routing stays legacy. Coverage proves only GET /api/admin/operations/audit rewrites to admin-service /v1/admin/audit-logs with gateway auth and global ADMIN role header injection. Admin operations health, queues, retry/clear commands, metrics, import jobs, outbox, AI settings, feature-maintenance routes not included in this table, broad /api/admin, and fallback remain legacy-proxied until operational controls, tenant filtering, and response compatibility are explicit. Verified by route JSON parse, shell syntax, make test-admin-audit-routes, focused gateway/admin-service tests, full Go tests, go vet, and no legacy diff.
P9-008Add parent alert route-table rehearsal coverageapi-gateway, notification-service, scriptsDoneAdded non-default parent-alert route-table examples, static route coverage, gateway regression coverage, Make/docs/runbook updates, and handoff notes for the Phase 9 native notification foundation while default routing stays legacy. Coverage proves only GET /api/parent/alerts, POST /api/parent/alerts/{notificationId}/read, and POST /api/parent/alerts/read-all rewrite to notification-service with gateway auth plus global PARENT role header injection. Weak-topic alert creation, parent-child relationship lookup, broad /api/parent/alerts, broad /api/alerts, broad /api/notifications, broad /api/admin, and fallback remain legacy-proxied until recipient resolution and response compatibility adapters are explicit. Verified by route JSON parse, shell syntax, make test-parent-alert-routes, focused gateway/notification-service tests, full Go tests, go vet, and no legacy diff.

Phase 10 DevOps Hardening Tasks

IDTaskService/AreaStatusDefinition Of Done
P10-001Complete offline K8s service deployment coveragedeploy/k8s, scripts/devDoneEvery target Go service that scripts/dev/services.sh builds and loads has a matching offline K8s Deployment/Service manifest with local image, imagePullPolicy: Never, configmap/secret envs where needed, service-owned database URL, health/readiness probes, and basic resource requests/limits. k8s-deploy.sh applies all manifests and rolls the requested image tag across gateway plus every service deployment. Runbook documents the service coverage check. Verified by YAML parse, service coverage script, deploy script shell syntax, compose config, full Go tests/vet, and no legacy diff.
P10-002Add offline K8s schema migration jobs per servicetools/migrator, deploy/k8s/jobs, scripts/devDoneMigrator image can apply or report target service schema migrations from services/{service}/migrations without mutating the legacy database. Each service with SQL migrations has a matching offline K8s Job using service-owned DATABASE_URL, local migrator image, and imagePullPolicy: Never; k8s-migrate.sh applies these jobs idempotently. Runbooks document schema migration commands and their separation from legacy backfill commands. Verified by migrator unit tests, job coverage script, YAML parse, shell syntax, full Go tests/vet, compose config, and no legacy diff.
P10-003Add offline K8s observability scrape baselinedeploy/k8s/observability, scripts/dev, scripts/testDoneOffline kind deployment includes a Prometheus manifest that scrapes /metrics for every service in scripts/dev/services.sh, uses an explicitly preloaded local observability image, and exposes a local service for target inspection. Deployment/load scripts account for observability images. Runbooks document image preloading, target checks, and coverage validation. Verified by observability coverage script, YAML parse, shell syntax, compose config, full Go tests/vet, and no legacy diff.
P10-004Expand offline Helm chart render baselinedeploy/helm, scripts/test, docs/runbooksDoneHelm chart renders the namespace, platform config/secret, local infra, API gateway, every service in scripts/dev/services.sh, ingress, Prometheus scrape config, and optional schema migration Jobs with local image tags and imagePullPolicy: Never. Runbook documents offline Helm render/install flow. Verified by Helm lint/template coverage, YAML parse, compose config, full Go tests/vet, and no legacy diff.

Phase 11 Frontend Platform Tasks

IDTaskService/AreaStatusDefinition Of Done
P11-001Add VoidZero frontend platform workspaceapps, packages, frontend toolingDoneAdded a new go-platform frontend workspace without touching legacy apps/ or root packages/: independent Vite React apps for admin, teacher, student, parent, and public surfaces; shared frontend packages for UI, API client, auth client, config, types, and validators; pnpm/Turborepo orchestration; Vitest projects; Oxlint/OXC linting; Vite 8/Rolldown-compatible build setup; and docs/runbook coverage for local dev and Cloudflare Pages-style per-app builds. Frontend apps call the Go API Gateway/BFF through VITE_API_BASE_URL, not individual microservices. Verified by pnpm install, pnpm frontend:typecheck, pnpm frontend:test, pnpm frontend:lint, pnpm frontend:build, and git diff -- apps packages --exit-code.
P11-002Harden frontend platform architecture gatesapps, packages, frontend toolingDoneAudited P11-001 against the frontend-platform note, then added the missing large-platform gates without touching legacy apps/ or root packages/: app ownership folders, shared shadcn/Tailwind-style primitives, TanStack Query provider wiring, Zustand auth/session store, OpenAPI-generated gateway client types, Playwright smoke scaffold, and Cloudflare Pages deployment manifest. Verified with pnpm install, pnpm peers check, pnpm frontend:generate-api, pnpm frontend:typecheck, pnpm frontend:test, pnpm frontend:lint, pnpm frontend:build, pnpm frontend:e2e --project=chromium --reporter=line, git diff -- apps packages --exit-code, and curl -I http://127.0.0.1:5201/.

Phase 12 Frontend Auth/Public Tasks

IDTaskService/AreaStatusDefinition Of Done
P12-001Add auth/public audit, handoff, and QA image workflowfrontend docsDoneCreated evidence-backed docs for legacy auth/public behavior, Phase 12 handoff, and screenshot workflow before implementation. Legacy root apps//packages/ stayed read-only.
P12-002Add frontend i18n structurepackages/i18n, appsDoneAdded Vietnamese-default and English-supported dictionaries with typed locale helpers. Apps and shared UI can consume locale-aware copy without duplicating strings.
P12-003Add seed auth helpers and shared auth UIpackages/auth-client, packages/uiDoneModeled seed accounts [email protected], [email protected], [email protected], [email protected] with password Hoctapaz@123; added login/register/forgot/Google-entry components shared by role apps; remember behavior stores email only.
P12-004Wire role app auth routesapps/admin-web, apps/teacher-web, apps/student-web, apps/parent-webDone/login, /auth/login, /register, /auth/register, /forgot-password, and /auth/forgot-password render role-aware auth pages while root still renders the app workspace shell.
P12-005Implement public-web homepage parity surfaceapps/public-web, packages/uiDonepublic-web root renders a HocTapAZ public homepage aligned with the current legacy teacher-toolkit home, with brand, auth CTAs, teacher toolkit labels, and responsive desktop/mobile layout.
P12-006Verify checks and Chrome screenshotsfrontend tests, docs/demo-imagesDonePassed frontend typecheck/test/lint/build/e2e. Saved images under go-platform/docs/demo-images/frontend-auth-public/round-01-after-implementation/ and inspected representative desktop/mobile screenshots. Chrome extension captured public-home images; auth images used Chrome channel fallback after extension UI blocked automation.

Phase 13 Frontend Staff/Auth/Cloudflare Tasks

IDTaskService/AreaStatusDefinition Of Done
P13-001Add staff/auth/Cloudflare audit, handoff, and QA workflowfrontend docsDoneAudit, handoff, and runbook were created before source edits, then updated with final validation and screenshot results.
P13-002Enforce admin seed-only registration in native Go authauth-serviceDoneNative /v1/auth/register rejects ADMIN, allows TEACHER/STUDENT/PARENT, OpenAPI register schemas exclude admin, and focused Go tests pass with CGO_ENABLED=0.
P13-003Connect shared frontend auth to Gateway/native authpackages/auth-client, packages/uiDoneLogin/register use Gateway /api/auth/login and /api/auth/register when available, preserve local seed demo fallback for non-production login, and do not store plaintext passwords.
P13-004Add staff-web app and shared app configapps/staff-web, packages/config, packages/typesDoneStaff app builds/tests like other role apps, has its own host/port/deploy metadata, and does not expose self-registration.
P13-005Link public auth CTAs to role frontendspackages/ui, public-webDonePublic home shows role-specific login/register actions targeting teacher, student, parent, staff, and admin frontends instead of dead local auth links.
P13-006Update Cloudflare/performance structuredeploy/cloudflare, frontend toolingDonePages manifest includes six apps from the go-platform monorepo root, app-specific Vite build outputs, static SPA headers/redirects, and lazy-loaded route chunks.
P13-007Verify production gates and screenshot QAtests, Chrome, docs/demo-imagesDoneGo/frontend test gates pass; Chrome desktop/mobile screenshots were captured, visually inspected, and notes were updated by workflow.

Phase 14 Frontend Structure And Cloudflare V2 Dev Tasks

IDTaskService/AreaStatusDefinition Of Done
P14-001Restructure packages/ui for large-project ownershippackages/uiDoneUI package has explicit component/layout/module/router folders, auth/public modules are split out of monolith files, compatibility wrappers remain thin, and package-level tests pass independently.
P14-002Restore public role portal contractpublic-web, packages/uiDonePublic portal links teacher/student/parent login+register and staff/admin login-only, matching auth-service registration rules.
P14-003Add AI-followable frontend structure docsdocs/architecture, docs/agentsDoneArchitecture and handoff docs describe app boundaries, UI package rules, CSS rules, and verification commands for future agents.
P14-004Prepare Cloudflare Pages v2-dev deploy flowdeploy/cloudflare, scripts/deploy, docs/runbooksDoneManifest maps six apps to v2.dev.* domains, deploy script supports Direct Upload via Wrangler, and runbook documents auth/domain prerequisites.
P14-005Verify six app gates and local runtimeapps, testsDoneTypecheck, package UI test, full frontend tests, lint, build, e2e, dry-run deploy expansion, and local HTTP checks pass for all six apps.
P14-006Deploy Cloudflare Pages v2-devCloudflare PagesDonePages projects, custom-domain attachments, proxied CNAME records, and asset deployments exist for all six v2.dev.* hostnames in the hoctapaz.com Cloudflare zone. Cloudflare API reports the latest deployment stage success and custom domain status active for admin, staff, teacher, student, parent, and public. Verified by Wrangler Direct Upload, Cloudflare API metadata, dig @1.1.1.1, curl 200 checks for all custom domains plus SPA fallback paths, and live Playwright smoke on public/admin domains.

Phase 15 VitePress Docs And API Guide Tasks

IDTaskService/AreaStatusDefinition Of Done
P15-001Add VitePress documentation sitedocs, frontend toolingDonego-platform/docs is served by VitePress with local search, API/architecture/contracts/runbooks/QA navigation, shared theme assets, and root scripts docs:dev, docs:build, and docs:preview. Legacy root apps/ and root packages/ remain untouched. Verified by pnpm docs:build, VitePress preview, and route smoke for /, /api/, and /contracts/openapi/.
P15-002Publish gateway-first API guidedocs/api, contractsDoneAPI guidance now documents the public /api/* gateway contract, environment matrix, required headers, route-state lifecycle, gateway/native calling examples, OpenAPI source locations, service guide index, and cutover checklist. The guide keeps browser clients on API Gateway/BFF and reserves native /v1/* routes for service tests, adapters, and migration tooling.
P15-003Deploy docs site to Cloudflare Pages v2-devCloudflare PagesDonePages project hoctapaz-v2-dev-docs-web, custom domain v2.dev.docs.hoctapaz.com, and proxied CNAME exist in the hoctapaz.com zone. deploy/cloudflare/pages.frontend.json includes docs-web, and the docs output deploys from docs/.vitepress/dist. Verified by Wrangler Direct Upload, Cloudflare API metadata, dig @1.1.1.1, curl 200 checks, and live Playwright smoke on the VitePress home/API/contracts pages.

Task Rules

  • Every implementation task must cite the legacy files used as evidence.
  • Every route migration task must include rollback instructions.
  • Every DB task must include validation queries.
  • No task may edit apps/api, apps/web, packages/shared, or existing legacy config unless explicitly approved in a later phase.

Go-platform documentation is generated from repository Markdown.