fix(server): auth-cover extra_routes + reserved-path rule (SRV-01, SRV-06)

- apply bearer_auth_middleware route_layer AFTER the extra_routes merge,
  so assembly-layer custom routes resolve the bearer token by default
  (ADR-046 §4); per-route opt-out via the route's own layer remains
- enforce RESERVED_PATHS per-method at build time: a probe MethodRouter
  occupied on all methods is pre-merged against extras, so a custom
  POST /search panics like a same-method overlap (ADR-046 §3)
- tests: auth resolves through an extra route; an extra route with its
  own layer opts out; reserved-path merge panics; non-reserved
  different-method merge stays legal; MCP bearer-gate test stays green
- ADR-046 §3: one sentence restating the per-method rejection rule

Verification: cargo test (215) ok, cargo test --all-features (260 +
integration) ok, clippy -D warnings (default + all-features) ok,
cargo fmt --check ok.
This commit is contained in:
2026-08-29 08:28:15 +00:00
parent d7ee302046
commit e4284a0d3c
3 changed files with 244 additions and 14 deletions
@@ -124,7 +124,11 @@ patterns appear, and those custom routes are subject to the same
collision rule.) If a custom route collides with a reserved path, the
default surface wins — the custom route is silently shadowed (or the
construction panics/warns; the specific collision-handling is a
two-way-door implementation detail). A deployment that wants
two-way-door implementation detail). alkhttp panics at construction for
both the same-method overlap (axum's merge) and the different-method
case (a pre-merge probe over the reserved set), so a custom
`POST /search` next to the default `GET /search` is rejected, not
silently served. A deployment that wants
`/v1/chat/completions` namespaces it away from the reserved set, which
is natural (`/v1/...` doesn't collide).