New package internal/web/api/ with AdultsResponse, JuniorsResponse, PaymentsResponse, VersionResponse — all fields carry explicit json: tags matching the Python view-model keys
Expected{Value int; Unknown bool} with custom MarshalJSON emits integer or "?" for junior single-attendance months
RawTransaction covers the full 11-column payments sheet row (for unmatched and raw_payments)
schemagen_test.go reflects all four types via github.com/invopop/jsonschema; golden-compares against committed schemas in tests/fixtures/api-schema/
The JSONSchema() method for Expected lives in the test file — production binary has zero jsonschema dependency
member_data/month_labels/raw_payments are nested objects in the API contract (not pre-serialised JSON strings as in the Jinja templates)
Plan file at docs/plans/2026-05-07-1650-go-rewrite-m5-1-api-structs-schemas.md
Test plan
go test fuj-management/go/internal/web/api — schema golden test passes
go vet ./internal/... ./cmd/... — clean
golangci-lint run ./internal/web/... — clean
All existing Go tests still pass (go test ./internal/... ./cmd/...)
Inspect tests/fixtures/api-schema/juniors.schema.json — Expected appears as oneOf: [integer, "?"]
## Summary
- New package `internal/web/api/` with `AdultsResponse`, `JuniorsResponse`, `PaymentsResponse`, `VersionResponse` — all fields carry explicit `json:` tags matching the Python view-model keys
- `Expected{Value int; Unknown bool}` with custom `MarshalJSON` emits integer or `"?"` for junior single-attendance months
- `RawTransaction` covers the full 11-column payments sheet row (for `unmatched` and `raw_payments`)
- `schemagen_test.go` reflects all four types via `github.com/invopop/jsonschema`; golden-compares against committed schemas in `tests/fixtures/api-schema/`
- The `JSONSchema()` method for `Expected` lives in the test file — production binary has zero jsonschema dependency
- `member_data`/`month_labels`/`raw_payments` are nested objects in the API contract (not pre-serialised JSON strings as in the Jinja templates)
- Plan file at `docs/plans/2026-05-07-1650-go-rewrite-m5-1-api-structs-schemas.md`
## Test plan
- [x] `go test fuj-management/go/internal/web/api` — schema golden test passes
- [x] `go vet ./internal/... ./cmd/...` — clean
- [x] `golangci-lint run ./internal/web/...` — clean
- [ ] All existing Go tests still pass (`go test ./internal/... ./cmd/...`)
- [ ] Inspect `tests/fixtures/api-schema/juniors.schema.json` — `Expected` appears as `oneOf: [integer, "?"]`
🤖 Generated with [Claude Code](https://claude.ai/claude-code)
Add internal/web/api package with Go structs for every /api/X route:
AdultsResponse, JuniorsResponse, PaymentsResponse, VersionResponse.
All fields carry explicit json: tags matching the Python view-model keys.
Key design choices:
- member_data / month_labels / raw_payments are nested objects (not
the pre-serialised JSON strings used in Jinja templates)
- Expected{Value int; Unknown bool} with custom MarshalJSON emits int
or the string "?" for junior single-attendance months
- RawTransaction covers the full 11-column payments sheet row
schemagen_test.go reflects all four response types via
github.com/invopop/jsonschema and golden-compares against committed
schemas in tests/fixtures/api-schema/. The JSONSchema() method on
Expected lives in the test file so the prod binary has no jsonschema
dependency.
Closes M5.1 in docs/plans/2026-05-03-2349-go-backend-rewrite-progress.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
internal/web/api/withAdultsResponse,JuniorsResponse,PaymentsResponse,VersionResponse— all fields carry explicitjson:tags matching the Python view-model keysExpected{Value int; Unknown bool}with customMarshalJSONemits integer or"?"for junior single-attendance monthsRawTransactioncovers the full 11-column payments sheet row (forunmatchedandraw_payments)schemagen_test.goreflects all four types viagithub.com/invopop/jsonschema; golden-compares against committed schemas intests/fixtures/api-schema/JSONSchema()method forExpectedlives in the test file — production binary has zero jsonschema dependencymember_data/month_labels/raw_paymentsare nested objects in the API contract (not pre-serialised JSON strings as in the Jinja templates)docs/plans/2026-05-07-1650-go-rewrite-m5-1-api-structs-schemas.mdTest plan
go test fuj-management/go/internal/web/api— schema golden test passesgo vet ./internal/... ./cmd/...— cleangolangci-lint run ./internal/web/...— cleango test ./internal/... ./cmd/...)tests/fixtures/api-schema/juniors.schema.json—Expectedappears asoneOf: [integer, "?"]🤖 Generated with Claude Code
Add internal/web/api package with Go structs for every /api/X route: AdultsResponse, JuniorsResponse, PaymentsResponse, VersionResponse. All fields carry explicit json: tags matching the Python view-model keys. Key design choices: - member_data / month_labels / raw_payments are nested objects (not the pre-serialised JSON strings used in Jinja templates) - Expected{Value int; Unknown bool} with custom MarshalJSON emits int or the string "?" for junior single-attendance months - RawTransaction covers the full 11-column payments sheet row schemagen_test.go reflects all four response types via github.com/invopop/jsonschema and golden-compares against committed schemas in tests/fixtures/api-schema/. The JSONSchema() method on Expected lives in the test file so the prod binary has no jsonschema dependency. Closes M5.1 in docs/plans/2026-05-03-2349-go-backend-rewrite-progress.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>