Skip to content

D1096 — The routed surface and /health follow the caller's token

Decision. A routed connection serves the effective set: the KBs named by ?kbs= (after alias resolution) or every mounted KB, intersected with the KBs the principal can read. The kb enum, the one-KB rule (D288) and the tool union (D187) are computed on it. A principal that can write none of the set gets a read-only token view (no write tool listed; a write call still reaches the target KB, which answers read_only_token; no initialize instructions), and the bridge's ?access=read view (D1018) wins when both apply. A principal that reads no mounted KB gets a denied view: forbidden: no_kb_access from the metadata gate with a hint naming no KB, tool not found on a call, never an HTTP 403 (D118). A ?kbs= name the principal cannot read is unknown, exactly like an unmounted one, and an alias never resolves to an unreadable target. With auth on, GET /health gives an anonymous caller only status, ready, version, started_at, mount_mode, routed_path; a valid token adds kbs filtered to what it reads (always a list, never null) and latest_version. Auth off is unchanged. To make that possible the middleware attaches, on a public path with auth on, the principal of a valid bearer and no principal otherwise (never the local admin, never a 401).

Why. A host that hands the model only tools got a menu of tools it could never use and the names of KBs it has no business knowing, and an unauthenticated probe received every KB name, capability and the audit sink state. Views stay cached by (effective set, mode); principals are static configuration, so the count is bounded and a cached Server never carries anything per-request.

Alternatives rejected. A 401 on /health for an invalid token: a probe or a client with a rotated token must still get its liveness answer. Filtering tools/list per request instead of per cached view: the connection's guide (#1097) is per view. A new HTTP status for the denied view: D118.

Consequences. Amends D187 ("authorized as can reach at least one routed KB", "a principal scoped to one KB lists the union"); keeps D118, D288, D756, D772, D1018, D343. A tokenless /health no longer lists KBs, so readiness waits key on started_at; kb list's MOUNTED column needs a token or an auth-off server. A provisioned client bound to a KB its token cannot read now fails at connection with the D756 400. Any cache in front of /health must key on Authorization.