Skip to content

Handoff: SVC-015-ai-usage-wallet-route-proof ai-service usage wallet route proof

Scope

  • Service/area: ai-service via services/ai-classifier-service
  • Task pack: docs/agents/service-tasks/ai-service.md
  • Goal: accept the bounded SVC-015 next slice by proving the current usage/wallet ownership boundary, public AI route guard state, and route rollback notes before any AI job/default public route promotion.
  • Non-goals: default or deployed Gateway route promotion, live provider credential proof, quota enforcement inside AI, wallet credit movement inside AI, provider secret storage, or legacy source edits under /Users/velikho/Desktop/WORKING/HOCTAPAZ/.

Docs Read

  • go-platform/docs/agents/service-tasks/ai-service.md
  • go-platform/docs/agents/handoffs/SVC-015-queue-worker-batching-semantics.md
  • go-platform/docs/agents/service-agent-next-slice-queue.json
  • go-platform/docs/agents/service-agent-next-slice-closeout-ledger.json
  • go-platform/docs/agents/agent-handoff-format.md
  • go-platform/docs/agents/handoff-phase-6-ai-classifier-foundation.md
  • go-platform/docs/agents/handoff-phase-6-ai-classifier-pgx-store.md
  • go-platform/docs/agents/handoff-phase-6-ai-classifier-provider-adapters.md
  • go-platform/docs/api/ai-classifier-service.md
  • go-platform/docs/qa/ai-classification-job-live-smoke.md
  • go-platform/docs/qa/question-classification-apply-live-smoke.md
  • go-platform/services/ai-classifier-service/README.md

Legacy Evidence Read

  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/ai-settings.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/ai-usage.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-classification.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-classification.queue.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-classification.worker.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-generation.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-generation.service.spec.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-solution.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/questions/question-solution.service.spec.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/grading/grading.spec.ts
  • Legacy evidence shows the old generation/solution flows check AZ Credit before provider calls and burn credits after usable results, while the Go migration boundary keeps AI preview/provider telemetry separate from future usage-service and wallet-service consumption APIs.
  • Legacy source was read-only evidence only; no file under /Users/velikho/Desktop/WORKING/HOCTAPAZ/ was edited.

Files Changed

  • go-platform/docs/agents/handoffs/SVC-015-ai-usage-wallet-route-proof.md
  • go-platform/docs/agents/service-agent-next-slice-closeout-ledger.json
  • go-platform/docs/agents/service-agent-next-slice-closeout-ledger.md
  • go-platform/docs/agents/service-agent-accepted-handoffs.md
  • go-platform/docs/qa/service-agent-goal-completion-audit.md
  • go-platform/docs/qa/service-agent-readiness-smoke.md
  • go-platform/docs/qa/ai-generation-usage-wallet-runtime-proof.md
  • go-platform/docs/qa/ai-classification-worker-runtime-smoke.md
  • go-platform/scripts/test/ai-classification-worker-runtime-smoke.sh
  • go-platform/deploy/gateway/routes.ai-classification-jobs-native-example.json
  • go-platform/deploy/gateway/routes.ai-classification-jobs-native-localhost-example.json
  • go-platform/scripts/test/ai-classification-job-route-coverage.sh
  • go-platform/scripts/test/ai-classification-job-route-guard.sh
  • go-platform/packages/ui/src/modules/teacher/panels/ai-classification-jobs-panel.tsx
  • go-platform/packages/ui/src/modules/teacher/teacher-ai-preview-api.ts
  • go-platform/packages/ui/src/modules/teacher/teacher-workspace.test.tsx
  • go-platform/services/ai-classifier-service/internal/domain/ai_task_contract.go
  • go-platform/services/ai-classifier-service/internal/usecase/classifier.go
  • go-platform/services/ai-classifier-service/internal/usecase/generation_monetization_client_test.go
  • go-platform/services/ai-classifier-service/internal/repository/{memory.go,postgres.go,memory_test.go,postgres_test.go,postgres_settlement_integration_test.go}
  • go-platform/services/ai-classifier-service/internal/http/{server.go,server_test.go}
  • go-platform/services/ai-classifier-service/internal/http/generation_settlement_fault_injection_test.go
  • go-platform/services/ai-classifier-service/internal/domain/classifier.go
  • go-platform/services/ai-classifier-service/internal/provider/{provider.go,provider_test.go}
  • go-platform/services/ai-classifier-service/internal/repository/{memory.go,memory_test.go,postgres.go}
  • go-platform/services/ai-classifier-service/migrations/000006_generation_preview_settlement_worker.sql
  • go-platform/services/ai-classifier-service/README.md
  • go-platform/scripts/test/ai-generation-settlement-fault-injection.sh
  • go-platform/scripts/test/ai-generation-settlement-local-postgres.sh
  • go-platform/docs/qa/ai-generation-settlement-reconciliation-proof.md
  • go-platform/Makefile

Behavior Implemented

  • P6-049 adds an opt-in durable generation-settlement worker. It claims only AI-owned pending replay rows, persists lease/attempt/backoff/last-error state, and continues settlement with the existing owner-service idempotency keys. It does not call provider, preflight, Question Bank context, or a canonical Question Bank write.
  • The isolated fault-injection runner sends a generation request through the real AI HTTP handler, fails one usage-consume boundary call after the wallet debit and three usage mutations, then starts the production settlement worker loop against disposable HTTP usage/wallet fixtures. The retry reuses the same owner idempotency keys and completes the stored provider result without rerunning quota preflight or provider generation.
  • Existing ai-classifier-service preview routes record provider usage telemetry and use ChargePolicy: "preview_only_no_consume" for generate, explain, and essay-grade envelopes.
  • The bounded P6-047 generation adapter is opt-in only. When AI_GENERATION_USAGE_WALLET_ENABLED=true, it asks usage-service to check the four quota keys, asks wallet-service for balance, then settles a usable result through owner-service USAGE_DEBIT and idempotent usage/consume calls. AI neither stores quota state nor mutates the wallet database.
  • Existing generation preview results remain handoff payloads for question-service, explanation preview results do not mutate question data, and essay-grade preview results remain handoff payloads for attempt-service.
  • The AI-owned provider_settings default selection now initializes the native provider runtime when an enabled row exists. ADMIN-only GET/PUT /v1/admin/ai/providers/settings validates and saves only provider, model, base URL, and an allowlisted secret environment-variable reference; raw provider keys are never persisted or returned. The update switches the active in-process provider only after candidate validation and adds no public/default Gateway route.
  • Existing public AI job, suggestion, generation, and solution routes remain legacy-proxied. The only native question-classification route example remains the exact PATCH /api/questions/ai-classify/apply carve-out to question-bank-service, not ai-classifier-service.
  • The Teacher route /teacher/questions/ai-classify-jobs is an actual read-only consumer of the local candidate GET /api/questions/ai-classify/jobs and GET /api/questions/ai-classify/jobs/{id} paths. It obtains the access token from the existing Gateway session, renders owner-provided progress, Question Bank context, and suggestion fields, and deliberately exposes no apply, retry, cancel, or canonical Question Bank write.
  • Required evidence covered: usage/wallet boundary proof, AI route live proof, no quota or credit ownership in AI.

Tests And Verification

  • Command: GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/...
  • Result: passed.
  • Evidence: ai-classifier-service cmd, domain, HTTP, provider, repository, and usecase packages passed.
  • Command: make test-ai-generation-settlement-reconciliation
  • Result: passed on 2026-07-14.
  • Evidence: a provider result that had already caused one effective wallet debit and a partial usage sequence was recovered by the settlement worker without a second provider or preflight call. The focused tests also prove delayed backoff, lease recovery, and an expired preview that remains claimable while settlement is pending.
  • Command: scripts/test/ai-generation-settlement-fault-injection.sh
  • Result: passed on 2026-07-14.
  • Evidence: a hermetic AI HTTP request ran one quota preflight (four resource checks) and one provider generation, then received an injected 503 from the credits_weekly usage-consume fixture after one effective wallet debit. The real settlement worker made a second HTTP settlement attempt: owner idempotency reduced two wallet ledger calls to one effective debit and eight usage-consume calls to four effective resource mutations. The stored replay completed in one worker claim; a final identical AI HTTP request was served from the settled replay without any additional provider, usage, or wallet calls.
  • Command: GOTOOLCHAIN=go1.25.11 go test -race ./services/ai-classifier-service/internal/http -run '^TestGenerationSettlementWorkerHTTPFaultInjection$' -count=1 -timeout=60s -v
  • Result: passed on 2026-07-14.
  • Evidence: the concurrent usage-consume fixture, worker loop, and HTTP call counters passed the Go race detector with the same 1/4/2/1/8/4/1 provider/preflight/wallet-call/effective-debit/usage-call/effective-usage/ worker-attempt proof tuple.
  • Command: AI_CLASSIFIER_POSTGRES_DSN=postgres://hoctapaz:[email protected]:15440/hoctapaz_ai_classifier_db?sslmode=disable GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/internal/repository -run TestPostgresGenerationSettlementClaimPersistsAcrossStores -count=1 -v
  • Result: passed on 2026-07-14 against a new disposable postgres:16 database.
  • Evidence: all AI migrations through 000006 applied; a pending replay whose preview TTL had expired was readable through a new store instance, one worker claim acquired a persisted lease, a second worker could not claim, and the retry timestamp/error survived a separate store read. The container was removed after verification.
  • Command: GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/internal/usecase -run 'TestClassifierServiceGeneratePreview|TestClassifierServiceExplainPreview|TestClassifierServiceGradePreview|TestClassifierServiceProcessJob|TestHTTPQuestionContextClient' -count=1 -v
  • Result: passed.
  • Evidence: focused tests covered question context loading, provider batching, generation preview usage plus question-service handoff, explanation preview usage with no write result, essay-grade preview usage plus attempt-service handoff, invalid grade contracts, configured question-context failure, cancelled-running-job safety, retry recovery usage, circuit-open usage, and HTTP question context client behavior.
  • Command: make test-ai-classification-job-route-guard
  • Result: passed.
  • Evidence: all gateway route tables kept AI job/suggestion/generation/solution prefixes off active native AI targets; broad questions and fallback routes stayed legacy_proxy; the apply carve-out did not target ai-classifier-service.
  • Command: AI_CLASSIFICATION_JOB_SELF_TEST=1 make test-ai-classification-job-live
  • Result: passed.
  • Evidence: hermetic live-smoke harness self-test validated route-table/header assertions for AI classification job routes staying on the legacy questions route. This is not real browser proof or a live deployed gateway call.
  • Command: make test-question-classification-apply-routes
  • Result: passed.
  • Evidence: default route table stayed legacy-only; non-default compose and localhost examples expose only exact authenticated PATCH /api/questions/ai-classify/apply to question-bank-service, with broad questions/fallback routes still legacy.
  • Command: AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime make test-ai-classification-worker-runtime
  • Result: passed on 2026-07-13.
  • Evidence: a temporary in-memory service and mock provider accepted one deferred twelve-question job, its enabled worker completed three batches with one attempt, and native job detail, SSE snapshot, queue summary, and worker log agreed on the drained COMPLETED state. The process and temporary binary were removed after the check. Artifacts: output/qa/ai-classification-worker-runtime-20260713/.
  • Command: AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres make test-ai-classification-worker-runtime
  • Result: passed on 2026-07-13.
  • Evidence: a new postgres:16 container received only the AI service migrations. The worker completed the deferred job through the Postgres store; direct SQL verified COMPLETED:1:ai-classifier-worker-1 before the service, database container, and ports were removed. Artifacts: output/qa/ai-classification-worker-postgres-20260713/.
  • Command: AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank make test-ai-classification-worker-runtime
  • Result: passed on 2026-07-13.
  • Evidence: a disposable memory-backed Question Bank accepted twelve canonical questions through POST /v1/questions. The configured AI worker loaded all twelve through POST /v1/questions/ai-classify/context, completed the deferred job with native SSE and queue-summary evidence, and retained the twelve canonical prompt rows in scope.questionContext. Artifact: output/qa/ai-classification-worker-question-bank-20260713-rerun/.
  • Command: AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank make test-ai-classification-worker-runtime
  • Result: passed on 2026-07-13.
  • Evidence: the same isolated Question Bank fixture loaded all twelve prompt rows into a fresh Postgres-backed AI job. Direct SQL verified COMPLETED:1:ai-classifier-worker-1 before removing the AI service, Question Bank process, database container, and temporary ports. Artifact: output/qa/ai-classification-worker-question-bank-postgres-20260713/.
  • Command: make test-ai-classification-job-routes && make test-ai-classification-job-route-guard
  • Result: passed on 2026-07-13.
  • Evidence: only the two designated non-default tables may activate exactly three authenticated GET routes for native classification job list, detail, and {id}/events; their broad questions/fallback routes remain legacy. The default route table has no active job route.
  • Command: AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank AI_CLASSIFICATION_WORKER_SMOKE_GATEWAY=job-read make test-ai-classification-worker-runtime
  • Result: passed on 2026-07-13.
  • Evidence: a fresh Postgres-backed AI job aiclsjob-83f63573d0d70099 loaded all twelve Question Bank prompt rows, completed once, and was read through a disposable Gateway using the localhost candidate table. List/detail/SSE responses carried their expected native_read route headers; a locally signed teacher JWT was accepted and a student JWT was rejected with 403 AUTH_FORBIDDEN. Artifacts: output/qa/ai-classification-worker-question-bank-gateway-postgres-20260713-final/.
  • Command: pnpm exec vitest run packages/ui/src/modules/teacher/teacher-workspace.test.tsx
  • Result: passed on 2026-07-13 (90 tests).
  • Evidence: the exact Teacher route stored an authenticated Gateway session, fetched GET /api/questions/ai-classify/jobs?limit=20, auto-loaded the first selected detail, rendered a worker suggestion, and fetched a second detail after the operator selected another job.
  • Command: held disposable Postgres/Question Bank/Gateway worker smoke followed by the in-app browser at http://127.0.0.1:15202/teacher/questions/ai-classify-jobs.
  • Result: passed on 2026-07-13.
  • Evidence: the browser loaded one completed job aiclsjob-8adf2b5038c91f21 through the local candidate Gateway, displayed 12/12 processed, three batches, 12/12 Question Bank context and three result suggestions, then Tải lại job issued the exact list/detail reads. There were no console errors or warnings. The locally signed disposable Teacher session was cleared before browser finalization and the worker smoke cleaned all temporary processes/ports. Artifacts: output/qa/ai-classification-worker-teacher-browser-postgres-20260713/.
  • Command: isolated Compose runtime proof with AI_GENERATION_USAGE_WALLET_ENABLED=true, followed by a temporary Gateway using routes.teacher-ai-preview-native-localhost-example.json.
  • Result: passed on 2026-07-13.
  • Evidence: the fixture requested two mock previews, settled one six-credit wallet debit, consumed the four owner-service quota counters, and replayed without a second debit or counter increase. The Gateway request returned teacher-ai-generation-preview / native_write plus usage_wallet_settled; a STUDENT token was rejected with 403 AUTH_FORBIDDEN before upstream execution. Artifacts: output/qa/ai-generation-usage-wallet-runtime-20260713/.
  • workflowVerification:
    • GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/...
    • scripts/test/ai-generation-settlement-fault-injection.sh
    • GOTOOLCHAIN=go1.25.11 go test -race ./services/ai-classifier-service/internal/http -run '^TestGenerationSettlementWorkerHTTPFaultInjection$' -count=1 -timeout=60s -v
    • GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/internal/usecase -run 'TestClassifierServiceGeneratePreview|TestClassifierServiceExplainPreview|TestClassifierServiceGradePreview|TestClassifierServiceProcessJob|TestHTTPQuestionContextClient' -count=1 -v
    • make test-ai-classification-job-route-guard
    • make test-ai-classification-job-routes
    • AI_CLASSIFICATION_JOB_SELF_TEST=1 make test-ai-classification-job-live
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank AI_CLASSIFICATION_WORKER_SMOKE_GATEWAY=job-read make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank AI_CLASSIFICATION_WORKER_SMOKE_GATEWAY=job-read make test-ai-classification-worker-runtime
    • pnpm exec vitest run packages/ui/src/modules/teacher/teacher-workspace.test.tsx
    • make test-question-classification-apply-routes
  • requiredVerification:
    • GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/...
    • scripts/test/ai-generation-settlement-fault-injection.sh
    • GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/internal/usecase -run 'TestClassifierServiceGeneratePreview|TestClassifierServiceExplainPreview|TestClassifierServiceGradePreview|TestClassifierServiceProcessJob|TestHTTPQuestionContextClient' -count=1 -v
    • make test-ai-classification-job-route-guard
    • make test-ai-classification-job-routes
    • AI_CLASSIFICATION_JOB_SELF_TEST=1 make test-ai-classification-job-live
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank AI_CLASSIFICATION_WORKER_SMOKE_GATEWAY=job-read make test-ai-classification-worker-runtime
    • AI_CLASSIFICATION_WORKER_SMOKE_CONFIRM=disposable-runtime AI_CLASSIFICATION_WORKER_SMOKE_STORE=postgres AI_CLASSIFICATION_WORKER_SMOKE_CONTEXT=question-bank AI_CLASSIFICATION_WORKER_SMOKE_GATEWAY=job-read make test-ai-classification-worker-runtime
    • pnpm exec vitest run packages/ui/src/modules/teacher/teacher-workspace.test.tsx
    • make test-question-classification-apply-routes

Route State

  • Legacy route: public /api/questions/ai-classify/jobs*, /api/questions/ai-classify/suggestions, /api/questions/ai-generation*, /api/questions/ai-solutions*, and attempt submit stay behind existing legacy routes.
  • Native route: internal /v1/ai-classifier/*, /v1/ai/generation/preview, /v1/ai/explanation/preview, /v1/ai/essay-grade/preview, and owner admin queue/provider APIs remain service/native routes only.
  • Gateway state: no default gateway route table changed. The 2026-07-13 proof exercised only non-default teacher generation preview and AI job-read candidates; broad questions and fallback routes remained legacy_proxy. The Teacher job page is a local read-only candidate consumer. Non-default question-classification-apply examples target question-bank-service, not ai-classifier-service.
  • Route default state: AI job/public route promotion requires usage/wallet boundary proof and route live proof.
  • Rollback: keep deploy/gateway/routes.json as the active default route table. If a non-default AI job route rehearsal is added later, rollback must return GATEWAY_ROUTE_TABLE to deploy/gateway/routes.json or remove the native AI job entries, then rerun make test-ai-classification-job-route-guard and the relevant live/browser smoke before promotion review.

Data Notes

  • Tables touched: the isolated Compose project wrote only service-owned fixture rows for AI provider telemetry, usage events/counters, and wallet ledger entries. It used no legacy database.
  • The settlement fault-injection runner uses only memory-backed AI state and disposable in-process HTTP fixtures. It reads no shared credentials, starts no container, and touches no usage-service, wallet-service, legacy, or shared database. Fixture state is discarded when the focused Go test exits.
  • Migration run: service-owned Compose migration containers completed for ai-classifier-service, usage-service, and wallet-service before the proof calls.
  • Validation report: the fixture showed one six-credit debit, four settled owner-service counters, and replay idempotency. No canonical question, solution, attempt, or public default-route data was written.
  • Boundary proof: provider_usage_events remains AI-owned telemetry; usage-service owns quota decisions/counters and wallet-service owns credit balance/ledger movement.
  • Provider selection data stays AI-owned in provider_settings; it contains no provider secret value. The local PostgreSQL runner seeds only a disposable mock selection and verifies native startup reports configurationSource=database before and after the settlement restart.

Risks / Blockers

  • The owner-local worker smoke proves disposable memory and fresh Postgres storage paths, the isolated Question Bank prompt-context path, and a local non-default Gateway candidate for selected read/SSE routes. The separate Teacher proof validates the local read-only browser consumer. Neither proves concurrent Postgres SKIP LOCKED claims, Question Bank Postgres or taxonomy data, or a live deployed Gateway.
  • P6-049 now recovers a partial owner sequence forward with durable claim, lease, and backoff state. It intentionally has no distributed transaction or compensating debit, so keep the charged path opt-in and rely on the wallet/usage owner APIs' idempotency keys.
  • The new fault injection proves the AI worker and HTTP client against contract-shaped in-process owner fixtures; it does not execute the real usage-service/wallet-service binaries, their databases, or a process restart.
  • Public AI job route promotion remains blocked on provider-backed execution, disposable real-owner persistence proof, default-route rollback review, and deployed-Gateway evidence.
  • The database-backed selection proof uses the mock provider and verifies only configuration resolution. It does not prove a live provider credential, network execution, billing behavior, or a deployed/default Gateway route.

Next Step

  • Keep the Teacher job surface read-only. Before a charged provider-backed public route, repeat the injected failure with disposable real usage/wallet service processes and stores, then retain default-route rollback evidence. A separate owner-service apply handoff must be idempotent and audit-backed; it must not be added as a side effect of the AI read surface.

Go-platform documentation is generated from repository Markdown.