Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changeset/27123-plugin-packaging-bundled-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
'@objectstack/spec': minor
'@objectstack/cli': patch
---

feat(spec, cli)!: `bundled` is the one plugin packaging strategy — `manifest-deps` is retired, and `os plugin build` refuses a native addon (#27123)

Clause-②: no (narrowing)
Metadata-protocol: narrowed

<!-- adr-0087: registered manifest-packaging-manifest-deps-removed, manifest-packaging-manifest-deps-retired -->

ADR-0025 v2 §3.3 makes `bundled` the only dependency-packaging strategy. `manifest-deps` kept every dependency external and packed `package.json` and the lockfile beside the bundle, but nothing ever installed them, so a plugin built with it could not load them. A compiled `.node` addon can be neither bundled nor run by every host, so a plugin may not carry one.

- **`@objectstack/spec`**: `PluginPackagingSchema` is `['bundled']`. `manifest-deps` is a retired value: every door that parses a manifest refuses it at `packaging` with the prescription — `ManifestSchema` (an `objectstack.plugin.json` at `os plugin build`, a stack's `manifest` at `defineStack`, the ObjectQL registry), a packaged artifact's `packages[].manifest`, and the `POST /packages` install body — and TypeScript no longer admits it. The ADR-0087 D2 conversion `manifest-packaging-manifest-deps-removed` deletes the value from a stack's `manifest` and from each `packages[].manifest` (`os migrate meta --from 17`), and the D3 entry `manifest-packaging-manifest-deps-retired` carries the change to the upgrade guide. The `packaging` liveness row is `planned`: a one-member enum has no fork left to read.
- **`@objectstack/cli`**: `os plugin build` packs one strategy. It inlines every dependency except the host-provided `@objectstack/*` packages and no longer packs `package.json` or `pnpm-lock.yaml`. It refuses a native addon before it writes anything, naming each one it finds: a `.node` file the bundle imports (with its importer), a bundled package that declares a node-gyp build or ships a `.node` binary, and a `.node` file under `assets/`. An addon loaded at run time from an absolute or computed path outside every bundled package is not visible to the build.

**BREAKING** for a plugin manifest that writes `packaging: 'manifest-deps'`, and for a plugin that carries a native addon.

- **Before.** `packaging: 'manifest-deps'` built an artifact that left the dependencies out and carried `package.json` for an install step that never ran. A plugin importing a `.node` file failed in esbuild with a bare "Bundle failed"; one whose dependency located its binary at run time, or that kept a `.node` file under `assets/`, built an artifact that could not load it on a host without that binary.
- **Now.** `manifest-deps` is refused at the manifest (`objectstack.plugin.json is invalid:` names `packaging`, exit 1, no artifact). A native addon is refused by name (`Native addon refused: …`, exit 1, no artifact).
- **Fix.** Delete the `packaging` key, or write `bundled`. A stack source gets the edit from `os migrate meta --from 17` (`--write` applies it); an `objectstack.plugin.json` is edited by hand. Replace a native addon with a pure-JavaScript or WebAssembly alternative.
6 changes: 3 additions & 3 deletions content/docs/references/api/package-api-assembled.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Installed package row whose manifest is the assembled package body
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |
| **functions** | `Record<string, string \| { handler?: string; effect?: Enum<'pure' \| 'writes'> }> \| { name: string; handler?: string; packageId?: string; effect?: Enum<'pure' \| 'writes'> }[]` | optional | Named handler functions, lowered to the refs a JSON document carries |
Expand Down Expand Up @@ -289,7 +289,7 @@ This schema accepts one of the following structures:
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -352,7 +352,7 @@ This schema accepts one of the following structures:
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |
| **functions** | `Record<string, string \| { handler?: string; effect?: Enum<'pure' \| 'writes'> }> \| { name: string; handler?: string; packageId?: string; effect?: Enum<'pure' \| 'writes'> }[]` | optional | Named handler functions, lowered to the refs a JSON document carries |
Expand Down
12 changes: 6 additions & 6 deletions content/docs/references/api/package-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Install package request
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -208,7 +208,7 @@ Package manifest installed through POST /api/v1/packages (AUTHORING stage; scope
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -316,7 +316,7 @@ Package manifest installed through POST /api/v1/packages (AUTHORING stage; scope
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -433,7 +433,7 @@ Install package request
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -566,7 +566,7 @@ Upgrade package request
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -660,7 +660,7 @@ Resolve dependencies request
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down
2 changes: 1 addition & 1 deletion content/docs/references/api/protocol.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2113,7 +2113,7 @@ Install package request
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down
5 changes: 2 additions & 3 deletions content/docs/references/kernel/manifest.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Install mode: managed (registered as code, upgradeable, sealed) | unmanaged (cop
| **engine** | `{ objectstack: string }` | optional | Platform compatibility requirements (legacy; superseded by `engines`) |
| **engines** | `{ platform?: string; protocol?: string }` | optional | Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`) |
| **runtime** | `Enum<'node' \| 'sandbox' \| 'worker'>` | optional | Plugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting `node` → HTTP 422 + manual review) and at boot for a plugin `os plugin install` installed: only `node` is loaded (in process, not isolated); `sandbox` and `worker` are refused until ADR-0025 M3 routes them |
| **packaging** | `Enum<'bundled' \| 'manifest-deps'>` | optional | Dependency packaging strategy (ADR-0025 §3.3) |
| **packaging** | `Enum<'bundled'>` | optional | Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled`, the only one and the default — omit the key or write `bundled` |
| **main** | `string` | optional | Entry module of a code-bearing plugin, relative to the plugin root; `os plugin build` bundles it and writes `dist/index.mjs` here in the compiled manifest (ADR-0025 §3.4) |
| **integrity** | `Record<string, string>` | optional | Per-file content digests of the plugin artifact (ADR-0025 §3.2) |

Expand Down Expand Up @@ -179,12 +179,11 @@ Per-file content digests of the plugin artifact (ADR-0025 §3.2)

## PluginPackaging

Dependency packaging strategy (ADR-0025 §3.3)
Dependency packaging strategy (ADR-0025 v2 §3.3): `bundled` is the only one and the default — every dependency except the host-provided `@objectstack/*` packages is inlined into the artifact, and `os plugin build` refuses a native (`.node`) addon

### Allowed Values

* `bundled`
* `manifest-deps`


---
Expand Down
Loading
Loading