Files
summercms/.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-05-SUMMARY.md

8.8 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
06-http-routing-auth-groups-and-rate-limiting 05 testing
coverage
security-review
route-table
isolation
parity
tdd-close
phase provides
06-http-routing-auth-groups-and-rate-limiting bouncer.Registry, FixedWindowLimiter, GroupRaw, wire helpers, path-scoped CORS, body limits, fetchguard.Fetch
coverage-gap tests for bouncer, surf, wire, fetchguard and fonoteka auth/middleware
full assembled route-table mutual-exclusivity test
06-SECURITY-REVIEW.md mapping T-06-01 through T-06-18 plus T-06-SC
phase-07-user-plugin
phase-08-oauth
phase-12-collections-albums
added patterns
phase-ending *_coverage_test.go files close named gap categories with a test or a one-line skip comment
06-SECURITY-REVIEW.md is the phase-close threat-to-test map (file:TestName or verbatim accept)
created modified
bouncer/registry_coverage_test.go
surf/limiter_coverage_test.go
surf/routetable_coverage_test.go
surf/cors_coverage_test.go
wire/response_coverage_test.go
fetchguard/fetch_coverage_test.go
plugins/golem15/fonoteka/classes/auth/token_guard_coverage_test.go
plugins/golem15/fonoteka/middleware/token_scope_coverage_test.go
plugins/golem15/fonoteka/routes_isolation_test.go
http_config_test.go
parity/php_debug_test.go
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md
parity/parity_test.go
Full route-table isolation uses surf.BuildRouter of the real plugins; app.Handler returns http.Handler and cannot call Routes()
T-06-05 remains accept as originating 06-01 (the 06-05 plan's 'three accepts' list omitted it)
PublicOnlyMode any-host-when-public is proven via skipReservedCheck httptest, not a live public IP dial
Gap categories (a)-(g) each have a named test or an explicit one-line comment in the coverage file
Phase-close security review table has exactly 19 T-06-xx rows; accept rationales are copied verbatim
HTTP-03
HTTP-04
HTTP-05
HTTP-06
HTTP-07
HTTP-08
HTTP-09
13 min 2026-09-19

Phase 6 Plan 05: Unit coverage, route-table isolation, and security review Summary

Phase-ending coverage of bouncer/surf/wire/fetchguard and fonoteka auth/middleware, a full assembled Routes() mutual-exclusivity test, and 06-SECURITY-REVIEW.md mapping every T-06-01..18 plus T-06-SC to a named passing test or a restated accept

Performance

  • Duration: 13 min
  • Started: 2026-09-19T19:02:51Z
  • Completed: 2026-09-19T19:16:44Z
  • Tasks: 3
  • Files modified: 13

Accomplishments

  • Closed framework coverage gaps (a)-(g): neither-interface Register, MemoryStore sweep (purge 0% → 100%), RegisterHouseMiddlewareFactory duplicate-name, unmatched CORS path, Time +00:00/Z round-trip, PublicOnlyMode private-IP and any-host, empty-router Routes() plus empty-raw-group introspection on Group.raw
  • App-side: TokenGuard future/past ExpiresAt and RevokedAt against real Postgres; InvScope fail-closed on a non-*ApiToken credential; PublicShareHeaders late headers after a partial body write; TestFullRouteTableAuthGroupMutualExclusivity walks the real assembled table
  • Parity corpus: recorded 154/154 passing 2 failing 0 unrecorded 0 pending 152 — both genres routes (jwt and personal_token) passing, no regression from 06-01
  • 06-SECURITY-REVIEW.md maps 19 threat IDs; grep confirms no bearer/hash logging and inv.must-change-password only inside HouseMiddlewares()
  • go vet ./... and go test ./... -race green in both repos (testcontainers included)

Task Commits

Each task was committed atomically:

  1. Task 1: Framework coverage gaps - 98dd098 (test, summercms.go)
  2. Task 2: App coverage, isolation, short-safe corpus - 760c1ff (test, fonoteka.go)
  3. Task 2 follow-up: named tests for T-06-09 / T-06-13 - e160e81 (test, fonoteka.go)
  4. Task 3: Security review - 74d1eb3 (docs, summercms.go)

Plan metadata: (this commit)

Files Created/Modified

  • bouncer/registry_coverage_test.go — neither-interface, nil registry, authenticate default
  • surf/limiter_coverage_test.go — MemoryStore sweep, TrustedProxies, ClientIP empty XFF
  • surf/routetable_coverage_test.go — house factory duplicate, empty router, empty raw group
  • surf/cors_coverage_test.go — unmatched path independent of fonoteka; exact/pattern origins
  • wire/response_coverage_test.go — Time null/invalid/Z/+00:00; WriteJSON encode error
  • fetchguard/fetch_coverage_test.go — PublicOnlyMode both halves; hostAllowed; mapTransportError
  • plugins/golem15/fonoteka/classes/auth/token_guard_coverage_test.go — future/past/revoked rows
  • plugins/golem15/fonoteka/middleware/token_scope_coverage_test.go — wrong credential type; late headers
  • plugins/golem15/fonoteka/routes_isolation_test.go — full Routes() exclusivity
  • parity/parity_test.go — skip coverage counts under -short
  • parity/php_debug_test.go — APP_DEBUG=false pin (T-06-09)
  • http_config_test.go — 134217728/134217728, no INTERIM (T-06-13)
  • 06-SECURITY-REVIEW.md — 19-row threat-to-test map

Decisions Made

  • Isolation test calls surf.BuildRouter on activated real plugins (golem15.user, golem15.fonoteka) because app.Handler returns http.Handler and cannot expose Routes(). Importing app from package fonoteka would cycle.
  • T-06-05 stays accept, copied verbatim from 06-01. The 06-05 plan's "three accepts" list (T-06-03, T-06-08, T-06-SC) omitted it; the originating disposition wins.
  • PublicOnlyMode "any host accepted when public" uses skipReservedCheck + httptest TLS. A live public-IP dial is not asserted in unit tests.

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] TestParityCorpus coverage subtest failed under -short

  • Found during: Task 2 verify (go test ./... -race -short)
  • Issue: Ported replay skips via parityDB under -short, so cov.Passing stayed 0 while the coverage subtest required passing == ported. Pre-existing (flagged in 06-02 SUMMARY); this plan's verify command includes -short.
  • Fix: Skip the coverage counts subtest when testing.Short(); live replay remains the non-short gate.
  • Files modified: parity/parity_test.go
  • Verification: go test ./... -race -short green; go test ./parity/... -run TestParityCorpus → passing 2
  • Committed in: 760c1ff (Task 2)

2. [Rule 2 - Missing Critical] T-06-09 and T-06-13 had no named test for the security-review map

  • Found during: Task 3 (threat-to-test mapping)
  • Issue: APP_DEBUG=false lived only in php_parity.sh; production 134217728 lived only in yaml. Mitigate dispositions require file:TestName.
  • Fix: TestPHPParityPinsAppDebugFalse and TestProductionBodyLimitsOperatorConfirmed.
  • Files modified: parity/php_debug_test.go, http_config_test.go
  • Verification: both tests pass
  • Committed in: e160e81

Total deviations: 2 auto-fixed (1 Rule 3, 1 Rule 2) Impact on plan: Both required for the plan's own verify command and the 19-row security review. No production-code change. No scope creep.

Issues Encountered

None beyond the documented deviations.

scripts/check-phase2.sh --fresh-php is present (PHP artisan at /media/nvme/dev/golem15/fonoteka, port 8423 free, docker up). It was not run as a completion gate, matching Phase 3's precedent that --fresh-php is a sign-off convenience, not a plan gate.

User Setup Required

None - no external service configuration required.

Next Phase Readiness

  • Phase 6 is complete: guard registry, limiter, raw groups, CORS/body limits, SSRF helper, full coverage, and the security review.
  • Ready for /gsd:verify-work 6 and /gsd:plan-phase 7.
  • No blockers. OAuth client-credentials/token-exchange remains a Phase 8 pre-planning check.

Self-Check: PASSED

  • FOUND: bouncer/registry_coverage_test.go
  • FOUND: surf/limiter_coverage_test.go
  • FOUND: surf/routetable_coverage_test.go
  • FOUND: surf/cors_coverage_test.go
  • FOUND: wire/response_coverage_test.go
  • FOUND: fetchguard/fetch_coverage_test.go
  • FOUND: ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/token_guard_coverage_test.go
  • FOUND: ../fonoteka.go/plugins/golem15/fonoteka/middleware/token_scope_coverage_test.go
  • FOUND: ../fonoteka.go/plugins/golem15/fonoteka/routes_isolation_test.go
  • FOUND: .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md
  • FOUND: 98dd098
  • FOUND: 760c1ff
  • FOUND: e160e81
  • FOUND: 74d1eb3
  • FOUND: threat table 19 rows (grep -c '^| T-06-' = 19)
  • FOUND: parity recorded 154/154 passing 2
  • FOUND: go vet ./... and go test ./... -race green in both repos

Phase: 06-http-routing-auth-groups-and-rate-limiting Completed: 2026-09-19