Skip to content

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.md
  • docs/architecture/legacy-api-map.md
  • docs/agents/service-tasks/wallet-service.md
  • docs/agents/handoffs/SVC-017-wallet-admin-review-response-parity.md
  • docs/agents/service-agent-next-slice-queue.json
  • docs/agents/service-agent-next-slice-closeout-ledger.json
  • docs/agents/agent-handoff-format.md
  • docs/api/wallet-service.md
  • docs/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.md
  • services/wallet-service/internal/usecase/wallet.go
  • services/wallet-service/internal/http/server_test.go
  • services/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-chain and make test-monetization-broker-transport reached wallet successfully but the full targets failed in unrelated dirty billing-service code (Subscription.Events undefined and now undefined in services/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 table deploy/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/reviews rehearsal maps to /v1/admin/wallet/reviews with ADMIN authorization.
  • 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-service or 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.

Go-platform documentation is generated from repository Markdown.