5.0 KiB
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-typescriptgate 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, stackingbouncer/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:
surfrouter tests,../fonoteka.go/parityTestMain andseedHooks(token insertion for theinv_tokenguard) - 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: trueset in frontmatter
Approval: pending