88 lines
3.9 KiB
Markdown
88 lines
3.9 KiB
Markdown
# Task: Fix billing empty collection contract
|
|
|
|
## Identity
|
|
|
|
- Task ID: 20260817-fix-billing-empty-arrays-4f9d2a7c
|
|
- Mode: Feature
|
|
- Branch: main
|
|
- Worktree: D:\Datas\OthersProjects\NianAIGC
|
|
- Base commit: 600cba023ca39d6dd81e526ba1e6014d4bfad65b
|
|
- Owner: codex
|
|
- Status: Ready for Integration
|
|
|
|
## Scope
|
|
|
|
- Make Go billing overview responses encode empty collections as JSON arrays,
|
|
never `null`.
|
|
- Add frontend response-shape validation so malformed billing payloads produce
|
|
an inline error instead of crashing the `/billing` route subtree.
|
|
- Replace the obsolete `npm run db:migrate` route-error guidance with wording
|
|
appropriate to the static Web + Go API architecture.
|
|
- Add regression coverage at both the Go HTTP contract seam and the pure
|
|
frontend payload parsing seam.
|
|
|
|
## Intent And Constraints
|
|
|
|
- Preserve the accepted static Web + Go-only API architecture and existing
|
|
authorization behavior.
|
|
- Do not change database schema, seed fake organizations, or require production
|
|
data to make empty-state rendering safe.
|
|
- Keep the fix surgical: Go owns valid JSON output; frontend validation is a
|
|
defense against incompatible or malformed deployments.
|
|
- Work test-first from the deterministic diagnosis recorded in
|
|
`20260817-diagnose-billing-page-7c3a91e2`.
|
|
|
|
## Outcome
|
|
|
|
- Go billing overview services now normalize every response collection used by
|
|
the member and super-administrator billing pages to a non-nil slice, so an
|
|
empty database result is encoded as `[]` rather than `null`.
|
|
- The browser validates every billing object, collection element, and nested
|
|
price dimension used by the renderer before committing API data to React
|
|
state. Incompatible successful responses now produce the existing inline
|
|
error state instead of throwing during render and activating the route error
|
|
boundary. Validation preserves Go `omitempty` behavior for optional fields,
|
|
including a fresh super-administrator without `organizationId`.
|
|
- The billing route error boundary and invalid-JSON fallback now direct
|
|
operators to the Go API status and server logs rather than the removed Node
|
|
migration workflow.
|
|
- Regression tests cover the real Go HTTP response contract with an empty store
|
|
and the frontend parser contract for empty, missing, null, and malformed
|
|
payloads.
|
|
|
|
## Verification
|
|
|
|
- RED: `go test ./internal/httpapi -run TestBillingOverviewResponsesEncodeEmptyCollectionsAsArrays -count=1`
|
|
failed because empty member/admin collections encoded as `null`.
|
|
- RED: `npx vitest run tests/billing-api-contract.test.ts` failed before the
|
|
frontend parser module existed.
|
|
- PASS: `go test ./...`.
|
|
- PASS: `go vet ./...`.
|
|
- Initial final review: FAIL because top-level array checks still allowed
|
|
malformed collection elements such as `priceRules: [null]` and a null member
|
|
`organization` to reach render-time property access.
|
|
- Remediation: added complete render-shape validation and regressions for admin
|
|
organizations/wallets, members, ledger entries, price rules/dimensions/tiers,
|
|
and member organization/wallet/summary/personal data.
|
|
- PASS after remediation: `npm test` (`54` files, `174` tests).
|
|
- PASS: `npx tsc --noEmit --incremental false`.
|
|
- PASS: `npm run deploy:check` (`7` ACK manifest files).
|
|
- PASS: `npm run build` (all routes statically exported, including `/billing`).
|
|
- PASS: `check_project_docs.py --target .`.
|
|
- PASS: task-aware `check_doc_drift.py` for this task ID.
|
|
- PASS: `git diff --check` (line-ending notices only).
|
|
- Final read-only review: PASS on both Standards and Spec after the malformed
|
|
nested-payload remediation; no blockers remain.
|
|
|
|
## Follow-ups
|
|
|
|
- After publishing new Web and Go images under a fresh immutable tag, verify an
|
|
authenticated super-administrator with zero organizations sees the billing
|
|
empty state in production. This requires deployment access and is not a code
|
|
acceptance blocker.
|
|
|
|
## Promotion Candidates
|
|
|
|
- None. This task applies the existing static Web + Go API architecture and does
|
|
not introduce a new architectural decision.
|