Repository navigation
fix(metadata-protocol): a .custom pair's published override of a dashboard, report or email template no longer wears the base's envelope in the registry's bare slot - #29640
Conversation
…override never takes the base's envelope in the registry's bare slot The hydrator registered a published .custom override of a base's dashboard, report or email template under the bare name, wearing the base's artifact envelope (the artifact lookup, scoped to the pair, fell back to the base's). The base's per-package layer then listed the override beside the base's own item. Such a row now stays out of the bare slot, as a view row already did (#22057); every protocol read of these types answers it from its row. Claude-Session: https://claude.ai/code/session_01ADHkmQWkCUmHFTi97EGNu1 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmQWkCUmHFTi97EGNu1 Co-authored-by: Claude <noreply@anthropic.com>
…rved answer, not the registry entry Forced by the #29600 fix: a .custom pair's override of a member the package ships is served from its row and no longer registered under the package's envelope, so four cases that read the registry entry as the served answer now read the protocol (the execution list and the by-name read, which the send and every door take) and pin the registry's entry as the package's own member. Claude-Session: https://claude.ai/code/session_01ADHkmQWkCUmHFTi97EGNu1 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmQWkCUmHFTi97EGNu1 Co-authored-by: Claude <noreply@anthropic.com>
📓 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:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 10 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 e1cf57530692ea1a384dd900043b5a0d4b843535 && git checkout e1cf57530692ea1a384dd900043b5a0d4b843535
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d280265b849a1586447005e49e27f316fda2a2d5 c58da128a9b58e5d34788a9cabe48c1a87c1590f && git checkout -B drift-repro d280265b849a1586447005e49e27f316fda2a2d5 && git merge --no-ff c58da128a9b58e5d34788a9cabe48c1a87c1590f
node scripts/docs-audit/affected-docs.mjs --json d280265b849a1586447005e49e27f316fda2a2d5
|
|
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1 维护者速读
席位意见:与席位裁决 A 相符。邮件模板的注册表读方我设了前置条件,开发逐个核对过:plugin-email 先读协议,cli 读存储行加 席位核对ACCEPT ·
|
|
domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1 Hand-off note · seat 5 signs off · 2026-11-03T00:00ZSeat 5 goes off duty at the maintainer's order, so the next
|
Requested by Steve · project thread
Fixes #29600
Clause-②: no
Metadata-protocol: none
维护者速读
.custom配对包对基础包仪表盘、报表、邮件模板的已发布覆盖,不再以基础包的信封注册进注册表的裸槽位(沿用 finding(metadata-protocol): on an unscoped kernel, a package-bound stored row of a view name two packages ship is hydrated into the registry's bare slot, so a by-name read naming the other package serves that row's body under its own _packageId #22057 对 view 的规则,扩到这三种类型)。packages/metadata-protocol/src/protocol-package-bindings.ts中的declinesBorrowedEnvelope,以及新测试protocol-custom-override-bare-slot-envelope.test.ts。pnpm --filter @objectstack/objectql exec vitest run src/protocol-custom-override-bare-slot-envelope.test.ts src/environment-overlay-email-locale-restart.test.tsWhat changes
A published override of a base's dashboard, report or email template, saved in the base's
.custompair, was registered in the registry's bare slot wearing the BASE's artifact envelope (_packageId= BASE,_provenance: 'package'). The base's per-package layer, which the base's export reads, then listed the override beside the base's own item, and every registry-direct read of the base's item answered the override.The hydrator (
hydrateOverlayIntoRegistry) now declines the bare slot for a row of these three types when the row's bound package ships no artifact of the name while another package does. This is the #22057 view rule, widened per seat ruling A to dashboard, report and email_template. The rule lives indeclinesBorrowedEnvelopeinprotocol-package-bindings.ts, a closed list of three types.Files (5, +424 / −17):
packages/metadata-protocol/src/protocol-package-bindings.ts:declinesBorrowedEnvelopeand its type list.packages/metadata-protocol/src/protocol.ts: one guard line in the hydrator, plus the header and heal docblocks.packages/objectql/src/protocol-custom-override-bare-slot-envelope.test.ts(NEW): the per-type pins. It sits in objectql because the pins need the real ObjectQL engine, the in-memory driver and the real registry, and a metadata-protocol test cannot import objectql (that would be a dependency cycle). It reads metadata-protocol fromdist/, like the siblingprotocol-per-package-layer-provenance.test.tswhose harness it copies. No objectql source is edited.packages/objectql/src/environment-overlay-email-locale-restart.test.ts: forced edits, listed below..changeset/29600-pair-override-bare-slot-envelope.md: patch for@objectstack/metadata-protocol.Tests
New file
packages/objectql/src/protocol-custom-override-bare-slot-envelope.test.ts, 9 tests. Per type (view, dashboard, report, email_template) two tests:name@en-USfor the email template).registry.getItemanswers the base's own item.A control pins #4624: OTHER also ships the dashboard and owns a stored row, so its bare entry stays with OTHER's envelope and
_provenance: 'package'.Forced edits in
packages/objectql/src/environment-overlay-email-locale-restart.test.ts(seat-approved, on condition that no non-test email_template registry reader moves; the audit is under Acceptance notes). These four cases pinned the registry entry of a pair's override of a SHIPPED member, which is exactly the entry this PR removes. Each now pins the served read, and keeps the registry pin on the shipped body:PKG en/PKG zh. The served reads go through the protocol (subjectOf(protocol, 'en-US')), and after the restartsubjectOf(after.protocol, 'en-US')=ADMIN en.getMetaItem({ type, name, member: 'en-US' })=ADMIN digest en; the registry entry for en-US isPKG digest en.ADMIN zhis replaced bysubjectOf(protocol, 'zh-CN')=ADMIN zh.vi.waitForonsubjectOf(peer.protocol, 'zh-CN')=ADMIN zh; the registry pins arePKG zh/PKG enand stayPKG zhon both nodes after the delete.Ablation of the guard back to view-only. The anchor line in
declinesBorrowedEnvelopeis replaced so that it returns false for every type. The marker is confirmed indist/, and the restore is proved by an emptygit diff HEADandablation-dist-preflight --absentexit 0.Ablation reading (both files)
Acceptance notes
Bar from the ruling: no protocol read moves. Every reader was measured before (main 0ab4a09) and after (this branch) with the same harness: real ObjectQL, the in-memory driver and the protocol from
dist/. The base is registered byregisterApp, the pair installed byinstallPackage, and the override is a draft save into the pair declaring the override, then the publish. S is the shipped body, O the override; the envelope is label /_packageId/_provenance.Only the bold cells move, and none of them is a protocol served read. translation was not measurable through the pair (the save is refused NOT_OVERRIDABLE in this harness). flow and action are outside the card.
email_template non-test registry readers, per the condition on the forced edits:
template-loader.tsorganization-ownership.tsTemplatePortgetMetaItemsForExecutiongetItem,listItems)findServedOverlayRowand the list mergeThe plugin-email suite (48 files) and the cli ownership tests pass on the fixed head, as listed under Verification.
Follow-up: #29613 holds page, app, dataset, doc and book (row-served override path first, then the guard), and the two class-b findings: the pair's per-package layer is empty for those types, and their layered effective serves S while getMetaItem serves O.
Verification
Head c58da12 (
c58da128a9b58e5d34788a9cabe48c1a87c1590f) (main merged in). All heavy runs went throughscripts/pm/os-verify-lock.sh, and each VERDICT is command-exit 0../packages/**and./examples/**: 79/79 tasks.@objectstack/metadata-protocoltest: 308 files passed (4 skipped), 22257 tests passed (26 skipped).@objectstack/objectqltest: 542 files, 10517 tests passed.packages-export-base-unchanged-per-type.integration.test.tsfrom fix(runtime): the base's package export leaves out its pair's dashboard and report overrides (#29563) #29597), cloud-connection 3 / 27, cli 2 / 118 (organization-ownership apply and withdrawal-pair), plugin-email 48 / 785.--no-inline-configon packages/metadata-protocol and packages/objectql: exit 0.dispatch-gates --commands: 62 derived, 62 run, every one exit 0;dispatch-gates --ranreports 0 NOT-MEASURED, 0 UNRUN.Dogfood files
test/email-template-materialization.dogfood.test.tstest/email-template-overlay-survives-boot.dogfood.test.tstest/email-template-two-locales-survive-boot.dogfood.test.tstest/meta-read-doors-live.dogfood.test.tstest/package-commit-revert-path-package.dogfood.test.tstest/public-form-withdrawal-walled.dogfood.test.tstest/showcase-public-form-redirect.dogfood.test.tstest/showcase-public-form-walled-intake.dogfood.test.tstest/showcase-public-form-withdrawal-layers.dogfood.test.tstest/showcase-public-form-withdrawal.dogfood.test.tstest/email-template-boot-sweep.test.tstest/email-template-dependent-unshipped-locale-read.dogfood.test.tstest/email-template-override-unshipped-locale.dogfood.test.tstest/managed-content-sealed.dogfood.test.tstest/view-container-cross-package-default.dogfood.test.tstest/package-first-authoring.dogfood.test.tstest/wall-authoring-trail-doors.dogfood.test.tsGate reconciliation
Generated by Claude Code