Skip to content

Commit a041d30

Browse files
committed
test(rest): pin the published-route overlay consult; changeset
1 parent ed56a2d commit a041d30

2 files changed

Lines changed: 507 additions & 0 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
'@objectstack/rest': patch
3+
---
4+
5+
`GET /api/v1/meta/:type/:name/published`: resolve from the published store, not the code/package snapshot
6+
7+
The REST transport carried the same defect the dispatcher fixed for
8+
`/meta/:type/:name/published`: an item published at runtime — authored as an
9+
ADR-0027 draft and promoted via `POST /packages/:id/publish-drafts` — answered
10+
`404` here, while the ordinary read `GET /api/v1/meta/:type/:name` served it.
11+
The route and the publish path shared no store:
12+
13+
- **the write** flips the artifact's `sys_metadata` row `state:'draft' →
14+
'active'` (`publishPackageDrafts` / `promoteDraft`);
15+
- **the read** resolved only through `metadata.getPublished`, which reads the
16+
row-local `publishedDefinition` key that `MetadataManager.publishPackage`
17+
writes into its own in-memory registry — the ADR-0016-era package publish.
18+
19+
So the 404 was a false statement about an item that IS published, on the
20+
transport that actually serves the cloud runtime. ADR-0027 (E)(5) defines
21+
sealing a publish as exactly that `draft → active` flip;
22+
`SysMetadataRepository` names `'active'` "the published, live overlay"; and
23+
ADR-0033 §2 routes every runtime authoring write into that same ADR-0027 draft.
24+
The `active` overlay row is therefore the authoritative answer to "what is
25+
published", and both route arities — `/meta/:type/:name/published` and
26+
`/meta/:type/:section/:name/published` — now consult it first.
27+
28+
The overlay is read through `getMetaItemLayered`, whose overlay layer is a
29+
strict `state:'active'` lookup reported separately from the code layer. That
30+
separation is what the fix rests on:
31+
32+
- a **runtime-published** item is served, and served the published body;
33+
- a **draft-only** item is still `404` — the overlay lookup never reads a draft,
34+
so a pending edit is not served as published;
35+
- a **code-published** item is untouched: a null overlay is positively "no
36+
runtime-published row" and falls through to the existing `getPublished` path,
37+
which answers byte-identical bytes.
38+
39+
Unchanged on purpose: `404` on this route continues to mean "no such item"
40+
rather than "exists but unpublished" — an existing item that was never published
41+
still answers `200` with its current definition, which is `getPublished`'s
42+
documented fallback and a different fact from absence.
43+
44+
Two deliberate differences from the dispatcher twin:
45+
46+
- **No organization scoping.** `packages/rest` carries no
47+
`resolveActiveOrganizationId` and no org plumbing at all — the same seam
48+
`package-routes.ts` already names at its `deletePackage` call. The read
49+
resolves the env-wide (`organization_id: null`) overlay row, which is
50+
symmetric with what an org-less `publishPackageDrafts` writes.
51+
- **A metadata-store outage stays a `503`.** `getMetaItemLayered` throws
52+
`SERVICE_UNAVAILABLE` when an overlay read that would decide a layer did not
53+
happen (the benign "table not provisioned yet" case returns normally with a
54+
null overlay). That throw is re-raised rather than swallowed, so an
55+
availability failure is never answered as `404 Not found`.

0 commit comments

Comments
 (0)