Pin the authorization 403 that precedes the blob-upload dispatcher 405
The dispatcher answers 405 UNSUPPORTED for every verb on both OCI blob-upload
routes of a remote repository. The authorization route table is narrower: it maps
only the method each upload action serves, so five method-and-route pairs get a
bare 403 before resolution — on every repository kind — and never reach the
dispatcher wherever the authorization middleware is wired.
| Route | Method | Answered by |
|---|---|---|
.../blobs/uploads/ |
PATCH, PUT, GET, DELETE |
authorization middleware, 403 |
.../blobs/uploads/<id> |
POST |
authorization middleware, 403 |
The precedence is now written down in
docs/specs/S16-container-remote.md, under
### Gates ahead of the kind branch, and the blob-upload row in ## Error Cases
points at it. Nothing pins it.
What to add
One wrapped-handler test per pair — the authorization middleware composed around
the dispatcher — asserting the composed answer is 403, not the 405 the
dispatcher writes on its own. Five cases, one per row above.
Why it matters
Documented-but-untested precedence is invisible to the suite. Widening the
authorization route table so those pairs map to an action, or a change to how the
middleware is wired, would ship the dispatcher's 405 on a deployed instance
with every existing test still green — the dispatcher tests exercise the handler
directly, so they cannot see what the middleware answers in front of it.
Pointers
internal/authz/oci.go—blobUploadInitiateActionandblobUploadSessionActionare the two method maps that leave the gap; the comment above them explains why the table is deliberately not widened (the same five pairs already answer403on a hosted repository, where the dispatcher501s them, so widening moves a surface older than the spec).internal/format/oci/upload.go— the dispatcher whose405the test composes the middleware around.
Why it was deferred
Raised in review on !1390 (merged). The spec half of the ask landed there; the test needs a cross-package composed harness that does not exist yet, on an MR already past the size gate, so it comes out separately.