Skip to content

rest: trustedProxies cache relies on a conventional once-write invariant — consider making it structural #197

@SyniRon

Description

@SyniRon

This was generated by AI — surfaced during the #194 swarm review (follow-up to #190).

Observation

rest/clientip.go keeps the parsed trusted-proxy set in a package-level var trustedProxies []*net.IPNet, written once by InitTrustedProxies() at startup and read thereafter by clientIP. The "write once before any listener serves, read-only after" invariant is enforced only by call ordering + a comment, not by the type — any code in package rest could reassign it, and the read/write are unsynchronized.

Why it's benign today

  • The composition root wires InitTrustedProxies() before serving (and servers/server_test.go has a source-level guard pinning that ordering and the fatal-on-malformed behavior).
  • A read before init yields nil → trust-nothing → the safe direction.
  • Boot is single-threaded, so there is no real race in the current lifecycle.

Possible direction (for triage — low priority)

Per the type-design review, wrap the cache in atomic.Pointer[[]*net.IPNet] behind an unexported accessor (~5 lines), turning the once-write/read-after lifecycle from a documented convention into a structural one and removing the theoretical race. Only pays off if a concurrent writer ever appears on this surface (e.g. the deferred per-key rate-limiting work in PRD #112).

Design context: ADR 0005 (docs/adr/0005-trusted-proxy-client-ip.md). Surfaced by the type-design review on PR #194. needs-triage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent to implementrefactorCode restructure without functional change

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions