Files
summercms/.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-VALIDATION.md
2026-09-19 15:36:23 +02:00

5.0 KiB

phase, slug, status, nyquist_compliant, wave_0_complete, created
phase slug status nyquist_compliant wave_0_complete created
6 http-routing-auth-groups-and-rate-limiting draft false false 2026-09-19

Phase 6 — Validation Strategy

Per-phase validation contract for feedback sampling during execution.


Test Infrastructure

Property Value
Framework Go stdlib testing + testify (assert/require); net/http/httptest for router, limiter, CORS and fetch-helper tests; testcontainers-go Postgres only where the inv_token guard and parity harness need real rows
Config file none — plain func TestX(t *testing.T); parity TestMain in ../fonoteka.go/parity is reused
Quick run command go vet ./... && go test ./... -short (run in the repo the task writes to)
Full suite command go test ./... -race in summercms.go and in ../fonoteka.go
Estimated runtime ~20 s quick, ~120-180 s full

Sampling Rate

  • After every task commit: Run go vet ./... && go test ./... -short
  • After every plan wave: Run go test ./... in both repos
  • Before /gsd:verify-work: Full suite green in both repos with -race, parity harness green on genres under both auth groups, swag + openapi-typescript gate green
  • Max feedback latency: 120 seconds

Per-Task Verification Map

Task IDs are filled in by the planner once PLAN.md files exist. Requirement-level map from 06-RESEARCH.md §Validation Architecture:

Task ID Plan Wave Requirement Threat Ref Secure Behavior Test Type Automated Command File Exists Status
TBD TBD TBD HTTP-03 TBD Same handler serves JWT /_fonoteka/api/v1/genres and personal-token /api/v1/fonoteka/genres; unknown and malformed ids both 404; groups mutually exclusive in the route table integration `go test ./... -run 'TestGenresSharedHandler TestGroupsMutuallyExclusive'` (fonoteka.go) ❌ W0
TBD TBD TBD HTTP-04 TBD Five named buckets, inline throttle:N,M, stacked limiters; fixed-window Laravel semantics and headers; client IP only via trusted-proxy rule unit + integration `go test ./surf/... -run 'TestLimiter TestClientIP'` ❌ W0
TBD TBD TBD HTTP-05 TBD Guard registry: jwt and inv_token resolve to one bouncer.User(ctx); duplicate/unknown guard name fails boot; inv.scope 401/403 bodies exact unit + integration go test ./bouncer/... -run TestGuardRegistry ❌ W0 ⬜ pending
TBD TBD TBD HTTP-06 TBD [], +00:00, tri-state null, omitted keys; raw OAuth group refuses house envelope/error middleware at registration, verified over the route table unit + route-table `go test ./surf/... -run 'TestResponseTypes TestRawGroupExemption'` ❌ W0
TBD TBD TBD HTTP-07 TBD Fetch helper rejects non-allow-listed host and private/loopback IPs at dial time, https only, no redirects, byte cap while streaming, timeout unit (httptest) go test ./... -run TestFetch ❌ W0 ⬜ pending
TBD TBD TBD HTTP-08 — swag generates OpenAPI from handler annotations; openapi-typescript yields valid TS; drift check build gate phase gate script (exact command set at plan time) ❌ W0 ⬜ pending
TBD TBD TBD HTTP-09 TBD Path-scoped CORS equals config/cors.php (JWT group gets no CORS headers); http.MaxBytesReader body limits per group integration `go test ./surf/... -run 'TestCORS TestBodyLimit'` ❌ W0

Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky


Wave 0 Requirements

  • surf/limiter_test.go — fixed-window Store semantics, named-bucket resolution, inline throttle keys, stacking
  • bouncer/registry_test.go — guard register / duplicate-fail / resolve-by-name
  • Fetch-helper package fetch_test.go — httptest servers for each typed failure reason
  • surf/routetable_test.go — raw-group middleware refusal at registration, route table contents
  • Existing infra reused: surf router tests, ../fonoteka.go/parity TestMain and seedHooks (token insertion for the inv_token guard)
  • No new test framework

Manual-Only Verifications

Behavior Requirement Why Manual Test Instructions
Production client_max_body_size / post_max_size / upload_max_filesize values HTTP-09 The production nginx vhost and php.ini are operator-managed and not in any repo (06-RESEARCH.md A2) Operator reads the values from the production host; they are recorded in config defaults and the test asserts the recorded numbers

Validation Sign-Off

  • All tasks have <automated> verify or Wave 0 dependencies
  • Sampling continuity: no 3 consecutive tasks without automated verify
  • Wave 0 covers all MISSING references
  • No watch-mode flags
  • Feedback latency < 120s
  • nyquist_compliant: true set in frontmatter

Approval: pending