Skip to content

Commit 85a1e89

Browse files
os-zhuangclaude
andcommitted
fix(metadata-protocol): judge a package publish against the batch's own pending declarations
`publishPackageDrafts` built its author-time validation context from `engine.registry` alone -- the ALREADY-LIVE universe. A draft is not in that registry (the write-through runs on `mode: 'publish'`), and the batch's own promotions do not put it there either: `applyRegistryWriteThrough` lives in Phase 2, after the Phase-1 transaction in which every draft is gated and promoted. So while a batch was judged, no member of it was visible to any other member, in any order. Measured 2026-08-21 on a cloud rig: a package carrying `dataset/shyx_customer_ds` and a `dashboard` whose widget binds it rolled back at the dashboard with `[widget-dataset-unknown] ... does not resolve to a declared dataset`, on every attempt and under both dataset names the author tried. So a package shipping a dashboard together with its dataset could never publish. The batch door now reads its own pending drafts ONCE, before any promotion (a promote deletes the row it reads), and folds them into all four collections the closure carries -- `objects`, `permissions`, `books`, `datasets` -- replacing a live declaration of the same name rather than sitting beside it. A name in neither the batch nor the live universe is still refused exactly as before. Fixes #10377 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent b1893a8 commit 85a1e89

5 files changed

Lines changed: 745 additions & 5 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
'@objectstack/metadata-protocol': patch
3+
---
4+
5+
fix: a package publishes as a self-consistent unit — `publishPackageDrafts` judges each draft against the batch's own pending declarations
6+
7+
The batch publish door built the author-time validation context from
8+
`engine.registry` alone, i.e. the ALREADY-LIVE universe. A draft is not in that
9+
registry, and the batch's own promotions do not put it there either: the
10+
registry write-through runs in Phase 2, after the Phase-1 transaction that gates
11+
and promotes every draft. So while a batch was being judged, no member of it was
12+
visible to any other member — in any order.
13+
14+
Measured consequence: a package shipping `dataset/x` together with a `dashboard`
15+
whose widget binds `x` could NEVER publish. `validateWidgetBindings` raises
16+
`widget-dataset-unknown` at `severity: 'error'`, which refuses the promotion,
17+
and the batch being all-or-nothing rolls the whole package back. Renaming the
18+
dataset could not help, and neither could re-ordering the items.
19+
20+
`publishPackageDrafts` now reads its own pending drafts once, before any
21+
promotion, and folds them into all four context collections the closure carries
22+
(`objects`, `permissions`, `books`, `datasets`) — pending declarations replace a
23+
live one of the same name, never sit beside it. A binding that resolves to
24+
neither the batch nor the live universe is still refused exactly as before.

0 commit comments

Comments
 (0)