--- phase: 06-http-routing-auth-groups-and-rate-limiting verified: 2026-09-21T16:00:00Z status: passed score: 12/12 must-haves verified overrides_applied: 0 mvp_mode_note: "ROADMAP mode is mvp but the technical goal is not a valid User Story (user-story.validate valid=false); this re-verification retains the technical goal contract." re_verification: previous_status: gaps_found previous_score: 8/12 gaps_closed: - "Body limit now wraps all named/factory middleware (surf/router.go wrap: bodyLimit applied after the middleware loop, inside recovery); TestBodyLimitBoundsBodyConsumingMiddleware and TestBodyLimitBoundsNamedMiddleware exist and pass." - "RegisterBucket rejects nil store, nil Key, Max<1, Decay<=0; resolve() overflow-checks minute conversion; Middleware fails closed (500) instead of pass-through; TestRegisterBucketRejectsInvalidDefinitions, TestValidateThrottleRejectsOverflowAndNilStore, TestMiddlewareFailsClosed pass." - "fetchguard/ip.go carries full IANA special-use IPv4/IPv6 tables (198.18.0.0/15, 192.0.0.0/24, 240.0.0.0/4, ...); dialControl rejects zoned addresses with errPrivateIP; TestDialControlRejectsZonedAndSpecialUse and IANA boundary tests pass." - "06-SECURITY-REVIEW.md reopened and re-closed with T-06-28..35 (34/34 closed) backed by passing tests." - "Warnings also fixed: ServeMux conflict returns an error (handleRoute), factories built once (r.built cache), bad body config fails boot." gaps_remaining: [] regressions: [] deferred: - truth: "Public/onboarding groups have reachable unauthenticated handlers." addressed_in: "Phase 13" evidence: "Phase 13 ports onboarding/public/invitation routes with public buckets." - truth: "Unknown and malformed ids on ownership-scoped resources both return 404." addressed_in: "Phase 12" evidence: "Phase 12 owns Collections and Albums; Phase 6 supplies the constraint primitive." - truth: "A production OAuth/RFC route exists in the raw group." addressed_in: "Phase 8" evidence: "Phase 8 owns the OAuth2.1 endpoints; Phase 6 supplies the raw-group contract." - truth: "Manual-cover and Discogs production callers use fetchguard." addressed_in: "Phase 12 / Phase 14" evidence: "Cover handling and Discogs integration are owned there." --- # Phase 6: HTTP routing, auth groups and rate limiting Verification Report **Phase Goal:** The three mutually exclusive auth groups share handlers with correct subsets, rate-limit buckets are ported 1:1, OAuth/RFC routes are structurally raw, and the auth registry, limiter, and SSRF fetch helper form secure shared infrastructure. **Verified:** 2026-09-21 **Status:** passed **Re-verification:** Yes, after gap-closure plans 06-12..06-14 ## Goal Achievement ### Observable Truths | # | Truth | Status | Evidence | | --- | --- | --- | --- | | 1 | JWT and token groups share the genres handler; subsets mutually exclusive | VERIFIED (public groups deferred) | Unchanged from prior verification; tests pass. | | 2 | Five named buckets and inline throttles enforce live limits/keys, including stacking | VERIFIED | Valid definitions plus now-rejected invalid ones. | | 3 | Response conventions and raw/house panic behavior | VERIFIED | wire tests and recovery tests pass. | | 4 | Fetch helper is an SSRF boundary (allow-list, non-public IP rejection incl. special-use and zoned, cap, timeout) | VERIFIED | `fetchguard/ip.go` IANA tables; `dialControl` rejects zone; tests `TestDialControlRejectsZonedAndSpecialUse`, `TestIsReservedOrPrivateIANABoundaries`, `TestIsReservedOrPrivateIgnoresZone`. | | 5 | OpenAPI, path CORS, and body limits enforce the deployment contract | VERIFIED | Body cap now outermost of named middleware (router.go wrap, cap applied after loop, before locale/recover); body-consuming middleware test passes. | | 6 | Guard registry unifies users, exact error contracts | VERIFIED | Unchanged; typed-nil now rejected (8a9449d). | | 7 | `name:param` middleware via factories | VERIFIED | Factories cached in `r.built`, built once. | | 8 | Fixed-window limiter is a safe primitive | VERIFIED | Invalid definitions fail boot; runtime fail-closed. | | 9 | Raw routes refuse house middleware, bare recovery | VERIFIED | Unchanged. | | 10 | Route-table auth-group isolation | VERIFIED | Unchanged. | | 11 | Security review accurate | VERIFIED | 34/34 closed, mapped to existing passing tests; contradicting code paths independently confirmed fixed. | | 12 | Packages and regressions run cleanly | VERIFIED | `go vet ./...` clean and `go test ./... -count=1 -race -short` pass in summercms.go and fonoteka.go. | **Score:** 12/12 ### Requirements Coverage All seven IDs (HTTP-03..HTTP-09) appear in PLAN frontmatter and in REQUIREMENTS.md mapped to Phase 6; none orphaned. | Requirement | Status | Evidence | | --- | --- | --- | | HTTP-03 | SATISFIED (public handlers deferred to Phase 13) | Shared handler, exclusivity tests. | | HTTP-04 | SATISFIED | Five buckets, stacking, invalid definitions rejected. | | HTTP-05 | SATISFIED | Single accessor, exact denial bodies. | | HTTP-06 | SATISFIED (OAuth routes deferred to Phase 8) | wire helpers, raw infrastructure. | | HTTP-07 | SATISFIED | Allow-list, cap, timeout, full non-public/zoned rejection. | | HTTP-08 | SATISFIED (warning: OpenAPI covers one live route) | Generation/validation script and artifact. | | HTTP-09 | SATISFIED | CORS values and body cap enforced over named middleware. | Note: REQUIREMENTS.md traceability still shows HTTP-04 and HTTP-06 as "In Progress" while their checklist boxes are checked. This is metadata only; it should be updated to Complete. ### Anti-Patterns Found No unreferenced TBD/FIXME/XXX in phase files. All previously listed blockers and warnings (body cap order, limiter fail-open, overflow, IP table, ServeMux panic, typed-nil guard, factories built twice, zero body config) verified fixed in source. ### Human Verification Required None. ### Gaps Summary All four gaps from the prior verification are closed in code and covered by regression tests; no regressions found. Remaining items are deferred by roadmap to Phases 8, 12, 13, 14. --- _Verified: 2026-09-21_ _Verifier: Claude (gsd-verifier)_