/mcp's bearer was built in main.go and the buildMux tests used stubs, so
dropping it would have kept CI green. buildMux now takes the MCP handler
and wraps it with the same BearerMiddleware and credential as the REST
API. "/mcp" and "GET /metrics" left the public allowlist, so passing
either as a public route is refused. buildMux also registers GET
/metrics and returns the metrics-wrapped handler, so main passes its
result to ListenAndServe unchanged.
Flip-tested: registering /mcp unwrapped turns
TestBuildMuxRefusesMCPWithoutAValidToken red, and dropping the metrics
wrap turns the four metrics tests red.
Comments now claim only what is tested. The ListenAndServe line and the
symlink tripwire wiring in main (#154 comment) are still untested and
tracked in #182.
Closes#154
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PR #181 review (comment 15483):
- TestBuildMuxLogsARESTAuthRejection asserted only that the "Bearer <tok>"
header form was absent, which a field-logging chassis could never emit.
Replaced by TestBuildMuxRejectionLogLineOmitsTheBarePresentedToken (a
sentinel wrong token; neither it nor the static token may appear) and
TestBuildMuxAcceptedLogLineOmitsTheBareStaticToken. A local chassis
v0.7.1 copy logging rawToken as token_fp (deny, then accept) turns each red.
- labelRESTPattern doc: the label bound holds for refused requests only;
the authenticated-404 raw-path gap is hyperguild#185.
- Remove internal/startupretry: nothing imports it since the chassis bump.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1. Rejections are logged. chassis v0.2.0 refused without a log line, so
since #149 an unknown REST caller got silent 401s. v0.7.1 writes
`mcp auth rejected` (reason, remote, token fingerprint, path) and
`mcp auth accepted` per authenticated request. Tested through
buildMux.
2. Fallout: since chassis v0.7 (mcp-chassis#4) NewJWTValidator no longer
fails on OIDC discovery; the issuer resolves lazily and a JWT gets
503-and-retry until it does. #83's boot retry loop therefore never
retried, and its tests failed. buildJWTValidator now builds once and
logs an issuer still unresolved at boot. Behaviour change: a
misconfigured issuer no longer exits the process; JWTs get 503, the
static bearer keeps working. internal/startupretry is now unused.
3. Metrics: authenticated REST requests were already labelled by route
(the REST mux sets Pattern on the same *http.Request the middleware
reads). Requests refused by auth never reached the REST mux and were
labelled path="/". labelRESTPattern now sets the REST route's pattern
before auth; unmatched paths keep "/", so the label set stays bounded.
Closes#155
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>