You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Noticed while probing the reachability of saveMetaItem's opening guard for #8818 (PR #8840). Unassigned; nobody is on it. Out of that card's scope, which is region-confined to saveMetaItem's opening guard in packages/metadata-protocol/src/protocol.ts.
The site
packages/runtime/src/domains/meta.ts:314 — the metadata write branch of the http-dispatcher, the transport #7019 added as the second door onto protocol.saveMetaItem:
// PUT /metadata/:type/:name (Save)if(method==='PUT'&&body){
The && body conjunct means a falsy body does not take the save branch at all. Execution does not stop there and does not refuse — it continues past the whole save block (including its 501 fallbacks) into the read try beginning at :396, which resolves type === 'objects' | 'object' and friends and answers the ordinary metadata read.
So a write verb carrying no body appears to be answered as a read, rather than refused. Two consequences, if it holds:
A PUT is served as a GET. The caller asked to write and receives what looks like a successful read — no status, header or field distinguishes it from a real write acknowledgement, which is the shape "Absence must be loud" (AGENTS.md, Route & surface ownership §3) exists to prevent.
The REST door, packages/rest/src/rest-server.ts (PUT /meta/:type/:name), folds a falsy body to {} (const body = req.body ?? {}) and proceeds into the save unconditionally, so its bodyless writes are refused downstream by the per-type schema with 422 INVALID_METADATA — measured end to end on #8818. The two transports therefore appear to disagree about what a bodyless metadata write means: one refuses it, the other seems to answer a read.
Scope of the claim, honestly
Read from source, not measured.#8818's probe drove the REST transport (/api/v1/meta/...), not this dispatcher, so the fall-through above is traced by reading control flow rather than observed on the wire. Before anyone changes it, the checks worth running are: which host actually mounts this dispatcher path, whether a falsy body is reachable there at all (the transport may normalize it upstream, exactly as the REST route does), and what the read branch really answers for a PUT. The honest outcome may be "unreachable, leave it alone".
Filed as an observation rather than a defect for that reason — the same disposition #8818 was filed under, and its premise did hold.
Related
#8818 / PR #8840 (where it was noticed) · #7019 (this transport's gate) · #6603 (the REST-side gate it mirrors)
Noticed while probing the reachability of
saveMetaItem's opening guard for #8818 (PR #8840). Unassigned; nobody is on it. Out of that card's scope, which is region-confined tosaveMetaItem's opening guard inpackages/metadata-protocol/src/protocol.ts.The site
packages/runtime/src/domains/meta.ts:314— the metadata write branch of the http-dispatcher, the transport #7019 added as the second door ontoprotocol.saveMetaItem:The
&& bodyconjunct means a falsy body does not take the save branch at all. Execution does not stop there and does not refuse — it continues past the whole save block (including its501fallbacks) into the readtrybeginning at:396, which resolvestype === 'objects' | 'object'and friends and answers the ordinary metadata read.So a write verb carrying no body appears to be answered as a read, rather than refused. Two consequences, if it holds:
PUTis served as aGET. The caller asked to write and receives what looks like a successful read — no status, header or field distinguishes it from a real write acknowledgement, which is the shape "Absence must be loud" (AGENTS.md, Route & surface ownership §3) exists to prevent.manage_metadatacapability gate is inside theif. It is the first thing the save branch does (ec?.isSystem/systemPermissions, the finding: after ADR-0106, a restricted caller's GET → edit → PUT of an object schema DELETES the fields that were masked out of their read #6603/#6603's gate does not close #6603: the same masked-schema round-trip deletion is still reachable through the compound-name PUT and the dispatcher PUT (plus an ungated DELETE) #7019 gate). A falsy-body PUT never reaches it — it is judged only by whatever the read path enforces (ADR-0106 masking), which is a different posture than the write door's.Why the sibling door does not have this shape
The REST door,
packages/rest/src/rest-server.ts(PUT /meta/:type/:name), folds a falsy body to{}(const body = req.body ?? {}) and proceeds into the save unconditionally, so its bodyless writes are refused downstream by the per-type schema with422 INVALID_METADATA— measured end to end on #8818. The two transports therefore appear to disagree about what a bodyless metadata write means: one refuses it, the other seems to answer a read.Scope of the claim, honestly
Read from source, not measured.#8818's probe drove the REST transport (
/api/v1/meta/...), not this dispatcher, so the fall-through above is traced by reading control flow rather than observed on the wire. Before anyone changes it, the checks worth running are: which host actually mounts this dispatcher path, whether a falsybodyis reachable there at all (the transport may normalize it upstream, exactly as the REST route does), and what the read branch really answers for aPUT. The honest outcome may be "unreachable, leave it alone".Filed as an observation rather than a defect for that reason — the same disposition #8818 was filed under, and its premise did hold.
Related
#8818 / PR #8840 (where it was noticed) · #7019 (this transport's gate) · #6603 (the REST-side gate it mirrors)
Generated by Claude Code