Skip to content

publishMetaItem's declared request type omits packageId, and its in-tree comment now states the opposite of what the door does #10350

Description

@os-elon

Filed unassigned from #10063 (the REST publish route now states ?package=). Recording the half that card's fence could not reach — the file surface for #10063 was packages/rest/src/**, and this lands in packages/metadata-protocol.

Not a blocker for #10063: measured, the value flows correctly end-to-end today. This is about the declared contract and a comment that has gone stale.

📝 Body re-posted once to repair a sanitizer strip: the original wrote the parameter as ?package= followed by an angle-bracketed id placeholder, and the stored bytes lost the placeholder (the mutation AGENTS.md's "GitHub mutates body BYTES" clause describes). Spelled PKG_ID below instead. No other edit.

What is true after #10063

POST /meta/:type/:name/publish now accepts ?package=PKG_ID and puts packageId on the request it hands publishMetaItem. That value reaches the gate and repo.promoteDraft intact — verified on main + the #10063 branch:

  • publishMetaItem forwards its whole request object to promoteDraftForPublish, and the one transform in between, canonicalizeMetaRequestType, is return type === request.type ? request : { ...request, type } — a spread, so no key is dropped.
  • promoteDraftForPublishdoes declare packageId?: string | null and threads it into both limbs.

So the runtime path is sound. Two things are not.

1. The declared request type does not carry the field

publishMetaItem's request type declares type / name / organizationId / actor / message / _skipSeedApply — no packageId. The REST door reaches it through await (p as any).publishMetaItem({...}), so the cast is what makes the call compile, not the contract.

That makes the binding invisible to every typed caller: a caller that wants to state a package cannot discover it from the type, and a future refactor of publishMetaItem that destructures its request instead of forwarding it wholesale would silently drop the key. The failure mode would be the one this whole card family is about — narrowing that looks like it works and never fires.

⚠️environmentId is in exactly the same position on this call site today, so the fix should cover the declared shape rather than one key.

Same class as #9741 (Meta-read request schemas still omit previewDrafts / state / environmentId, so the REST call-site casts survive the organizationId catch-up), reached from the write side.

2. The in-tree comment now says the opposite of what happens

promoteDraftForPublish, on the gate limb:

publishPackageDrafts states it (a package publish, which is exactly the write this card is about); bare publishMetaItemnames no package and so narrows nothing, which is the correct answer rather than a gap — a promotion whose package is unstated has no declared dependency set to bound it.

and on its packageId docblock:

undefined (the publishMetaItem path, which names no package) keeps the historical "match any package" resolution.

Both were true when written. After #10063 the publishMetaItem path can name a package, and does whenever the HTTP caller states one. A future reader taking these at face value would conclude the REST door's forwarding is dead code.

⛔ Note the comment is still right about the thing it was really defending — that the package must not be read off draftForGate, because rowToItem projects a MetadataItem that carries no package id. That warning should survive any rewrite; only the "names no package" claim is stale.

Explicitly NOT this card

Widening MetadataItem in packages/spec (option 1 on #10063) stays out — that is a spec-contract change needing its own ruling, and nothing here needs it. This is metadata-protocol's own request type plus two comments.

Re-check

sed -n '/async publishMetaItem(request: {/,/_skipSeedApply/p' packages/metadata-protocol/src/protocol.ts
grep -n "names no package" packages/metadata-protocol/src/protocol.ts
grep -n "publishMetaItem({" packages/rest/src/rest-server.ts

Unassigned, concrete, awaiting first-touch grading.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions