Uh oh!
There was an error while loading. Please reload this page.
refactor(rest): drop the (p as any) cast at the publishMetaItem call site (#11145) - #11682
Merged
Merged
Conversation
…all site `MetadataProtocol` now declares `publishMetaItem` as an optional member carrying `PublishMetaItemRequest` (#11006, maintainer ruling 2026-08-22, option B), so the cast that was feature-detecting an ADR-0076 D9 server-only extension has nothing left to carry. The request literal is typed through the #9741 `TransportScopedMetaRequest` wrapper, which is the point: an undeclared key at this call site is now a compile error instead of an unchecked payload member. The docblock that existed only to explain why the cast had to stay is replaced rather than left behind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VK8rFDtg8eREaxBGX99Csn
…Item cast Part of #11145 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VK8rFDtg8eREaxBGX99Csn
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 13 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
huangyiirene
marked this pull request as ready for review
August 24, 2026 12:18
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#11145
The
POST /meta/:type/:name/publishdoor reached its protocol method through(p as any).publishMetaItemtwice — once for the 501 feature-detection guard,once for the call — so nothing checked the request literal it built. #11006
(maintainer ruling 2026-08-22, option B; landed as #11426) declared the member
on
MetadataProtocolwith aPublishMetaItemRequest, which is what takes theprop out from under the cast. This is the consumer half the ruling routed to
this lane by name.
The premise held, and it was measured rather than assumed
Verified on
origin/main@c251ef4213(the file took four commits on2026-08-24, so line numbers were taken fresh):
packages/spec/src/api/protocol.zod.ts:2535declarespublishMetaItem?(request: PublishMetaItemRequest): Promise<PublishMetaItemResponse>— an optional member carrying the request type, not a narrowed variant.
packages/specwas rebuilt before any verdict was read: the emittedpackages/spec/dist/api/index.d.tscarries the member at line 8987 andexports
type PublishMetaItemRequest, so the readings below are against therebuilt
.d.tsand not a stale artifact. (packages/restlooks up@objectstack/specthrough itsexportsmap, i.e.dist/.)What the cast was load-bearing for — three measured legs
All three legs are
pnpm --filter @objectstack/rest typecheck(tsc --noEmit),run back to back at
a5d4f97b92under the shared verify lock, with the mutationconfirmed on disk by grep between legs and restored from the commit under a
shell
trap:Leg 1 — cast removed (this PR's tree): clean, exit 0. On-disk before the
run:
(p as any).publishMetaItemcount0, typed-literal count1. No second,independent reason for the cast surfaced. Had one, this PR would have been a
finding instead — re-casting in a different spelling to reach green would have
defeated the card.
Leg 2 — undeclared key injected at the call site:
TS2353, exit 2. On-diskbefore the run: injected probe count
1.That diagnostic is the deliverable, not a side effect: it is the compile
error the card names as its acceptance signal, and the expanded type in the
message is the spec-declared surface the literal is now judged against.
Leg 3 — restored: clean, exit 0. On-disk after restore: probe count
0,typed-literal count
1. The mutation left nothing behind.The historical claim in the retired docblock is reproduced rather than
re-measured, and it is the counter-intuitive half worth keeping: deleting the
cast while the member was undeclared answered
TS2339: Property 'publishMetaItem' does not exist on type 'RestProtocol'— not aTS2353about an unknown key. The cast carried member existence, not request shape,
which is why widening the implementation's own parameter type in
@objectstack/metadata-protocol(a packagepackages/restdeliberately doesnot depend on) could never have retired it, and why declaring the member did.
What changed
if (!p.publishMetaItem). It stays — the declared member isoptional (a kernel may not implement the promotion door), and it is also what
narrows the member to callable at the call site.
TransportScopedMetaRequest<PublishMetaItemRequest>, the same shape [finding] Meta-read request schemas still omit previewDrafts / state / environmentId, so the REST call-site casts survive the organizationId catch-up #9741gave the meta-read doors and [finding] Non-door getMetaItems helper call sites in rest-server.ts still cast, though the declared surface + transport envelope now cover them #9805 gave the non-door helpers.
stay is replaced, not left behind. It asserted
MetadataProtocol"declares nosuch member", which [裁决]
MetadataProtocol是否应声明publishMetaItem成员 —— 半声明的门(响应已声明、请求未声明) #11006 falsified; a rationale for a prop that no longerexists is a declaration that outlived its subject.
No behaviour change, and nothing about the wire moves. The outgoing payload
is byte-identical — same keys, same conditional spreads. The edit hoists the
literal into a const and drops a type-level cast.
No type-level pin, and the reason is measured
A
@ts-expect-errorpin in apackages/resttest would be inert today, soit was deliberately not added rather than added for visibility.
packages/rest/tsconfig.jsonexcludes**/*.test.ts/**/*.spec.ts, and therepo runs no vitest
typecheckmode — the package's tests sitting outside everytsc program is a ledgered state, recorded as
TEST_DEBTat 155 errors inscripts/check-type-check-coverage.mjs. A pin nothing compiles is a phantomcheck, which is worse than none. The guarantee is instead pinned where it is
actually compiled: the call-site literal in
src/, whichtypecheckreads onevery run — that is what leg 2 exercised. The declaration side is already pinned
upstream by #11006 (
expectTypeOf<MetadataProtocol['publishMetaItem']>()inpackages/spec/src/api/protocol.test.ts:1760).Verification, all at
a5d4f97b92pnpm --filter @objectstack/rest typecheck— exit 0 (legs above).pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2— the fullpackage suite,
Test Files 142 passed (142),Tests 2270 passed (2270).pnpm lint(eslint . --no-inline-config, repo-wide, not narrowed) —exit 0.
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackfrom the actual change set — exit 0 each. Pluspnpm check:nul-bytes— exit 0.packages/specwas not touched: it is off limits from this lane, and thecleanup needed nothing further there.
Out of scope — filed, not touched here
Two sibling doors in this same file are in the state
publishMetaItemjust left,both needing a
packages/specdecision this lane cannot take. Filed rather thantouched; ⛔ neither is addressed here.
MetadataProtocoldeclares noauditMetaItemmember at all, so the REST audit door's request literal is compiled against nothing #11678 —MetadataProtocoldeclares noauditMetaItemmember atall (0 occurrences in
protocol.zod.ts), so that door's request literal atrest-server.ts:5873is compiled against nothing. The step before the state[裁决]
MetadataProtocol是否应声明publishMetaItem成员 —— 半声明的门(响应已声明、请求未声明) #11006 adjudicated: neither request nor member declared.deleteMetaItemis a declared member whose request schema declares 2 of the 8 members the REST reset door sends, so the call-site cast cannot come off #11679 —deleteMetaItemis declared, butDeleteMetaItemRequestSchemadeclares 2 of the 8 members the reset door sendsat
rest-server.ts:5704. The opposite half of this card:TS2339is alreadygone there, and what is left is a genuine request-shape gap, so that cast
cannot come off the way this one did.
Neither is in this diff. Both are
packages/specdecisions; #11678 and #11679remain open for triage.
Generated by Claude Code