Skip to content

saveMetaItem is a declared REQUIRED member whose request schema declares 3 of the ~11 members the REST PUT door sends, so the call-site literal is cast as any #12004

Description

@claude

Found while implementing #11679 (the deleteMetaItem request-schema catch-up; PR #12003) — the save door is the same request-shape gap one door over, and it is the biggest remaining one in the meta write family. Filed rather than touched: per-member protocol-vs-transport verdicts are a packages/spec contract decision (the #11006 ruled pattern), out of the fold's declared scope.

Measured on the PR #12003 merge head 2c8a3183 (base d63b0143)

SaveMetaItemRequestSchema (packages/spec/src/api/protocol.zod.ts) declares exactly three members:

exportconstSaveMetaItemRequestSchema=lazySchema(()=>z.object({type: z.string().describe('Metadata type name'),name: z.string().describe('Item name'),item: z.unknown().describe('Metadata item definition'),}));

The REST PUT /meta/:type/:name door (packages/rest/src/rest-server.ts, p.saveMetaItem({ ... } as any) — the closing cast sits at ~:5630 on that head) sends up to eleven: type, name, item, organizationId, writeFace: 'meta-envelope', and conditionally environmentId, parentVersion, actor, force, packageId, mode: 'draft'.

The implementation's parameter type (ObjectStackProtocolImplementation.saveMetaItem, packages/metadata-protocol/src/protocol.ts:13140) declares { type, name, item?, organizationId?, parentVersion?, actor?, force?, mode?, packageId?, source?, writeFace? } — so unlike the pre-#11679 delete door, every key the door sends IS read and enforced; only the spec contract is starved. saveMetaItem is a REQUIRED protocol member, so the cast here is pure request-shape smuggling (the TS2353 half, as measured for the delete door in PR #12003), not feature detection.

The decision (why filed, not fixed)

Same as #11679, on a bigger and subtler surface — per member, protocol vs transport:

Precedents: #11006 (maintainer ruling 2026-08-22, option B) · #11426 (publish request landing) · PR #12003 (#11678 audit + #11679 delete — the immediately preceding doors in this series).

⛔ Nothing about this door is addressed in PR #12003; its casts and payload are byte-identical there.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions