Skip to content

Commit fef212b

Browse files
docs(spec): say a disabled package's fields are not among a base's contributions (#30642)
domain:spec#3 · os-sales · session_01L6bhgTqqeHSwZYJmApbDCa <!-- claude-projects-attribution: {"github_login":"os-sales"} --> _Requested by **Sales** · [project thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuKB8Sg6c6sVpL96ruVvdxaf)_ Fixes #30086 Clause-②: no Metadata-protocol: none ## 维护者速读 1. 改了什么:包定制读取接口(`GET /api/v1/packages/:id/customizations`)里"其他包贡献的条目"那一段的说明文字,补上一句:被停用的包加到对象上的字段不会列出。 2. 为什么改:服务端早已不再列出、也不再展示这些字段(#30362 已落地),可说明文字还写着"来自任何其他包的字段都会列出",作者和 AI 读规格时会以为停用后字段仍在。 3. 风险与回滚:只改说明文字和由它生成的参考文档页,接口形状、键、默认值、导出都不变;回滚即还原本 PR 的两个提交。 4. 先看:`packages/spec/src/api/package-lifecycle.zod.ts` 的 `contributions` 数组 describe(字段分句新增的括号说明,原因写的是"停用包的扩展整体不参与对象合成"),其次是重新生成的 `content/docs/references/api/package-lifecycle.mdx` 同一行。 5. 两分钟验证:`pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated`,预期输出 "All 14 generated artifacts are up to date"。 6. 需要你做的:无,席位落地。 ## What changes - `packages/spec/src/api/package-lifecycle.zod.ts`: the `.describe()` of `GetPackageCustomizationsResponseSchema.contributions`. Its field clause, "the fields of every object extension of an object the base owns, from any package but the base and its pair", now ends with "(a disabled package's are not listed, as the served object withholds its extension)", in the same parenthetical form the flow and navigation clauses already carry. - `content/docs/references/api/package-lifecycle.mdx`: regenerated by `gen:docs`. Not hand-edited. - `.changeset/30086-customizations-disabled-package-fields.md`: a `@objectstack/spec` patch. No key, shape, export, default or test assertion changes, and nothing in `packages/runtime` or `packages/objectql` changes. ## Tests - Readings below are at head `88a5f3437` (merge base `af8aab1b1`, after merging `origin/main`). - `pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/api/package-lifecycle.test.ts src/api/package-api.test.ts`: Test Files 2 passed (2), Tests 155 passed (155). - `pnpm --filter @objectstack/spec typecheck`: exit 0. - `pnpm --filter @objectstack/spec check:generated`: exit 1 before `gen:docs` (only `content/docs/references/**` stale), then exit 0, "All 14 generated artifacts are up to date". - `eslint --no-inline-config packages/spec/src/api/package-lifecycle.zod.ts`: exit 0. ## Acceptance notes - **Premise moved, and the residue is what this PR fixes.** At `origin/main` `dc518112`, PR #30362 (`8cc709d5`, an ancestor of this branch's base, `merge-base --is-ancestor` exit 0) already makes the served object's fold withhold a disabled package's `objectExtensions` fields (`packages/objectql/src/registry.ts`, the `isPackageDisabled` filters at :4883 and :4912). `readBaseContributions` skips that package's `field` contributors (`packages/runtime/src/domains/packages.ts` :3386, docblock :3320-3326). So reading (b) of the card governs, no server work is owed, and the schema docblock "a disabled package's contributions MUST NOT be listed" (:511-514) is now true for every kind and stays as written. - **The runtime behaviour is pinned.** `packages/runtime/src/domains/packages-disable-module-extension-fields.test.ts` :326, "no longer lists the module's fields among the app's contributions", drives the real `GET /packages/:app/customizations` route after `PATCH /packages/:module/disable`, and :336 restores them on enable. The nav half is pinned in `packages/runtime/src/domains/packages-customizations.test.ts` :693. - **The `field` / `flow` arm describes are unchanged.** They define what a `field` or `flow` entry IS, not which items are listed, so neither reads as including a disabled package's fields; the listing rule lives in the array describe. - **Round 1 (contract review should-fix 1).** The reason in the new clause was wider than the mechanism. `withholdDisabledExtensions` (`packages/objectql/src/registry.ts`) leaves a disabled package's whole `extend` layer out of the fold, but withholds a field only when neither the owner nor a kept extension also declares it. So when an enabled package adds a field of the same name, or the disabled extension patches an owner-declared field, the field stays on the served object while the list still drops the disabled package's entry. The clause now reads "as the served object withholds its extension", which is exact in both cases. The changeset's matching sentence ("began withholding them") is corrected the same way. `origin/main` was merged in (merge, not rebase) before the edit. - **Changeset classification.** `patch`, `Clause-②: no`, `Metadata-protocol: none`: the text now matches what the server already answers, and no metadata author's accepted set moves. `check-changeset-no-major` measured below. ## Verification All readings at head `88a5f3437` (merge base `af8aab1b1`, `objectstack-ai/objectstack`), after merging `origin/main`. - `pnpm --filter @objectstack/spec check:generated`: exit 1 before regeneration (only `content/docs/references/**` stale), `gen:docs` exit 0, then exit 0, "All 14 generated artifacts are up to date". - `eslint --no-inline-config packages/spec/src/api/package-lifecycle.zod.ts`: exit 0. - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`: 96 derived commands (the same list as round 0), each run after a full `turbo run build --concurrency=2` (119/119 tasks) with its exit code captured before any pipe; all 96 exit 0. - `--ran` reconciliation: "96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN" (a DERIVED zero: all 96 recorded an exit code). - `node scripts/check-changeset-no-major.mjs --base origin/main --event` (this body as the declaration): exit 0, LEVEL AXIS "clause-② `no` and metadata-protocol `none` ... a non-protocol change at `patch`". - Local-only: `pnpm check:dev-prereqs` exit 0; `pnpm check:skill-frame-freshness` exit 0. - CI families (the type-check lanes, Build Core, Build Docs, Test Core) belong to CI; they were not re-run locally. --- _Generated by [Claude Code](https://claude.ai/code/session_01L6bhgTqqeHSwZYJmApbDCa)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01L6bhgTqqeHSwZYJmApbDCa --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent f4d568b commit fef212b

3 files changed

Lines changed: 13 additions & 2 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
docs(spec): the `contributions` array of `GetPackageCustomizationsResponseSchema` says a disabled package's fields are not listed
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The `.describe()` of the `contributions` array that `GET /api/v1/packages/:id/customizations` answers already left out a disabled package's flows and navigation items, but its field clause still read as listing the fields of every object extension from any package but the base and its pair. The server has not listed a disabled package's extension fields since the served object's fold began withholding a disabled package's extension; the field clause now says so, in the same parenthetical form as the flow and navigation clauses. Text only: no key, shape, default or export changes, and the reference page `content/docs/references/api/package-lifecycle.mdx` is regenerated from it.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ Per-package customization read: overrides, extensions and switched-off items of
173173
| **overrides** | `{ type: string; name: string; member?: string; basedOn?: string; … }[]` | ✅ | Every ACTIVE item of the base's paired `<base>.custom` package that declares `overrides.package` = the base and that the effective read serves over the base's item of the same name: the rows the served-override predicate admits (a declaration from any other package, and an undeclared pair item, are not listed), minus the stored rows every read declines (a shipped flow name). Ordered by type, name and member. |
174174
| **extensions** | `{ object: string; kind: Enum<'field' \| 'validation' \| 'index'>; name?: string; fields?: string[] }[]` | ✅ | Every field, validation rule and index the paired `<base>.custom` package declares in an object extension (`objectExtensions`) of an object the base owns, one entry per member, as the extension declares it. Ordered by object, kind and name. |
175175
| **switchedOff** | `{ type: string; name: string }[]` | ✅ | Every activation-ledger row (`sys_metadata_activation`) that records the base as its package and `active: false`: the base's items this deployment switched off. Ordered by type and name. |
176-
| **contributions** | `({ kind: Enum<'field' \| 'flow'>; object: string; name: string; packageId: string } \| { kind: 'nav'; app: string; group?: string; name: string; … })[]` | ✅ | Every field, flow and navigation item another installed package contributes to the base, one entry per item and contributing package: the fields of every object extension of an object the base owns, from any package but the base and its pair; every flow registered under such a package whose trigger object the base owns (a flow of a disabled package is not served, so not listed); and every navigation item such a package contributes to an app the base owns (a disabled package's are not listed). The entry shape is per `kind`: `object` for `field` and `flow`, `app` and an optional `group` for `nav`. Ordered: the `field` and `flow` entries first, by object, kind, name and package; then the `nav` entries, by app, group (an entry with no group first), name and package. |
176+
| **contributions** | `({ kind: Enum<'field' \| 'flow'>; object: string; name: string; packageId: string } \| { kind: 'nav'; app: string; group?: string; name: string; … })[]` | ✅ | Every field, flow and navigation item another installed package contributes to the base, one entry per item and contributing package: the fields of every object extension of an object the base owns, from any package but the base and its pair (a disabled package's are not listed, as the served object withholds its extension); every flow registered under such a package whose trigger object the base owns (a flow of a disabled package is not served, so not listed); and every navigation item such a package contributes to an app the base owns (a disabled package's are not listed). The entry shape is per `kind`: `object` for `field` and `flow`, `app` and an optional `group` for `nav`. Ordered: the `field` and `flow` entries first, by object, kind, name and package; then the `nav` entries, by app, group (an entry with no group first), name and package. |
177177
| **counts** | `{ overrides: integer; extensions: integer; switchedOff: integer; contributions: integer }` | ✅ | Each list's length, derived from the lists in this same answer. |
178178

179179
### Nested Shape: `GetPackageCustomizationsResponse.overrides[number]`

‎packages/spec/src/api/package-lifecycle.zod.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ export const GetPackageCustomizationsResponseSchema = lazySchema(() => z.object(
600600
])).describe(
601601
'Every field, flow and navigation item another installed package contributes to the base, one entry per '
602602
+ 'item and contributing package: the fields of every object extension of an object the base owns, from any '
603-
+ 'package but the base and its pair; every flow registered under such a package whose trigger object the '
603+
+ 'package but the base and its pair (a disabled package\'s are not listed, as the served object withholds '
604+
+ 'its extension); every flow registered under such a package whose trigger object the '
604605
+ 'base owns (a flow of a disabled package is not served, so not listed); and every navigation item such a '
605606
+ 'package contributes to an app the base owns (a disabled package\'s are not listed). The entry '
606607
+ 'shape is per `kind`: `object` for `field` and `flow`, `app` and an optional `group` for `nav`. Ordered: '

0 commit comments

Comments
 (0)