review 008 resolution: - AH-1: door_auth_middleware on extras doors resolves Authorization: Basic base64(user:pass) — password field as the token (GitHub-PAT shape, git-lfs / git smart-HTTP clients) — through the same IdentityProvider::resolve_from_token backend as Bearer; no new trait method, resolve-fails -> None fallback preserved. Bearer surfaces stay Bearer-only: the gateway endpoints, /openapi.json, /healthz, the MCP nest, and the WS upgrade path never resolve Basic. The 'Bearer-only is the auth mechanism' doc line flips (ADR-073). - AH-2 ride-along: extras door route tables are static — the merged router owns the decoy fallback, a second fallback panics at construction; documented on with_extra_routes and ADR-046 §1. docs: ADR-073, ADR-046 §1/§4 amendment, ADR-004 presentation table, review 008 marked resolved; new server::* re-exports; dep:base64 behind the server feature. Verification: cargo test (449 pass, incl. door Basic resolve-through and gateway-stays-Bearer-only pins), test --all-features (528), clippy --all-targets -D warnings, fmt --check, fuzz corpus replay (21/21), cargo doc.
4.0 KiB
ADR-073: Door-Surface Basic Auth Tolerance (git / git-lfs Clients)
Status
Accepted
Context
Review 008 AH-1, from alkgit's LFS POC (POC-L): a real git-lfs
3.7.0 client authenticates the batch endpoint with Basic
credentials (URL userinfo — the spec-shape behavior of the official
client; config http://user:pass@host/repo). The shared identity
middleware was Bearer-only — the module doc said so explicitly
("Bearer-only is the auth mechanism") — so a door mounted under the
shared auth layer received the batch request with the middleware
already having folded in None, and the door had to re-parse the
Authorization header itself (Basic or Bearer) to get any identity.
The middleware is shared by the gateway endpoints and to_mcp. Every
HTTP-door surface whose real client authenticates with Basic (LFS
today; git's smart-HTTP transport is tomorrow's git door) would
silently re-implement the fallback locally — the quiet-bypass shape
alkcall review 012 records for the ownership seam, one layer up in the
same stack.
Decision
Split the auth surface into token surfaces and the door surface,
and teach the door surface Basic — through the same resolution
backend, with no new IdentityProvider method.
bearer_auth_middlewarestays Bearer-only and continues to cover the token-auth surfaces: the gateway endpoints,/openapi.json,/healthz, and theto_mcpnest. A Basic header contributes no identity there./call,/batch,/subscribe,/publish,/mcp, and the WS upgrade path are token surfaces — this is the "no blanket method" constraint: a Basic credential never gains identity anywhere the deployment has not explicitly set up for it.door_auth_middleware(new) is applied bybuild_routerto the extras-door router (HttpAdapter::with_extra_routes) — the surface legacy clients authenticate on.- Both middlewares resolve through
IdentityProvider::resolve_from_token(). Basic parsing:Basic base64(user:pass)— the password field (the GitHub-PAT shape; the user segment is ignored) is decoded and fed as theAuthTokenraw bytes. A colon-less value is treated as a bare password. No new trait method: the provider's grant table governs a Basic credential exactly as it governs the same credential presented as Bearer — and the same backend mechanism that grants privileges to tokens grants them to these credentials (SOCKS5 userinfo-style integrations can follow the same pattern later). - Fallback semantics unchanged: no header →
None; unparseable or unresolvable credential →None(unauthenticated, not an error). A parse-time failure never becomes a 4xx of its own. - Doors may opt out with their own middleware stack as before (ADR-046 §4).
Consequences
Positive:
git-lfs/gitdoors work against a deployment whose provider maps password-tokens throughresolve_from_token, with zero door-side header re-parsing.- Scoping is structural (per-middleware), not per-path-inspection: Basic tolerance exists only where the assembly layer mounted the door surface.
Negative:
- A door surface deployment that does not want its door credentials resolvable as Basic must now ensure the provider does not resolve those values as tokens — or opt the door out of the shared layer.
- Scheme prefixes remain case-sensitive ("Bearer "/"Basic "), matching
the pre-existing Bearer parsing; strictly RFC-noncompliant
lowercase-scheme clients parse to
None.
References
- Review 008 — AH-1 evidence and disposition space
- ADR-004 — the shared-core resolution backend this rides
- ADR-046 — the extras-door surface the door middleware covers (§4 amended; AH-2 static-route constraint recorded there)
- alkcall review 012 — the same-round quiet-bypass analysis this avoids repeating at the door layer