docs(06): finalize phase plan after verification
This commit is contained in:
@@ -2,14 +2,14 @@
|
|||||||
gsd_state_version: 1.0
|
gsd_state_version: 1.0
|
||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: planning
|
status: executing
|
||||||
stopped_at: Phase 6 context gathered
|
stopped_at: Phase 6 context gathered
|
||||||
last_updated: "2026-09-19T12:04:36.559Z"
|
last_updated: "2026-09-19T15:16:57.658Z"
|
||||||
last_activity: 2026-09-18
|
last_activity: 2026-09-19 -- Phase 06 planning complete
|
||||||
progress:
|
progress:
|
||||||
total_phases: 15
|
total_phases: 15
|
||||||
completed_phases: 5
|
completed_phases: 5
|
||||||
total_plans: 23
|
total_plans: 28
|
||||||
completed_plans: 23
|
completed_plans: 23
|
||||||
percent: 33
|
percent: 33
|
||||||
---
|
---
|
||||||
@@ -27,8 +27,8 @@ See: .planning/PROJECT.md (updated 2026-09-16)
|
|||||||
|
|
||||||
Phase: 6
|
Phase: 6
|
||||||
Plan: Not started
|
Plan: Not started
|
||||||
Status: Ready to plan
|
Status: Ready to execute
|
||||||
Last activity: 2026-09-18
|
Last activity: 2026-09-19 -- Phase 06 planning complete
|
||||||
|
|
||||||
Progress: [██████████] 100%
|
Progress: [██████████] 100%
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ middleware entries at call sites, matching D-05.
|
|||||||
|
|
||||||
Create clientip.go: ClientIP(r, trusted) -- parse r.RemoteAddr via net.SplitHostPort to get the bare IP; if trusted is empty or the parsed IP does not match any prefix in trusted (netip.Prefix.Contains), return that IP; otherwise read X-Forwarded-For, split on comma, trim each hop, walk the list RIGHT TO LEFT, return the first hop whose parsed address is NOT contained in any trusted prefix; if every hop is trusted (or the header is empty/absent), fall back to the original RemoteAddr IP. TrustedProxies(cfg *compass.Config): read http.trusted_proxies as a []string (mirror corsOrigins's []string/[]any type-switch pattern already in router.go), netip.ParsePrefix each entry, skip invalid entries, return the slice (nil/empty when the key is absent).
|
Create clientip.go: ClientIP(r, trusted) -- parse r.RemoteAddr via net.SplitHostPort to get the bare IP; if trusted is empty or the parsed IP does not match any prefix in trusted (netip.Prefix.Contains), return that IP; otherwise read X-Forwarded-For, split on comma, trim each hop, walk the list RIGHT TO LEFT, return the first hop whose parsed address is NOT contained in any trusted prefix; if every hop is trusted (or the header is empty/absent), fall back to the original RemoteAddr IP. TrustedProxies(cfg *compass.Config): read http.trusted_proxies as a []string (mirror corsOrigins's []string/[]any type-switch pattern already in router.go), netip.ParsePrefix each entry, skip invalid entries, return the slice (nil/empty when the key is absent).
|
||||||
|
|
||||||
In router.go: add a limiter *FixedWindowLimiter field to Router. In Assemble() (before 06-03 introduces the BuildRouter split -- if 06-03 has already executed in this working tree when this task runs, make the equivalent change in BuildRouter instead, since Assemble will then just call BuildRouter+compile), after constructing r := New(corsOrigins(app)), build trusted := TrustedProxies(app.Config), lim := NewFixedWindowLimiter(NewMemoryStore(2*time.Minute), trusted) (document the 2-minute sweep default inline as "longest bucket decay is 1 minute; sweep at 2x"), set r.limiter = lim, and call r.RegisterMiddlewareFactory("surf", "throttle", func(param string) pact.Middleware { return lim.Middleware(param) }) before the existing HasMiddleware/HasMiddlewareFactories/BucketProvider loops (BucketProvider loop is new: for each plugin implementing surf.BucketProvider, call lim.RegisterBucket(p.ID(), name, b) for every entry). Remove the unconditional h = noOpLimit(h) line from wrap(). Delete the now-dead noopLimiter type and noOpLimit function entirely, and delete nothing else from the existing Limiter interface declaration or its doc comment -- it remains, untouched, as the Phase 3 seam (per the interfaces block's naming-collision note; confirm via grep that noOpLimit/noopLimiter have no other call sites in the repo before deleting -- there are none as of Phase 3/06-01).
|
In router.go: add a limiter *FixedWindowLimiter field to Router. In Assemble() (before 06-03 introduces the BuildRouter split -- if 06-03 has already executed in this working tree when this task runs, make the equivalent change in BuildRouter instead, since Assemble will then just call BuildRouter+compile), after constructing r := New(corsOrigins(app)), build trusted := TrustedProxies(app.Config), lim := NewFixedWindowLimiter(NewMemoryStore(2*time.Minute), trusted) (document the 2-minute sweep default inline as "longest bucket decay is 1 minute; sweep at 2x"), set r.limiter = lim, and call r.RegisterMiddlewareFactory("surf", "throttle", func(param string) pact.Middleware { return lim.Middleware(param) }) before the existing HasMiddleware/HasMiddlewareFactories/BucketProvider loops (BucketProvider loop is new: for each plugin implementing surf.BucketProvider, call lim.RegisterBucket(p.ID(), name, b) for every entry). Remove the unconditional h = noOpLimit(h) line from wrap(). Delete the now-dead noopLimiter type and noOpLimit function entirely, and keep the existing Limiter interface declaration as the Phase 3 seam, changing only its doc comment (which currently claims "Phase 6 replaces the no-op with named buckets" and would be stale) to state that Limiter is a retained seam with no implementer after Phase 6 and that rate limiting is provided by FixedWindowLimiter through the parameterized throttle middleware (D-03, D-05) (per the interfaces block's naming-collision note; confirm via grep that noOpLimit/noopLimiter have no other call sites in the repo before deleting -- there are none as of Phase 3/06-01).
|
||||||
</action>
|
</action>
|
||||||
<verify>
|
<verify>
|
||||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && go vet ./... && go test ./surf/... -run TestFixedWindowLimiter -short && go test ./surf/... -run TestClientIP -short</automated>
|
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && go vet ./... && go test ./surf/... -run TestFixedWindowLimiter -short && go test ./surf/... -run TestClientIP -short</automated>
|
||||||
|
|||||||
Reference in New Issue
Block a user