docs backend evidence community safety SEC02C_BUDGET_SPLIT - AlexandreZanata/Abastevo GitHub Wiki
SEC02-C — Global/per-client split, viability and edge proof
Date: 2026-10-11. Status: LOCAL_DONE. Scope: deliberate global
breaker + viability pins + real local Caddy→API proof — no shared
VPS edge change. Head: maintained dev + this task.
Plan: remediation plan
(SEC02, AUD-03). Contract: B-BR-015 (identity quotas); Caddy edge
(infra/caddy/Caddyfile). Constraint: raw IPs stay hashed-only;
global shedding never leaks identity; multi-replica edge sizing
stays an operator decision.
Validation: PASS
Changes
identity/adapters/http/breaker.go(new): process-localGlobalBreaker(hourly per-operation ceilings, mutex-guarded, window reset, concurrent-safe) +BreakerError(503identity.overloaded+ Retry-After). Zero/nil disables an operation (no global cap; fairness still enforced).identity/adapters/http/http.go:Handler.GlobalBreaker;quota()sheds global-first (503) before per-subject fairness (429), so overload never consumes fairness budget.platform/config:ANPFUEL_GLOBAL_QUOTA_{CHALLENGE,REGISTER,WRITE}(non-negative ints, default disabled/0, startup-validated).cmd/api: builds the breaker from config into the handler.- Tests: breaker disabled/trip/reset/concurrency pins; handler
viability ceremony (real quota path: 3 challenges + register +
rotate = 10 units; 6/60 challenge + 4/10 register headroom);
503 shape (code/header/no-echo); real docker Caddy
(pinned
caddy:2.10.2-alpine) → API proof: forged XFF replaced by observed loopback (billed subject matches), direct forgery bills the peer (spoof ignored end-to-end).
Validation (actual)
go test ./internal/modules/identity/... ./internal/platform/config/...green.-race -tags=integrationgreen: identity adapters (existing quota/registration/rotation/retention re-green) +TestLocalCaddyForwardsObservedClientPASS with the real edge (0.3s, image cached).go build ./...,go vet,gofmt -lclean,git diff --checkclean,scan-secrets.shpassed (synthetic TEST-NET IPs only).- RED pre-GREEN: breaker tests failed before the handler shed (no 503 path); viability counts drifted before valid JWK/ purposes (proves the test bills the real path, not stubs).
Limits / owed
- Process-local breaker covers single-process overload; multi-replica/global-DDoS protection belongs to the separately authorized edge/network layer (not claimed here).
- Global ceilings default disabled (deliberate opt-in); numeric values remain operator-sized, not advertised capacity.
- Shared-VPS edge change out of scope; staging rollout rides SEC09. No live readiness inference.
Next microtask: SEC03-A atomic reservations.