|
1 | 1 | --- |
2 | 2 | '@objectstack/metadata-core': patch |
| 3 | +'@objectstack/runtime': patch |
3 | 4 | --- |
4 | 5 |
|
5 | | -fix(metadata-core): the artifact forward conversion walks every `packages[].manifest` body of a multi-package artifact, so a retired key inside a package body is converted instead of refused at the metadata door |
| 6 | +fix(metadata-core, runtime): a multi-package artifact built before a retirement boots at `os dev -a` and `os start`. The ADR-0087 forward conversion walks every `packages[].manifest` body, and the runtime's artifact load converts the bundle once, before any reader sees it |
6 | 7 |
|
7 | 8 | Clause-②: no |
8 | 9 |
|
9 | | -**What an operator saw.** A multi-package release artifact (ADR-0130 D4: `os build` of a `composeStacks(…, { manifest: 'preserve' })` project) carries its collections in `packages[i].manifest`. When such an artifact was built before a retirement, for example a dashboard still spelled `refreshInterval`, the metadata plugin's artifact door refused it at the strict parse (`invalid_type` at `packages.1.manifest.dashboards.0.refreshInterval`). The ADR-0087 conversion converted the same dashboard when it sat in the artifact's own `dashboards`, but it never read a package body. |
| 10 | +**What an operator saw.** A multi-package release artifact (ADR-0130 D4: `os build` of a `composeStacks(…, { manifest: 'preserve' })` project) carries its collections in `packages[i].manifest`. Take such an artifact built before a retirement, for example with a dashboard still spelled `refreshInterval`. `os dev -a dist/objectstack.json` and `os start` exited at boot with "`packages[1]` is not a package entry (ADR-0130 D4): manifest.dashboards.0.refreshInterval: `dashboard.refreshInterval` was renamed to `refreshIntervalSeconds`…". The metadata plugin's artifact door refused the same artifact at its strict parse. The ADR-0087 conversion converted that dashboard when it sat in the artifact's own `dashboards`, but it never read a package body, and the runtime read the bundle raw before any conversion ran. |
10 | 11 |
|
11 | | -**What an operator sees now.** `applyArtifactForwardConversions` runs the same conversion over each package body as over the artifact's own collections: the same registry, and the same window, decided once from the artifact's own `engines.protocol` (a body's own `engines.protocol` is not read). The metadata plugin's artifact door registers the converted body, each item still owned by its own package, and its one-per-conversion warning names the body: `… converted 2 site(s) forward via ADR-0087 conversion 'dashboard-refresh-interval-to-refresh-interval-seconds' (first at packages[0].manifest.dashboards[0].refreshIntervalSeconds) …`. A body built after the retirement converts nothing and logs nothing. An artifact authored past every retirement still meets the tombstone inside its body. |
| 12 | +**What an operator sees now.** The same artifact boots at `os dev -a` and at `os start`. Each body's items are served converted (`refreshIntervalSeconds: 300`, valid), each owned by its own package. The boot log names each conversion once, with the body it found it in: `[MetadataPlugin] artifact '…' … converted 2 site(s) forward via ADR-0087 conversion 'dashboard-refresh-interval-to-refresh-interval-seconds' (first at packages[0].manifest.dashboards[0].refreshIntervalSeconds) …`. The artifact file itself is unchanged, so it converts again on every boot until it is rebuilt with `os build`. A body built after the retirement converts nothing and logs nothing. An artifact authored past every retirement is still refused with the tombstone inside its body. |
12 | 13 |
|
13 | | -**Not yet.** The default host (`os dev -a`, `os start` from an artifact) reads `packages[]` raw in `@objectstack/runtime` before the metadata door runs, so such an artifact is still refused there with "`packages[N]` is not a package entry (ADR-0130 D4)". That reader is not changed here. |
| 14 | +- **`@objectstack/metadata-core`.** `applyArtifactForwardConversions` runs the same conversion over each package body as over the artifact's own collections. It uses the same registry and the same window, decided once from the artifact's own `engines.protocol`; a body's own `engines.protocol` is not read. A notice from a body is located from the artifact root (`packages[1].manifest.…`). |
| 15 | +- **`@objectstack/runtime`.** `loadArtifactBundle` converts the loaded artifact once, before it merges the runtime module and before the stack, `AppPlugin` or the `manifest` service read it. The database resolver reads the artifact file itself, and it runs the same conversion on what it reads. So a multi-package artifact that declares its default datasource in a package body opens that database, not the unified default. |
14 | 16 |
|
15 | | -**Unchanged.** An artifact without `packages[]` converts exactly as before, with the same notices, paths and messages. |
| 17 | +**Unchanged.** An artifact without `packages[]` converts exactly as before, with the same notices, paths and messages, and it is served the same way. |
0 commit comments