|
| 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