From 6558060910a16011c0f847f46ed2964e399ae3a9 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 07:27:24 +0000 Subject: [PATCH 1/2] docs(spec): the kernel install request's describe now states what the primitive does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `InstallPackageRequestSchema.enableOnInstall` declared, in its `.describe()` and in its doc block, that the in-process protocol primitive does not read the key. That stopped being true when `MetadataProtocol.installPackage` started honouring it (482d584121): `true` enables, `false` disables, an absent key makes no lifecycle call at all. Both statements ship — the file matches `src/**/*.zod.ts` in the package's `files[]`, and the `.describe()` is regenerated into two published reference pages — so the correction is a published-surface fix, not a comment tidy. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude --- .../spec/src/kernel/package-registry.zod.ts | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/packages/spec/src/kernel/package-registry.zod.ts b/packages/spec/src/kernel/package-registry.zod.ts index 64a17a8bc36..c3ce48e6de5 100644 --- a/packages/spec/src/kernel/package-registry.zod.ts +++ b/packages/spec/src/kernel/package-registry.zod.ts @@ -293,19 +293,39 @@ export const InstallPackageRequestSchema = lazySchema(() => z.object({ * ⛔ Never let the two drift: `src/api/package-install-one-authority.test.ts` * parses BOTH over one matrix and reds when they disagree on any cell. * - * ## ⚠️ This contract's own implementation does not read the key + * ## ⭐ This contract's own implementation HONOURS the key — on the registry row * * This schema types the in-process protocol primitive - * `ObjectStackProtocol.installPackage` (`src/api/protocol.zod.ts`), whose - * implementation reads `request.manifest` and `request.settings` and nothing - * else (`packages/metadata-protocol/src/protocol.ts`). The HTTP door does - * NOT forward the key down this seam either: it calls - * `installPackage({ manifest, settings })` and performs the enable/disable - * flip itself afterwards, because the durable half must follow the ROW that - * door returned rather than the request's intent. So an `enableOnInstall` - * spelled on THIS request reaches no code that acts on it — which is why the - * `.describe()` says so on the published reference page rather than - * repeating the authority's promise a layer that cannot keep it. + * `ObjectStackProtocol.installPackage` (`src/api/protocol.zod.ts`), and that + * implementation (`packages/metadata-protocol/src/protocol.ts`) applies the + * same rule the HTTP door applies — 「缺省 = 保持,有旗 = 设置」 — through the + * same registry verbs `PATCH /packages/:id/enable` and + * `PATCH /packages/:id/disable` use: + * + * - `true` ⇒ `enablePackage` — clears a disable, including a boot-seeded one; + * - `false` ⇒ `disablePackage` — the row and its `status` both move; + * - ABSENT ⇒ no lifecycle call at all; the row the registry returned stands. + * + * `=== true` / `=== false`, never a truthiness test and never a `??` default: + * the THREE states are the contract, and a non-boolean value is read as + * ABSENT rather than coerced. The `.default(true)` below never reaches that + * path — nothing parses an install request through this schema there — so an + * absent key arrives intact and is read as absent. + * + * ⚠️ What this seam does NOT write, stated so the scope is not over-read: the + * runtime's DURABLE disabled-package file. That record is keyed by + * ENVIRONMENT (`setPackageDisabled(environmentId, id, disabled)`, + * `packages/runtime/src/package-state-store.ts`) and an + * `InstallPackageRequest` carries no environment, so the key cannot even be + * formed here; that module also lives in `@objectstack/runtime`, which + * depends on the protocol package and not the other way round. It is also why + * the HTTP door still calls `installPackage({ manifest, settings })` and + * performs its own enable/disable flip afterwards rather than forwarding the + * key down this seam: the durable half must follow the ROW that door returned + * rather than the request's intent. So an `enableOnInstall` spelled on THIS + * request moves the registry row — what every in-process reader serves from — + * for the life of the process; a caller that needs the choice to survive a + * restart goes through `POST /api/v1/packages`. * * ## ⛔ Why the reference is documentary and not `…Schema.shape.…` * @@ -322,7 +342,7 @@ export const InstallPackageRequestSchema = lazySchema(() => z.object({ * mechanical half of the reference, and it is the half that can fail. */ enableOnInstall: z.boolean().default(true) - .describe('Whether to enable immediately after install — restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive does not read it'), + .describe('Whether to enable immediately after install — restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive honours it on the registry row: true enables, false disables, absent makes no lifecycle call'), /** * Current platform version for compatibility checking. * When provided, the system compares this against the package's From adbbc66907cba2d5db17c50fb208e7e66cec786d Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 07:38:04 +0000 Subject: [PATCH 2/2] docs(spec): regenerate the two reference pages and declare the release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pnpm --filter @objectstack/spec check:generated --fix` regenerated `content/docs/references/{api/protocol,kernel/package-registry}.mdx` from the corrected describe — one line each, by the repo's own tooling, never by hand. `check:generated` named exactly one stale artifact before the run and none after it, which is also the measurement that both pages are DERIVED from that describe rather than hand-written. The changeset is `patch` on `@objectstack/spec`: the changed bytes ship (`src/**/*.zod.ts` is in the package's `files[]`, and the sentence also reaches `dist/` and `json-schema/`, both listed there), while no key, type or default moves. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude --- ...kernel-install-request-describe-honours.md | 19 +++++++++++++++++++ content/docs/references/api/protocol.mdx | 2 +- .../references/kernel/package-registry.mdx | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .changeset/19339-kernel-install-request-describe-honours.md diff --git a/.changeset/19339-kernel-install-request-describe-honours.md b/.changeset/19339-kernel-install-request-describe-honours.md new file mode 100644 index 00000000000..72258688e11 --- /dev/null +++ b/.changeset/19339-kernel-install-request-describe-honours.md @@ -0,0 +1,19 @@ +--- +"@objectstack/spec": patch +--- + +`kernel/InstallPackageRequest.enableOnInstall` no longer tells authors the in-process primitive ignores the key — it now states the three states that primitive really applies (#19339). + +The declaration's published description read "this protocol primitive does not read it". That was true when it was written and stopped being true when `MetadataProtocol.installPackage` started honouring the key (`482d584121`): `true` enables, `false` disables, and an ABSENT key makes no lifecycle call at all. Nothing went red, because `check:docs` holds the generated reference page equal to the `.describe()` and the two still agreed with each other — internal consistency, not truth. + +Clause-②: no + +**What moves** + +The `.describe()` text of one key, the doc block above it, and the two reference pages generated from that text (`references/api/protocol.mdx`, `references/kernel/package-registry.mdx`). It now reads: "restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive honours it on the registry row: true enables, false disables, absent makes no lifecycle call". + +The scope word "on the registry row" is load-bearing and is spelled out in the doc block: the durable disabled-package file is keyed by environment, which an `InstallPackageRequest` does not carry, so this seam moves the registry row for the life of the process and `POST /api/v1/packages` still owns the record that survives a restart. + +**What does not move** + +No key is added, removed, renamed or retyped, and no default changes — the accept set is byte-for-byte what it was, and `api-surface`, `authorable-surface` and `authorable-defaults` are all unchanged. `PackageInstallRequestSchema` (`api/package-api.zod.ts`) remains the one authority for this key, and the parity pin that holds the copy to it is untouched. diff --git a/content/docs/references/api/protocol.mdx b/content/docs/references/api/protocol.mdx index 88d647fc075..ef17f9aa1a1 100644 --- a/content/docs/references/api/protocol.mdx +++ b/content/docs/references/api/protocol.mdx @@ -1910,7 +1910,7 @@ Install package request | :--- | :--- | :--- | :--- | | **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | Package manifest to install | | **settings** | `Record` | optional | User-provided settings at install time | -| **enableOnInstall** | `boolean` | optional (default: `true`) | Whether to enable immediately after install — restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive does not read it | +| **enableOnInstall** | `boolean` | optional (default: `true`) | Whether to enable immediately after install — restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive honours it on the registry row: true enables, false disables, absent makes no lifecycle call | | **platformVersion** | `string` | optional | Current platform version for compatibility verification | ### Nested Shape: `InstallPackageRequest.manifest` diff --git a/content/docs/references/kernel/package-registry.mdx b/content/docs/references/kernel/package-registry.mdx index ce4b5b76eba..4a90ffa4274 100644 --- a/content/docs/references/kernel/package-registry.mdx +++ b/content/docs/references/kernel/package-registry.mdx @@ -184,7 +184,7 @@ Install package request | :--- | :--- | :--- | :--- | | **manifest** | `{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }` | ✅ | Package manifest to install | | **settings** | `Record` | optional | User-provided settings at install time | -| **enableOnInstall** | `boolean` | optional (default: `true`) | Whether to enable immediately after install — restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive does not read it | +| **enableOnInstall** | `boolean` | optional (default: `true`) | Whether to enable immediately after install — restates the install-door request key, whose one authority is api/PackageInstallRequest; this protocol primitive honours it on the registry row: true enables, false disables, absent makes no lifecycle call | | **platformVersion** | `string` | optional | Current platform version for compatibility verification | ### Nested Shape: `InstallPackageRequest.manifest`