diff --git a/docs/reviews/008-http-door-consumer-review.md b/docs/reviews/008-http-door-consumer-review.md new file mode 100644 index 0000000..5843f1f --- /dev/null +++ b/docs/reviews/008-http-door-consumer-review.md @@ -0,0 +1,94 @@ +# Review 008 — First HTTP-door consumer evidence: shared auth vs LFS Basic, and the extras route-fallback constraint + +## Status + +Open — filed 2026-10-17. Report-only consumer input from alkgit's LFS +POC (POC-L, 2026-10-16; findings at +`/workspace/@alkdev/alkgit/docs/research/pocl-findings.md`; the POC +crate is `/workspace/lfs-poc`, which served a real `git-lfs` 3.7.0 +client through `with_extra_routes` doors). Ask ledger source: alkgit's +`docs/research/substrate-recomposition.md` §Upstream-push +candidates #6/#9 (the alkhttp-named items; the gateway-dispatch half +of #6 is filed where it belongs — alkcall review 012). + +## Scope + +Two findings, both from the same consumption round (an LFS batch-API +door on the extras router). Neither was discovered by a source sweep; +both anchors were re-verified by targeted read this session. Severity +and shape are the consumer seat's; the disposition belongs to this +crate's own session. + +## AH-1 [small, contract-visible] — The shared bearer middleware is Bearer-only; LFS clients authenticate with Basic on the batch + +**Anchor.** `src/server/auth.rs` — the shared identity middleware +(`bearer_auth_middleware`); the module doc states the semantics +explicitly: *"Malformed `Authorization` header (not `Bearer `) +→ `None` (treated as no-token, not an error — Bearer-only is the auth +mechanism)"* (lines 1–20, verified this session). + +**Evidence.** Real `git-lfs` 3.7.0 authenticates the batch endpoint +with **Basic** credentials (URL userinfo — the spec-shape behavior of +the official client; its config is `http://user:pass@host/repo`). An +extras door mounted on the shared middleware therefore receives the +batch request with the middleware already having resolved `None` +(the Basic header is not `Bearer`) — the door had to parse the +Authorization header a second time (Basic *or* Bearer) to get any +identity at all. The POC's door resolved both schemes locally and +passed the real client; the shared middleware contributed nothing on +this request shape. + +**Why it matters beyond LFS.** The middleware is shared by gateway +endpoints and `to_mcp`; any HTTP-door surface whose +real-world client authenticates with Basic (LFS today; git's +smart-HTTP transport's basic auth is tomorrow's `git` door) silently +loses identity resolution at the middleware and every door +re-implements the fallback — the exact quiet-bypass shape review 012 +(alkcall) records for the ownership seam, one layer up in the same +stack. + +**Recommended shape (own session, to be re-derived)**: tolerate Basic +userinfo in the shared middleware — parse `Basic base64(user:pass)` +into the identity provider's resolve path (or expose a documented +per-door hook that receives the raw header before the None fold-in), +keeping the current "resolve fails → None" fallback semantics. The +doc line "Bearer-only is the auth mechanism" should flip to match +whatever lands. Small surface; the decision is whether Basic +resolution belongs in the shared middleware (uniform) or stays a +door concern (explicit). + +**Verification status**: middleware semantics re-read this session; +the client behavior is POC-L's recorded route-shape fact (real +client, live). Re-verify by pointing a stock `git-lfs` at a +shared-middleware door during resolution. + +## AH-2 [recorded constraint, no ask yet] — Extras doors cannot carry a route fallback; door route tables must be static shapes + +**Anchor/evidence.** POC-L, live: the merged extras router already +owns a fallback route (the decoy), and axum refuses a second merge — +a door attempting `fallback_layer`/merge fallback on the merged +router panics **at construction**. Consequence: door route tables +must be statically enumerated; multi-segment repo namespaces +(`/user/repo/objects/batch` style) need enumerated pattern routes +(`/{user}/{repo}/...` shape), not a dynamic-fallback match. The POC +door's static shapes worked for every e2e case. + +**Disposition space.** This is a structural fact of the current +router assembly, currently undocumented on the door-facing surface — +worth one doc line in the extras/hooks documentation ("route tables +are static; no second fallback; enumerate multi-segment patterns +explicitly") regardless of whether any mechanism change is ever +wanted. Not a mechanism ask today; recorded so the next door author +does not rediscover the construction panic. + +## What this review asks for + +| # | Item | Class | +|---|---|---| +| AH-1 | Basic tolerance (or a documented pre-resolution hook) in the shared identity middleware | small change + doc flip, own session | +| AH-2 | doc line: extras route tables are static; no second fallback | docs-only, ride-along | + +Nothing here blocks any door surface that resolves identity +door-side (the proven compensation), but the shared-middleware trap +(AH-1) compounds alkcall review 012's gateway trap for every future +External-facing door — the two are worth one resolution round each. \ No newline at end of file