Appearance
Handoff: SVC-017-wallet-ledger-route-proof wallet-service ledger route proof
Scope
- Service/area:
wallet-service - Goal: prove the bounded wallet ledger, replay, route-guard, and rollback evidence required by the next-slice queue.
- Non-goals: public/default wallet route promotion, payment-provider reconciliation, billing subscription mutation, usage/quota ownership, broad admin-wallet response parity, or changes to legacy source.
Docs Read
docs/architecture/service-responsibility-matrix.mddocs/architecture/legacy-api-map.mddocs/agents/service-tasks/wallet-service.mddocs/agents/handoffs/SVC-017-wallet-admin-review-response-parity.mddocs/agents/service-agent-next-slice-queue.jsondocs/agents/service-agent-next-slice-closeout-ledger.jsondocs/agents/agent-handoff-format.mddocs/api/wallet-service.mddocs/qa/wallet-admin-review-live-smoke.md
Legacy Evidence Read
/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/wallet/wallet.service.ts/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/wallet/wallet.controller.ts/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/wallet/az-credit.service.ts/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/wallet/wallet-topup-create.spec.ts/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/wallet/wallet-course-purchase.spec.ts- Legacy source was read-only evidence; no files under
/Users/velikho/Desktop/WORKING/HOCTAPAZ/were changed.
Files Changed
docs/agents/handoffs/SVC-017-wallet-ledger-route-proof.mdservices/wallet-service/internal/usecase/wallet.goservices/wallet-service/internal/http/server_test.goservices/wallet-service/internal/repository/postgres_integration_test.go- No OpenAPI, migration, or default gateway route file was changed.
Behavior Implemented
- Reusing a wallet idempotency key with different ledger type, amount, balance delta, or reference now returns
WALLET_CONFLICT; the original ledger row and balance remain unchanged. - Identical replays still return the original ledger row with
replay=true. - The route proof now asserts immutable after-balance snapshots for the credit and debit rows, and the Postgres replay integration covers the conflicting key case.
Tests And Verification
- Command:
GOTOOLCHAIN=go1.25.11 go test ./services/wallet-service/... -count=1 - Result: passed.
- Evidence: wallet-service audit sink, event fanout, HTTP, repository, and use-case packages passed.
- Recorded prior verification:
make test-monetization-event-chain test-monetization-routes test-monetization-broker-transport - Result: previously passed in the handoff's earlier worktree state; current reruns are qualified below.
- Command:
WALLET_ADMIN_REVIEW_SELF_TEST=1 bash scripts/test/wallet-admin-review-live-smoke.sh - Result: passed.
- Evidence: the admin-review route envelope and route-table guard self-test passed; this is not fresh real gateway/browser proof.
- Command:
GOTOOLCHAIN=go1.25.11 go test -race ./services/wallet-service/internal/... -count=1 - Result: passed.
- Evidence: wallet internal packages passed with race detection.
- Command:
WALLET_SERVICE_POSTGRES_TEST_DATABASE_URL='postgres://hoctapaz:hoctapaz@localhost:5433/hoctapaz_platform?sslmode=disable' GOTOOLCHAIN=go1.25.11 go test ./services/wallet-service/internal/repository -run TestPostgresWalletLedgerReplayIntegration -count=1 -v - Result: passed.
- Evidence: Postgres replay and conflicting-key assertions passed in an isolated schema.
- Current-turn note:
make test-monetization-event-chainandmake test-monetization-broker-transportreached wallet successfully but the full targets failed in unrelated dirty billing-service code (Subscription.Eventsundefined andnowundefined inservices/billing-service/internal/usecase/billing.go). The route target and wallet eventfanout package passed.
Current Working-Tree Re-verification
On 2026-07-13, the billing compile regression no longer reproduced: go test ./services/wallet-service/..., go test -race ./services/wallet-service/internal/..., make test-monetization-routes, and the admin-review self-test all passed. The isolated Postgres replay integration also passed against a fresh Compose database.
The read-only non-default Gateway smoke passed on 127.0.0.1:18091 with the current wallet-service: GET /api/admin/wallet/reviews?limit=5 returned 200, wallet-admin-reviews, and native_read. Broad admin and wallet paths still matched legacy_proxy; their deliberately unreachable legacy target returned 502. Artifacts are in output/qa/wallet-admin-review-live-20260713/. The temporary Compose project, volume, and Gateway listener were removed after validation.
Required Evidence
- immutable ledger proof: wallet-service repository/use-case tests passed for append-only balance movement and replay-safe idempotency behavior, including top-up, subscription-credit, debit, withdrawal, and refund-related paths covered by the existing service test suite.
- idempotency collision proof: identical replays are accepted, but reuse of a key with changed movement fields is rejected without adding a ledger row or moving balance.
- replay and route guard proof: the recorded event-chain/broker self-tests and current route guard/admin-review self-test passed; the 2026-07-13 current wallet package, race, Postgres, and live non-default Gateway checks passed.
- live rollback evidence: the existing local live artifact
output/qa/wallet-admin-review-live-20260709-092623/records the non-default native read route and the legacy fallback routes; its rollback instruction is the default route tabledeploy/gateway/routes.json.
Route State
- Legacy route: broad
/api/wallet,/api/admin/wallet, payment, subscription, and quota routes remain legacy-proxied. - Native route: only the non-default
GET /api/admin/wallet/reviewsrehearsal maps to/v1/admin/wallet/reviewswithADMINauthorization. - Gateway state:
wallet route changes require immutable ledger, replay, route guard, live proof, and rollback evidence; no default route table was changed or promoted. - Delegated gateway scope: route proof only; default gateway route tables remain orchestrator-owned unless a later slice produces reviewed promotion and rollback evidence.
- Rollback: keep
GATEWAY_ROUTE_TABLE=deploy/gateway/routes.json; do not promote public or broad admin wallet traffic based on self-test evidence.
Data Notes
- Tables touched: none.
- Migration run: none.
- Validation report: not applicable; this handoff changed no live data and performed no backfill.
Risks / Blockers
- Fresh real gateway/browser proof for the next route slice is still open; the current self-test is intentionally not treated as live evidence.
- Legacy-compatible public/admin response adapters and default-route rollback-after-candidate evidence remain open.
- This bounded handoff does not complete
wallet-serviceor the broader service rollout goal.
Next Step
- Run the non-default admin wallet-review route against a real seeded gateway session, attach request/response and browser artifacts, then review whether an exact read-only route can be promoted with explicit rollback evidence.