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:

export const SaveMetaItemRequestSchema = 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions