docs(specs): correct S16 hoistability, body cap, and credential prose
What
Three corrections to S16. In each one the spec and the implementation disagree, and the spec is the side that is wrong.
- The container request builder is not hoistable as written. The S13
Dependencies row said hoisting both the cache store and the request builder to
one instance per remote repository was "a pure rewiring". True for the store.
Not for the builder, which holds the client's
Acceptvalues and a snapshot of the row'surl,auth_status, andauth_url, andremote.RequestBuilder.BuildRequesthas no per-call channel for either. - The token exchange reads its response under a fixed 64 KiB bound, not
body_size_cap_metadata(16 MB). The Oversize acceptance criterion and the body-cap Error Cases row are corrected with it. - A half-set credential pair is refused, not sent anonymously. The prose said
"when both are set ... otherwise"; the acceptance criterion already said "When
neither ... is set". Refusal answers
500 INTERNAL, with its own Error Cases row and acceptance criterion.
Each correction gets a ## Resolutions entry carrying its reasoning, in the shape
that section already uses.
Why each one matters
Item 1 misleads a reader in a different slice. The Dependencies row is where
someone composing single-flight looks, and it currently tells them the hoist is
free. The failure mode is a builder that compiles, passes every test, and
forwards the first request's Accept for the repository's lifetime, plus an
unknown auth snapshot that re-runs the discovery HEAD on every fetch and
breaks the two memoization criteria the three-state auth_status column exists
to keep.
Worth noting for review: the row was the only place that overclaimed.
### Manifest proxy and the media_type resolution both already scope the claim
to the cache store and are untouched here, which is what marks the row as a
drafting slip rather than a decision being reversed.
Item 2 is not only a wrong number. S13's Client.bodyCap clamps a
per-request override against body_size_cap_blob only, and deliberately not
against the kind's own default, because that is what lets npm's
max_remote_packument_size raise the metadata cap. So an override replaces the
metadata cap rather than tightening it. An oversize-token fixture written from the
earlier text would sit above 16 MB, exceed both bounds, and pass while asserting
nothing about the one that binds.
Item 3 started as a one-clause prose fix and now carries the answer with it.
The all-or-none CHECK on container_remote_repositories admits no half-set
pair, so reaching that state is a read-side defect rather than an operator
configuration, and answering it anonymously would surface upstream as a 401
byte-identical to a wrong password. 500 INTERNAL rather than the
token-exchange-failure 503: a 503 is retryable to an OCI client and this
fault never clears, and it must not take the cache-fallback path, which S13
scopes to a response the upstream never returned.
Scope
No code changes.
Item 1's deferral is tracked in
#596,
which carries its own ## Follow-ups bullet cross-linked with item 9 of
#320 (closed) and
with the Resolutions entry. It is deliberately not a widening of item 9: that
item rests on a call-time credential read being free, which does not hold for
Accept (not a BuildRequest parameter at all) or for the auth snapshot (a
store read per fetch). Item 2 owes no work item — the override semantics it
documents are deliberate in S13, not a defect.
Items 2 and 3 were found while implementing S16 Step 12 (container request builder
and token-exchange flow), whose MR opens against this text. Per the
documentation-pairing table in docs/dev/conventions.md,
docs/specs/ ships in its own spec MR rather than with the implementation.
Two changes outside docs/specs/ ship here alongside the corrections:
docs/plans/2026-07-30-container-remote.mdcarried the same "the hoist is free" claim item 1 retracts, in Dependencies, in Step 8, and in Step 12's Template. All three are corrected, and the correction is recorded under Research Findings so the plan says where it contradicted the spec rather than substituting the fact silently. The same file's Acceptance-criterion ownership section gains a row for item 3's new criterion, and aCorrectionnote: its stated total of 111 is four short of the 115 criteria onmain, so four criteria from earlier spec MRs have no owner in that table.CLAUDE.mdgains two rules under Docs Make Claims a Reader Can Check: naming one file as the home of a list of values is a claim about every value in it, and a claim of scale has to hold at the weak end of the range the same sentence names. Both came out of quantities in this MR's own new text.