Uh oh!
There was an error while loading. Please reload this page.
feat(spec): declare publishMetaItem as an optional MetadataProtocol member with PublishMetaItemRequest - #11426
Conversation
…er with PublishMetaItemRequest (#11006) Maintainer ruling 2026-08-22 (option B) closes the half-declared publish door: #7294 declared the response side; this declares the request schema and the optional interface member, mirroring the implementation parameter type member for member. environmentId stays transport-level per the #9741 ruling; _skipSeedApply stays internal. ADR-0122 pin Iso856 records the request schema isomorphic. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9cDbY2NBiVJWYx3BpWfH2
📓 Docs Drift CheckThis PR changes 1 package(s): 4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin df001338a45c3bb001eeaacbeb617ea2e751ad95 && git checkout df001338a45c3bb001eeaacbeb617ea2e751ad95
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 68e8b4b53c387eb56d3c6ec4a976acf385eb977d 10931f2edf02b14bb48edef2ebbf74332251b23d && git checkout -B drift-repro 68e8b4b53c387eb56d3c6ec4a976acf385eb977d && git merge --no-ff 10931f2edf02b14bb48edef2ebbf74332251b23d
node scripts/docs-audit/affected-docs.mjs --json 68e8b4b53c387eb56d3c6ec4a976acf385eb977d
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#11006
Executes the maintainer ruling recorded on the card (2026-08-22, 「同意所有」, item 5 = B): declare
publishMetaItemas an optional member ofMetadataProtocol, accepting a newly declaredPublishMetaItemRequestand returning a Promise of the already-declaredPublishMetaItemResponse(#7294). This closes the half-declared door: the response side was declared while the request and the member were not, so the request literal at the one HTTP call site was checked by nothing (the cast there carried member-existence weight — measured on the card as TS2339, not TS2353).What changed
packages/spec/src/api/protocol.zod.tsPublishMetaItemRequestSchema+PublishMetaItemRequest—{ type, name, organizationId?, actor?, message?, packageId? }, mirroring the implementation's parameter type in@objectstack/metadata-protocolmember for member.packageIdis string-or-null-or-absent with the absent-vs-nullsharp edge documented (absent = match any package;null= pin to the package-unbound row).MetadataProtocolmemberpublishMetaItem— takesPublishMetaItemRequest, returns a Promise ofPublishMetaItemResponse; optionality consistent with thedeleteMetaItem/getMetaItemLayeredprecedent (additive to a shipped contract, implementation predating declaration).packages/spec/src/api/protocol.test.ts— schema pins (value-preserving accepts, requiredtype+name,packageIdnull-vs-absent distinguishability,environmentIdand_skipSeedApplyshape-absent + stripped) and type-level pins (member optional; an undeclared key in a request literal fails compilation at the member's call shape via@ts-expect-error, compiled by the spec test typecheck program).packages/spec/src/type-alias-convention.pin.test.ts— ADR-0122 pinIso856(request schema measured isomorphic: no default/transform/catch/pipe anywhere in its tree), count 836 → 837 with receipt.check:generated --fix, only the proved-stale set):api-surface/,export-origins/,content/docs/references/**, strictness-ledger counts; the spec build movedauthorable-surface/api.jsonandjson-schema.manifest/api.jsonby exactly the new schema's entries.minorfor@objectstack/spec(additive public member; not breaking, so no ADR-0087 disposition marker is owed).Request-shape derivation (wire-measured, not invented)
type,name(required)POST /api/v1/meta/:type/:name/publish; required on the implementation's parameter typeorganizationId?organizationIdForMetaWrite(...)and always sends it; implementation resolves the draft through the org partition (ADR-0005 / the #8805 fix)actor?resolveMetaWriteActor(...)(authenticated identity, one producer — #7749)message?body.messagewhen it is a stringpackageId?(string or null)packagequery param (#10063), declared on the implementation withnull-vs-absent semantics (#10350 / PR #11005)Deliberately not declared:
environmentId(transport-level multi-kernel routing key — OUT of protocol request shapes by the #9741 maintainer ruling of 2026-08-18;packages/restlayers it viaTransportScopedMetaRequest) and_skipSeedApply(internal batch coordination forpublishPackageDrafts, never read from the wire).Cross-lane linkage — call-site consumer for the engine seat
The one HTTP consumer of this member is
packages/rest/src/rest-server.ts, thePOST ${metaPath}/:type/:name/publishhandler, which today reaches the verb as(p as any).publishMetaItem({...})(feature-detection cast around line 6027, with the #10350 measurement comment above it). Removing that cast (and typing the literal via the #9741TransportScopedMetaRequestwrapper) is the engine lane's work, tracked in #11145 — #11145 remains open and is deliberately not touched by this PR.Verification (all at commit
10931f2edf, the branch head — no commits after the runs)pnpm --filter @objectstack/spec build— exit 0 (✓ packages/spec/dist/.build-input-hash)pnpm --filter @objectstack/spec check:generated— after--fix: all 4 stale artifacts regenerated, re-verdict cleanpnpm --filter @objectstack/spec test— 419 files / 11152 tests passed, exit 0pnpm --filter @objectstack/spec typecheck— exit 0, includingcheck:test-typecheck("OK — test layer compiles"; debt counts held, so the new@ts-expect-errorpins compiled and fired)pnpm lint(full repoeslint . --no-inline-config) — exit 0node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, answered from this tree at10931f2edf): 36 derived/convention families run locally, all exit 0 — includingcheck:spec-parsed-alias,check:strictness-ledger,check:liveness,check:empty-state,check:merge-driver,check:engine-double-contract,check:where-matcher,check:query-options-erasure,check:type-check-coverage, ADR-0087/changeset gates, docs gates.packages/metadata-protocolimporting from@objectstack/spec/api— RED leg: undeclared keyspackageID/environmentIdanswered TS2561/TS2353 naming the full declared shape (proves the rebuilt declaration file carries the type and refuses undeclared keys); GREEN leg: the implementation class's instance type extendsMetadataProtocol, and the member-vs-member function check compiles, exit 0 (proves the shipped implementation satisfies the widened interface). Probes deleted; tree clean.check:type-check-debt --re-measurerefuses locally without the full 32-package built closure (its own loud refusal); population = the 13 ledgered packages inscripts/check-type-check-coverage.mjs; the only ledgered package that names the changed surface is@objectstack/metadata-protocol(repo-wide grep: soleimplements … MetadataProtocolimplementer with apublishMetaItemmethod), and the green probe above answers exactly that compile question against rebuilt dists; an added optional member + new exports cannot move tsc verdicts in packages that never name them. ②check-dev-prereqs.mjsreds locally on "43 sibling packages have no dist on disk" — a fresh-worktree environment precondition (CI builds the workspace first); the spec-dist half is green from the fresh build.Generated by Claude Code