On this page
ADR-0023: An authentication gate answers 401 before body parsing
Status: Accepted (WP-02). Implemented in crates/commonlayer-app/src/http.rs (authentication_gate).
Context
Authorization happens in the application services. A handler, however, parses the path
and the body before it calls the service, so an anonymous caller of a private endpoint
would receive a 422 validation error that reveals the endpoint's input rules, and the
router-level test ("every operation not tagged public answers 401 without credentials")
could not hold for endpoints whose body fails validation.
Decision
The composition adds a route layer that answers 401 auth.required to a request that
presents no credential at all (no session cookie, no Authorization header) for an
/api/v1 operation that is not tagged public in the OpenAPI document. Requests with an
Authorization header pass through, because some bearers are verified by the owning
endpoint (GitHub Actions OIDC tokens on the submission endpoint).
Several domain crates additionally use a SignedIn/Authenticated extractor before
their path and body extractors.
Consequences
- The gate is defence in depth, not authorization: services still call
actor.require. - The
publicOpenAPI tag is load-bearing. Tagging a private operationpublicwould let anonymous requests reach its handler (the service would still refuse them). - Routes outside
/api/v1(webhooks, the registry token realm, registry events) authenticate themselves and are not gated.