Skip to content

Commit 66d2757

Browse files
feat(spec): the installed-package row declares its origin, a closed source (code / marketplace / authored), and the served writable verdict (#24010)
Fixes #23972 Clause-②: yes (narrowing) ## What this does Every installed-package row says where it came from. `InstalledPackageSchema` declares a required, closed `source: 'code' | 'marketplace' | 'authored'` (`InstalledPackageSourceSchema`), which is the set ruling B on #23892 (`6216295104`) names for the Packages Source column. The `GET /packages` and `GET /packages/:id` rows also declare `writable`, the verdict they have served since #14375. - The door that registers a package stamps `source` on the registry row. `GET /packages` reads it off the record (`'source'` joins the response projection). ⛔ It is never derived from `writable` or from a second list. - `writable` is declared on the SERVED row, the two branches of `InstalledPackageAtEitherStageSchema`, and not on the record. The registry never stores it, because it is recomputed per read by `isWritablePackage`. The two keys are separate declarations, and neither derives the other. - `SchemaRegistry.installPackage(manifest, source, settings?, scope?)` takes the origin as a required argument. A missing or unknown value throws a `TypeError` before any check or mutation, so no row is recorded. `ObjectQL.registerApp(body, scope?, source = 'code')` and the `manifest` service's `register(artifact, { source })` accept `'code' | 'marketplace'` and refuse `'authored'`. ## Where each origin is decided (measured, this branch) | path | file:line | value | pin | | --- | --- | --- | --- | | code / kernel: `ObjectQL.registerApp`, the `manifest` service default | `packages/objectql/src/engine.ts:7877`, `:7922`; `packages/objectql/src/plugin.ts:675`, `:742` | `code` | `package-source-stamp.test.ts` › "a package registered by code, with no source stated, records source code" | | marketplace install (hot-register) | `packages/cloud-connection/src/marketplace-install-local-plugin.ts:1559` | `marketplace` | `marketplace-install-local-hot-loaded.test.ts` › "states marketplace on the install register and on the rehydrate after a restart" | | marketplace boot rehydrate from the ledger | `marketplace-install-local-plugin.ts:783` | `marketplace` | same pin (second boot over the same ledger) | | multi-package marketplace artifact | `plugin.ts:742` (each body) | `marketplace` | `package-source-stamp.test.ts` › "every package of a multi-package marketplace artifact records source marketplace" | | install-local's own Installed Apps UI bundle | `marketplace-install-local-plugin.ts:677` | `code` (the plugin's code, no source stated) | the marketplace pin's CONTROL leg | | authored: `installPackage` in `@objectstack/metadata-protocol` (Studio base, `duplicatePackage`, base creation) | `packages/metadata-protocol/src/protocol.ts:31395` | `authored` | `protocol-install-package-enable-on-install.test.ts` › "installs the row with source authored, in both records" | | authored: the `POST /packages` no-protocol fallback | `packages/runtime/src/domains/packages.ts:1414` | `authored` | `packages-install-manifest-id.test.ts` / `-version.test.ts` / `http-dispatcher.test.ts` fallback limbs | | authored: the `sys_packages` boot rehydrate | `packages/services/service-package/src/index.ts:718` | `authored` | `hydration.test.ts` › "rehydrates a sys_packages row as source authored" | | the record seam | `packages/objectql/src/registry.ts:5455` (refusal), `:5588` (stamp) | the argument | `package-source-stamp.test.ts` › "refuses a call that states no source, or a value outside the closed set, and records no row" | | the read door | `packages/runtime/src/domains/packages.ts:273` | read off the record | `packages-writable-verdict.test.ts` › "serves each row's source as recorded…" and "the served body parses through its declared contract…" | Schema pins: `package-registry.test.ts` › `InstalledPackageSchema.source` (three origins accepted; `'cloud'` refused at `source` with `invalid_value`; a row without `source` refused). `package-api.test.ts` › "the served installed-package row declares `writable`" (required boolean on both stages; kept on the served parse; stripped by the record schemas). `objectql-engine.test.ts` holds the contract's spelled union equal to `InstalledPackageSource`. **Persistence.** No new storage surface. Both restart paths re-stamp from facts they already hold. The `sys_packages` rehydrate stamps `authored`, because that table holds only what `installPackage` persisted. The install-local ledger rehydrate stamps `marketplace`, because every ledger entry is a marketplace install. Code packages re-register at every boot. Install-local does not write `sys_packages`, so a marketplace row cannot come back through the authored path. **`source` against `writable` (assumption 2).** Measured per path: code ⇒ `writable: false` (`engine.manifests` holds it), marketplace ⇒ `false` (registered through `registerApp`), authored ⇒ `true`. Two divergences were read from code. Neither is fixed here, and both are in the acceptance notes: an authored install whose manifest says `scope: 'system' | 'cloud'`, and a `POST /packages?overwrite=true` over an id that code registered. Both read `authored` with `writable: false`. ## Ablation (both rebuilt from source; each subject is resolved through a relative import) - Marketplace: `node scripts/ablation-replace.mjs` replaced `register(manifest, { source: 'marketplace' })` with `register(manifest)` (anchor 1 → 0, blob `1e6d446df04f` → `546d2bbefdd7`). The marketplace pin went red with `expected [ [ 'com.example.crm', undefined ] ] to deeply equal …`, 1 failed / 3 passed. On restore, the blob equals HEAD and `git diff HEAD` is empty. The green run is on the same blob. - Authored: the `sys_packages` rehydrate's `'authored'` was replaced with `'code'` (blob `11e28de72ae1` → `caac9ee3e4f4`). Two hydration pins went red. On restore, the blob equals HEAD and `git diff HEAD` is empty. ## Verification - Full `pnpm test`, merge base `adce192`: spec 690 files / 20940 tests green; objectql 437 files; metadata-protocol 245 files / 20612 tests green; service-package 7 / 114 green; cloud-connection 46 / 556 green; client 52 / 671 green; runtime 403 files. The first objectql and runtime runs failed only on pins that encoded the old state: the two-argument fallback call, "no source stamp", and "undeclared residue is exactly `writable`". Those 11 tests were updated to read the declared keys, and their files re-run green (8 runtime files / 371 tests; 3 objectql files). - After merging `origin/main` (`92fd343b`, which touches `packages/spec` and `packages/core`): `pnpm --filter @objectstack/spec test` 689 / 690 files. The one red was ADR-0122's hand-kept isomorphism count (788 → 789 for the new alias), corrected in `410897be` and re-run green. - `pnpm typecheck` green for spec, objectql, metadata-protocol, runtime, service-package, cloud-connection and client, test layers included. - `pnpm --filter @objectstack/spec check:generated`: all 14 artifacts current after the merge of `origin/main` `92fd343b`, measured against a dist that run built. - Derived gates (`dispatch-gates --commands`) are run locally at the final head. Readings are in the report on #23972. ## Acceptance notes - **Out of the file surface the claim listed, and why:** `packages/client/src/index.ts` docblocks said `source` and `writable` "stay undeclared", which is false after this change, and `return-type-precision.test.ts` assigns a record row to the served type, which now needs `writable`. `packages/spec/src/contracts/objectql-engine.ts` declares the registry contract the runtime fallback calls. `packages/spec/src/type-alias-convention.pin.test.ts` carries ADR-0122's isomorphism pin for the new alias. - **The contract spells the union.** Importing `InstalledPackageSource` into `contracts/objectql-engine.ts` pulled `package-registry.zod` and the manifest graph into the `objectstack-data` skill's reference closure, and `gen:skill-refs` then wanted to rewrite `skills/objectstack-data/references/_index.md`, which is a governed surface outside this card. The contract spells `'code' | 'marketplace' | 'authored'` instead, and a type-level pin holds it equal to the declaration. - **API change (`@objectstack/objectql`, minor):** `installPackage`'s second positional argument is now `source`. In-repo callers and fixtures are updated, and the changeset carries FROM → TO. - **Not addressed:** #23974's conversion gap at the same two seams (`service-package` hydration, `protocol.installPackage`) is untouched. This PR only stamps `source` there. - **`source` / `writable` divergences** (read, not fixed): ① `POST /packages` with `manifest.scope: 'system' | 'cloud'` installs an authored row that serves `writable: false`. ② `POST /packages?overwrite=true` over an id in `engine.manifests` replaces the row with `source: 'authored'` while the boot map keeps it read-only. - A hosted kernel outside this repository that registers control-plane installs through the `manifest` service without `{ source: 'marketplace' }` records them as `code`. Every in-repo producer is stamped. - **Round 2 (`7c45b88c`), the direction is `(narrowing)`.** `InstalledPackageSchema` requires `source`, the served-row union requires `writable`, and `installPackage` takes `source` second. These are registered as ADR-0087 semantic entries `installed-package-row-source-required` and `registry-install-package-source-argument`; neither is mechanically convertible. `check:adr-0087-registration` is green. This line and line 2 were edited by the seat (`domain:spec` seat 2, session `session_01LFqdRsuM5nkqoJdHd5ztVk`) after contract review `6222834057`. Follow-up (objectui, filed by the seat after landing): the Packages Source column reads `row.source` and drops the two-read join. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01RGdjFAX2oq1VdGNT5WGdKN --- _Generated by [Claude Code](https://claude.ai/code/session_01RGdjFAX2oq1VdGNT5WGdKN)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2b27460 commit 66d2757

77 files changed

Lines changed: 807 additions & 241 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/objectql': minor
4+
'@objectstack/metadata-protocol': patch
5+
'@objectstack/runtime': patch
6+
'@objectstack/service-package': patch
7+
'@objectstack/cloud-connection': patch
8+
'@objectstack/client': patch
9+
---
10+
11+
feat(spec)!: every installed-package row declares where it came from, a closed `source: 'code' | 'marketplace' | 'authored'`, and the `GET /packages` rows declare the `writable` verdict they already served (#23972)
12+
13+
Clause-②: yes (narrowing — the served row gains two declared keys, and the record schema, the served-row union and the registry's installPackage signature each refuse what they accepted before)
14+
15+
**BREAKING** — three published accept sets narrow. `InstalledPackageSchema` refuses a row without `source`, or with a value outside `code` / `marketplace` / `authored`. The served-row union `InstalledPackageAtEitherStageSchema` refuses a row without a boolean `writable`. `SchemaRegistry.installPackage` and `EngineSchemaRegistryView.installPackage` take `source` as their second argument and refuse a call without it. The migration is below. None of it is mechanically convertible, because only the door that registers a package knows where it came from.
16+
17+
**What is new on the wire.** `GET /api/v1/packages` and `GET /api/v1/packages/:id` serve two declared keys on every row:
18+
19+
- `source` names the package's origin. `code` means the deployment's own code registered it (a `defineStack()` host, a plugin's bundled manifest, a platform package). `marketplace` means the marketplace install-local plugin installed it, and that holds after a restart too, when the plugin rehydrates it from its ledger. `authored` means it is a database-authored package (a Studio base, a duplicate, an HTTP install), including after the restart that rehydrates it from `sys_packages`. The door that registers the package stamps the value. No reader derives it.
20+
- `writable` is the server's own writability verdict (ADR-0070 D2), served on these rows since #14375 and now declared. It is computed per read and never stored, so it is declared on the served row (`InstalledPackageAtEitherStageSchema`) and not on the registry record.
21+
22+
FROM → TO for a reader of these rows:
23+
24+
| you did | do instead |
25+
| --- | --- |
26+
| treated `writable: true` as authored, and looked up each non-writable row in the marketplace's installed list (the control plane's, else install-local's) to tell marketplace from code | read `row.source` |
27+
| read the undeclared `writable` | read the declared `writable` (unchanged value) |
28+
29+
The two keys are separate statements: `source` says where the package came from, and `writable` says what this server lets an org do to it.
30+
31+
**`InstalledPackageSchema` requires `source`.** It is `InstalledPackageSourceSchema`, exported from `@objectstack/spec/kernel`. A row without it, or with a value outside the closed set, is refused at the `source` key.
32+
33+
**API change for code that registers packages (`@objectstack/objectql`).** The registry records the origin and never infers it:
34+
35+
| you wrote | write instead |
36+
| --- | --- |
37+
| `registry.installPackage(manifest)` | `registry.installPackage(manifest, 'code')` (or `'marketplace'` / `'authored'`, whichever is where the package came from) |
38+
| `registry.installPackage(manifest, settings, scope)` | `registry.installPackage(manifest, source, settings, scope)` |
39+
| `ctx.getService('manifest').register(artifact)` for a marketplace install | `ctx.getService('manifest').register(artifact, { source: 'marketplace' })` |
40+
41+
`SchemaRegistry.installPackage` throws a `TypeError` naming the closed set when `source` is missing or unknown, before anything is recorded. `ObjectQL.registerApp(body, scope?, source?)` and the `manifest` service record `'code'` when no source is given. They accept `'code'` or `'marketplace'` and refuse `'authored'`. The `IObjectQLEngine` registry contract (`@objectstack/spec/contracts`) declares the same `installPackage(manifest, source, settings?)`.
42+
43+
**The one-line fix:** pass the package's origin as `installPackage`'s second argument.
44+
45+
Readers: objectui's Setup → Packages Source column and its `?source=` filter (it switches from the two-read join to `source` in its own follow-up), and the client SDK's `packages.list()` / `packages.get()` row types.
46+
47+
<!-- adr-0087: registered installed-package-row-source-required, registry-install-package-source-argument -->

‎content/docs/references/api/package-api-assembled.mdx‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Installed package row whose manifest is the assembled package body
6767
| Property | Type | Required | Description |
6868
| :--- | :--- | :--- | :--- |
6969
| **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | The ASSEMBLED package body this row carries, at the stage the registry records it |
70+
| **source** | `Enum<'code' \| 'marketplace' \| 'authored'>` | ✅ | Where the installed package came from: code (registered by the deployment's own code), marketplace (installed from the marketplace), or authored (a database-authored package) |
7071
| **status** | `Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>` | optional (default: `"installed"`) | Package state: installed, disabled, installing, upgrading, uninstalling, or error |
7172
| **enabled** | `boolean` | optional (default: `true`) | Whether the package is currently enabled |
7273
| **installedAt** | `string` | optional | Installation timestamp |
@@ -166,7 +167,7 @@ Get installed package response
166167
| **success** | `boolean` | ✅ | Operation success status |
167168
| **error** | `{ code: Enum<'VALIDATION_ERROR' \| 'INVALID_FIELD' \| 'MISSING_REQUIRED_FIELD' \| …>; declaredCode?: string; message: string; userMessage?: string; … }` | optional | Error details if success is false |
168169
| **meta** | `{ timestamp: string; duration?: integer; requestId?: string; traceId?: string }` | optional | Response metadata |
169-
| **data** | `{ manifest: object; status?: Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>; enabled?: boolean; installedAt?: string; … } \| … +1 more` | ✅ | Installed package details |
170+
| **data** | `{ manifest: object; source: Enum<'code' \| 'marketplace' \| 'authored'>; status?: Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>; enabled?: boolean; … } \| … +1 more` | ✅ | Installed package details |
170171

171172
### Nested Shape: `GetInstalledPackageResponse.error`
172173

@@ -193,11 +194,10 @@ Get installed package response
193194

194195
### Nested Shape: `GetInstalledPackageResponse.data[option 1]`
195196

196-
Installed package with runtime lifecycle state
197-
198197
| Property | Type | Required | Description |
199198
| :--- | :--- | :--- | :--- |
200199
| **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | Package manifest at the AUTHORING stage; a row installed by a `defineStack()` host carries the assembled body instead — see `AssembledInstalledPackageSchema` / `InstalledPackageAtEitherStageSchema` |
200+
| **source** | `Enum<'code' \| 'marketplace' \| 'authored'>` | ✅ | Where the installed package came from: code (registered by the deployment's own code), marketplace (installed from the marketplace), or authored (a database-authored package) |
201201
| **status** | `Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>` | optional (default: `"installed"`) | Package state: installed, disabled, installing, upgrading, uninstalling, or error |
202202
| **enabled** | `boolean` | optional (default: `true`) | Whether the package is currently enabled |
203203
| **installedAt** | `string` | optional | Installation timestamp |
@@ -209,14 +209,14 @@ Installed package with runtime lifecycle state
209209
| **settings** | `Record<string, any>` | optional | User-provided configuration settings |
210210
| **upgradeHistory** | `{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' \| 'failed' \| 'rolled_back'>; … }[]` | optional | Version upgrade history |
211211
| **registeredNamespaces** | `string[]` | optional | Namespace prefixes registered by this package |
212+
| **writable** | `boolean` | ✅ | Whether this server lets an org author into and manage this package (a writable base); false for a read-only package. Computed per read by the server's own predicate, never stored |
212213

213214
### Nested Shape: `GetInstalledPackageResponse.data[option 2]`
214215

215-
Installed package row whose manifest is the assembled package body
216-
217216
| Property | Type | Required | Description |
218217
| :--- | :--- | :--- | :--- |
219218
| **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | The ASSEMBLED package body this row carries, at the stage the registry records it |
219+
| **source** | `Enum<'code' \| 'marketplace' \| 'authored'>` | ✅ | Where the installed package came from: code (registered by the deployment's own code), marketplace (installed from the marketplace), or authored (a database-authored package) |
220220
| **status** | `Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>` | optional (default: `"installed"`) | Package state: installed, disabled, installing, upgrading, uninstalling, or error |
221221
| **enabled** | `boolean` | optional (default: `true`) | Whether the package is currently enabled |
222222
| **installedAt** | `string` | optional | Installation timestamp |
@@ -228,6 +228,7 @@ Installed package row whose manifest is the assembled package body
228228
| **settings** | `Record<string, any>` | optional | User-provided configuration settings |
229229
| **upgradeHistory** | `{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' \| 'failed' \| 'rolled_back'>; … }[]` | optional | Version upgrade history |
230230
| **registeredNamespaces** | `string[]` | optional | Namespace prefixes registered by this package |
231+
| **writable** | `boolean` | ✅ | Whether this server lets an org author into and manage this package (a writable base); false for a read-only package. Computed per read by the server's own predicate, never stored |
231232

232233

233234
---
@@ -242,13 +243,12 @@ This schema accepts one of the following structures:
242243

243244
#### Option 1
244245

245-
Installed package with runtime lifecycle state
246-
247246
### Properties
248247

249248
| Property | Type | Required | Description |
250249
| :--- | :--- | :--- | :--- |
251250
| **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | Package manifest at the AUTHORING stage; a row installed by a `defineStack()` host carries the assembled body instead — see `AssembledInstalledPackageSchema` / `InstalledPackageAtEitherStageSchema` |
251+
| **source** | `Enum<'code' \| 'marketplace' \| 'authored'>` | ✅ | Where the installed package came from: code (registered by the deployment's own code), marketplace (installed from the marketplace), or authored (a database-authored package) |
252252
| **status** | `Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>` | optional (default: `"installed"`) | Package state: installed, disabled, installing, upgrading, uninstalling, or error |
253253
| **enabled** | `boolean` | optional (default: `true`) | Whether the package is currently enabled |
254254
| **installedAt** | `string` | optional | Installation timestamp |
@@ -260,6 +260,7 @@ Installed package with runtime lifecycle state
260260
| **settings** | `Record<string, any>` | optional | User-provided configuration settings |
261261
| **upgradeHistory** | `{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' \| 'failed' \| 'rolled_back'>; … }[]` | optional | Version upgrade history |
262262
| **registeredNamespaces** | `string[]` | optional | Namespace prefixes registered by this package |
263+
| **writable** | `boolean` | ✅ | Whether this server lets an org author into and manage this package (a writable base); false for a read-only package. Computed per read by the server's own predicate, never stored |
263264

264265
### Nested Shape: `InstalledPackageAtEitherStage[option 1].manifest`
265266

@@ -306,13 +307,12 @@ Installed package with runtime lifecycle state
306307

307308
#### Option 2
308309

309-
Installed package row whose manifest is the assembled package body
310-
311310
### Properties
312311

313312
| Property | Type | Required | Description |
314313
| :--- | :--- | :--- | :--- |
315314
| **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | The ASSEMBLED package body this row carries, at the stage the registry records it |
315+
| **source** | `Enum<'code' \| 'marketplace' \| 'authored'>` | ✅ | Where the installed package came from: code (registered by the deployment's own code), marketplace (installed from the marketplace), or authored (a database-authored package) |
316316
| **status** | `Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>` | optional (default: `"installed"`) | Package state: installed, disabled, installing, upgrading, uninstalling, or error |
317317
| **enabled** | `boolean` | optional (default: `true`) | Whether the package is currently enabled |
318318
| **installedAt** | `string` | optional | Installation timestamp |
@@ -324,6 +324,7 @@ Installed package row whose manifest is the assembled package body
324324
| **settings** | `Record<string, any>` | optional | User-provided configuration settings |
325325
| **upgradeHistory** | `{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' \| 'failed' \| 'rolled_back'>; … }[]` | optional | Version upgrade history |
326326
| **registeredNamespaces** | `string[]` | optional | Namespace prefixes registered by this package |
327+
| **writable** | `boolean` | ✅ | Whether this server lets an org author into and manage this package (a writable base); false for a read-only package. Computed per read by the server's own predicate, never stored |
327328

328329
### Nested Shape: `InstalledPackageAtEitherStage[option 2].manifest`
329330

@@ -443,7 +444,7 @@ List installed packages response
443444

444445
| Property | Type | Required | Description |
445446
| :--- | :--- | :--- | :--- |
446-
| **packages** | `({ manifest: object; status?: Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>; enabled?: boolean; installedAt?: string; … } \| … +1 more)[]` | ✅ | Installed packages |
447+
| **packages** | `({ manifest: object; source: Enum<'code' \| 'marketplace' \| 'authored'>; status?: Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>; enabled?: boolean; … } \| … +1 more)[]` | ✅ | Installed packages |
447448
| **total** | `integer` | optional | Total matching packages |
448449
| **nextCursor** | `string` | optional | Cursor for the next page |
449450
| **hasMore** | `boolean` | ✅ | Whether more packages are available — this door serves one page, so always `false` |

‎content/docs/references/api/package-api.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ Install package response
383383

384384
| Property | Type | Required | Description |
385385
| :--- | :--- | :--- | :--- |
386-
| **package** | `{ manifest: object; status?: Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>; enabled?: boolean; installedAt?: string; … }` | ✅ | Installed package details |
386+
| **package** | `{ manifest: object; source: Enum<'code' \| 'marketplace' \| 'authored'>; status?: Enum<'installed' \| 'disabled' \| 'installing' \| 'upgrading' \| 'uninstalling' \| 'error'>; enabled?: boolean; … }` | ✅ | Installed package details |
387387
| **dependencyResolution** | `{ dependencies: object[]; canProceed: boolean; requiredActions: object[]; installOrder: string[]; … }` | optional | Dependency resolution result |
388388
| **namespaceConflicts** | `{ type: 'namespace_conflict'; requestedNamespace: string; conflictingPackageId: string; conflictingPackageName: string; … }[]` | optional | Namespace conflicts detected |
389389
| **message** | `string` | optional | Installation status message |

0 commit comments

Comments
 (0)