# ADR 0022: The gateway takes its dependencies, not the Server Status: accepted (2026-09-21). Canonical copy in git at `docs/adr/0022-gateway-dependencies-not-the-server.md`. Part of the [architecture quality plan](/plans/architecture-quality.md), track 3d-3a; the study and the owner's decisions (F10, F11) are in the [3d proposal](/plans/architecture-quality/3d-boundary-proposal.md). ## Context The broker package is one package of about 29,000 lines. Its 2026-08 sweep named four seams (core, OAuth server, MCP gateway, storage), and the plan schedules the split as track 3d-3. Before the directories can move, the code has to stop reaching across the seams. The MCP gateway held a `*Server` and read through it: the config, the world registry, the write token store, the clock, the provisioner, the auth and rate limit middleware. The Server in turn held the gateway's state: the write token store, the production QUIC pool, the provisioner and the gateway profile, which `newMCPGateway` wrote back into the Server as a side effect so `/me/install` could scope worlds the way the gateway did. The memory broker enabled provisioning through a `Setup` hook that mutated the Server after construction. `NewServer` took seven positional arguments, four of them nil in most tests. Config carried six `*Ref` methods that resolve Secret locations for stores that will live in three different packages, and several helpers took `*Config` only to reach the registry inside it. ## Decision - `gatewayDeps` names everything the gateway needs: the world registry, the issuer, the public URL, the MCP config, a clock, a logger, the write token store, the provisioner (nil in static mode), and the auth and rate limit middleware as `func(http.Handler) http.Handler`. `Run` builds it from the Server and the shared Secret store; tests build it by hand. - `Run` owns the gateway's lifecycle: it builds the write token store and the QUIC pool, closes the pool after the MCP listener drains, and wires the provisioner when the binary supplies a bucket backend (`RunOptions.Buckets`) and the config enables provisioning. The `Setup` hook, `EnableProvisioning`, `MCPGateway`, `MCPGatewayWith` and `CloseMCPGateway` are gone. - The Server keeps only the OAuth surface and the management API. It learns the gateway profile's tenant scoping at construction (`ServerDeps.TenantScoped`) from the same profile `Run` hands the gateway, so the two cannot diverge. - `NewServer(cfg, ServerDeps)`: the signer, verifier, store, optional discovery and id_token signer, logger and scoping are named fields. - Secret locations are free functions in `secret_refs.go`, next to the pinned Secret names and keys, so each future package calls them without owning `Config`. `readableWorlds`, `authorizedWorlds`, `lookupWorld`, `tenantWorldFor` and `newWorldPool` take the registry (and the issuer where identity keys are built), not `*Config`. - `Claims` and the context and fingerprint helpers live in `claims.go`; `config.go` is four files: types, load, defaults, validate. - The two authorize redirect helpers are an `authorizeReply` value carrying the validated redirect URI and client state. ## Consequences - Broker behaviour, tool output, wire goldens and log text are unchanged; the memory broker's "provisioning enabled" line now comes from `Run` with the same fields. One ordering change at startup: the Secret store is built before OIDC discovery, so a broker with both misconfigured reports the store first. - Test fixtures are one file, `helpers_test.go`, with a `gatewayFixture` that mirrors `Run`'s wiring, a shared `fakeClock` and one `ServerDeps` builder. Tests set the clock on the fixture instead of on the Server after the fact. - The directory split (3d-3b) can now be a near pure move: `gateway` imports `core` for the registry and config types and nothing from the OAuth server; `Run` is the one place that knows all four packages. - Lint ratchet 123 to 121 entries: `NewServer`'s argument count and the authorize helpers' argument count are gone, `Run` is two statements shorter, `buildServer` returns two values.