feat(server): add server foundation for S12 OCI local (MR 1/5)
Why
Foundation slice of the S12 OCI-local stack. Anchors the contract surface every subsequent OCI handler MR depends on. This MR replaces the previous version of !124 after Pawel asked the stack to be split with file-level boilerplate factored out into !141 (MR-0) so reviewers could land mechanical changes first and focus the rest of the stack on Go code.
Issue: #19 (closed) Spec: S12 (already merged via !48 (merged))
Stack and merge order
| # | MR | Branch | Targets | Blocks |
|---|---|---|---|---|
| 0 | !141 (merged) | 19-oci-boilerplate |
main |
!124 (closed) |
| 1 | !124 (closed) ← you are here | 19-oci-foundation |
19-oci-boilerplate |
!125 (closed) |
| 2 | !125 (closed) | 19-oci-database |
19-oci-foundation |
!126 (closed) |
| 3 | !126 (closed) | 19-oci-cas |
19-oci-database |
!127 (closed) |
| 4 | !127 (closed) | 19-oci-format |
19-oci-cas |
!128 (closed) |
| 5 | !128 (closed) | 19-oci-wiring |
19-oci-format |
n/a |
What's in MR-1
25 files, ~4,800 insertions, all Go code. One squash commit on top of MR-0.
internal/auth/: anticipatory contract for S08.Validator,Identity,HasGrant, theMiddleware, and theBootstrapValidatorwith constant-time-compare. The auth-decision label constants live ininternal/observabilityandinternal/authconsumes them so the two packages cannot drift. Future S08 swap preserves theIdentityshape, the middleware position, and the/v2/auth/tokenURL.internal/middleware/: the package's middlewares (Chain,BodySizewith exempt-prefixOriginalBodystash,HeaderHardening,Recovery,RequestID,RoutePattern). TightAllocsPerRunbudgets (1 and 0 respectively) pin the two hot-path optimizations (exempt-onlyOriginalBodystash andRoutePatterncontext-rewrap fast-path) so a regression fails CI deterministically.internal/observability/: foundation slice of S03's metric set. The metrics arehttp_requests_total,http_request_duration_seconds(with OTel-trace-id exemplars on sampled spans),panics_total,auth_decisions_total, anddb_connection_pool_size. The package exposes cardinality allowlists asAllowed*slice helpers, and cardinality-audit tests assert the materialized series count matches the allowlist sizes. Off-allowlist prefixes and methods collapse to_other_. Off-allowlist decisions and outcomes drop the call entirely so a typo fails the audit rather than landing a synthetic bucket.internal/gc/:Lockinterface plus anInMemoryLockplaceholder.ErrLockTimeoutcovers bothcontext.Canceledandcontext.DeadlineExceededby design so handlers map every "lock not obtained" outcome to a single 503 UNAVAILABLE response.internal/testutil/: DSN parsing helper and test-DB plumbing.go.mod: promotesprometheus/client_{golang,model}andotel/tracefrom indirect to direct since the new packages consume them.
The proto schema and generated code, .gitlab-ci.yml validate-stage hardening, and the dev-tooling configs all live in MR-0 (!141 (merged)).
Test plan
- CI green on this MR (build, vet, lint, test, bench-regression, fuzz seed corpus). Both
test:bench-regressionandtest:fuzzactivate on this MR (it addsinternal/{auth,middleware,observability}/**/*.go). -
benchstatMR comment appears in this MR after CI runs (verifiesBENCHSTAT_NOTE_TOKENplumbing). The comment should show the foundation benchmarks with no target-side baseline (first MR introducing them). The job tolerates that gracefully. - Allocation budgets pass deterministically: auth happy path ≤ 8, observability HTTP middleware ≤ 6, BodySize non-exempt = 1, RoutePattern holder-seeded = 0.
- Cardinality-audit tests pin the (method × route × status_code) and (prefix × decision × outcome) series counts.
-
go mod tidyis a no-op locally. - !125 (closed) builds cleanly on top of this branch.
Reviewer-feedback rounds
This branch absorbed three review passes before being rebuilt on MR-0. The most recent round (post-second-pass review) addressed:
- W1: chain-position references in
routepattern.gonow match the S01 spec and the metrics-middleware doc. - W2: this MR description documents the plan-file waiver.