You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4bf30da
Browse filesBrowse the repository at this point in the historyBrowse files
feat(runtime): export the package disable door's dependent-rule verdict and its sentence on the package entry (#31157)
<!-- claude-projects-attribution: {"github_login":"marchtian"} -->
_Requested by **田騏** · [project
thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSiUfC8G7ZWNaCdELoQcXkaCC)_Fixes#31067
Clause-②: yes
Metadata-protocol: none
## 维护者速读
- 改了什么:平台把「停用包」时检查依赖校验规则的判定函数和拒绝提示语,作为 `@objectstack/runtime`
的公开导出开放出来(`readPackageDisableDependents`、`formatPackageDisableDependents`、`DisableDependentRule`
类型);平台自己的停用接口用的就是同一份。
- 为什么改:cloud 控制面的「按安装停用」和软卸载会绕过这道检查,导致对象之后的写入全被拒;按裁决「平台开放检查,cloud
接上(推荐)」,平台开放、cloud 接上,检查逻辑和提示语只保留一份。
- 风险与回滚:只是新增导出,现有接口行为不变;公开面变宽(Clause-② yes),需要席位做契约复审。回滚即撤掉这次导出。
-
先看:`packages/runtime/src/index.ts`(新增的三项导出)、`packages/runtime/src/domains/packages.ts`(两个函数加
`export` 和说明)、测试文件末尾新增的 describe。
- 两分钟验证:`pnpm --filter @objectstack/runtime exec vitest run
src/domains/packages-disable-module-extension-fields.test.ts`,预期 33
个用例全部通过(其中 4 个是新增的)。
- 需要你做的:无,席位落地。
## What changes
- `packages/runtime/src/domains/packages.ts`:
`readDisableDependentRules` and `disableDependentRulesMessage` gain
`export` and a JSDoc paragraph naming their public spelling. No line of
either body changes, and both call sites (`PATCH /packages/:id/disable`
and the `POST /packages` `enableOnInstall: false` arm) still call them
directly.
- `packages/runtime/src/index.ts`: the package entry re-exports them as
`readPackageDisableDependents` and `formatPackageDisableDependents`,
named after what each answers, with the `DisableDependentRule` type
beside them. The door's function and the entry's export are the same
function object, so there is one scan and one sentence. The test pins
that identity.
- `.changeset/31067-runtime-export-disable-dependents.md`:
`@objectstack/runtime` patch, carrying both declaration lines.
Clause-②: the package entry's public surface widens by two functions and
one type. The seat owes the contract review.
## Tests
A new top-level describe in the existing harness file
`packages/runtime/src/domains/packages-disable-module-extension-fields.test.ts`,
`[#31067] the verdict the disable door asks is the package entry's
export`. It uses a bare `SchemaRegistry` plus the real `HttpDispatcher`
and boots no kernel. It has four cases:
1. Identity: `runtime.readPackageDisableDependents` is
`readDisableDependentRules`, and
`runtime.formatPackageDisableDependents` is
`disableDependentRulesMessage`.
2. The verdict answers the one active rule (the switched-off rule is
left out), writes nothing (the package stays enabled and the field stays
served), and answers `[]` for a package that withholds nothing and for a
registry it cannot read.
3. The door's `409 PACKAGE_DISABLE_RESTRICTED_BY_VALIDATION_RULE`
message equals exactly what the exported builder spells over the
exported verdict. The sentence is also spelled out literally once.
4. Control: once the reading package is disabled, the verdict is `[]`
and the door answers `200`.
The existing #30825 / #30379 / #30756 batteries in the same file are
untouched and green.
## Acceptance notes
- The code `PACKAGE_DISABLE_RESTRICTED_BY_VALIDATION_RULE` is not
exported from runtime. It is already in the `@objectstack/spec`
error-code ledger (`ApiError['code']`), so a host door can spell it
type-checked from there. Exporting the runtime wire pair as well would
be a second public spelling of the same code.
- `registry` stays typed `any`, as the door passes it. The verdict
probes `getObjectContributors` / `getAllObjects` and answers `[]` for
anything without them. A narrower structural type would be a separate
contract decision.
- The uninstall arm and the `DELETE` door are not touched. #30999 and
#31023 queue behind this card.
- The ablation was skipped on purpose: no tested behaviour changes. Case
1 is the pin that can fail: re-pointing the alias at any other function
reds it.
## Verification
Tree `objectstack-ai/objectstack`. The runtime suite and the first gate
sweep ran on `aae146a8` (merge base `5f003744`). `origin/main`
(`cadd6aa2`) was then merged as `72296d6c`. Its incoming paths touch
`formula`, `plugin-auth`, `service-settings` and `platform-objects`, and
none touches `runtime` or `objectql`. The delta against main is still
exactly these 4 files. After a rebuild, the scoped re-checks and the
whole derived gate sweep ran again on `72296d6c`.
<details><summary>Runtime package</summary>
- `pnpm --filter @objectstack/runtime exec vitest run --project local
--maxWorkers=2` :: exit 0 (on `aae146a8`). Test Files 554 passed (554),
Tests 8918 passed / 19 skipped.
- After the merge, on `72296d6c`: `pnpm build` (119/119) `&& pnpm
--filter @objectstack/runtime typecheck && vitest run` of the three
disable-door files (`packages-disable-module-extension-fields`,
`packages-disableable-verdict`, `packages-disable-app-module`) :: exit
0. Test Files 3/3, Tests 82/82.
- `pnpm --filter @objectstack/runtime typecheck` :: exit 0. The test
layer holds 27 files / 186 errors / 66 pinned signatures, unchanged.
- `eslint packages/runtime --no-inline-config` :: exit 0.
- Harness file wall time: base 17.02s (29 tests) against head 17.90s (33
tests), measured back to back under the lock.
</details>
<details><summary>Derived gates (dispatch-gates --commands)</summary>
On `72296d6c`, all 62 derived commands exit 0, each exit code captured
before any pipe (`check:type-check-debt` ran under the verify lock).
`dispatch-gates --ran`: 62 derived, 62 run, 0 NOT-MEASURED (a derived
zero: every entry carries an exit code).
On the first sweep (`aae146a8`), three commands exited 3 and were rerun
green. `check-plugin-teardown-shape --self-test` could not reach its
control commit on the shallow clone; that commit was fetched into a
private ref. `check:dual-build-cjs-loads` needed a full `pnpm build`.
`check:type-check-debt` timed out in the lock queue.
```text
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/ci/snapshot-next.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:durability-log-level :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:error-status-conformance :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:route-envelope :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:vouch-for-reference-callers :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
feat(runtime): `@objectstack/runtime` exports the package disable door's dependent-rule verdict, `readPackageDisableDependents`, and its sentence, `formatPackageDisableDependents`, with the `DisableDependentRule` type
6
+
7
+
Clause-②: yes
8
+
Metadata-protocol: none
9
+
10
+
`readPackageDisableDependents(registry, packageId)` answers the validation rules a disable of the package would leave reading a field it adds through `objectExtensions`: each as `{ packageId, object, rule, fields }`, from any enabled package (declared dependent or not, an app's `.custom` pair included), ordered by package, object and rule. It reads the registry and writes nothing, and answers an empty list for a package that withholds nothing. `formatPackageDisableDependents(lead, dependents)` spells the refusal's message: `lead`, every rule as `package · object · rule (reads FIELD, …)`, then the remedy.
11
+
12
+
They are the same two functions `PATCH /packages/:id/disable` and `POST /packages` with `enableOnInstall: false` ask, now on the package entry, so a host door that takes a package out of service another way (a control plane's per-install disable, a soft-disable uninstall) asks the same scan before its write and answers the same `409 PACKAGE_DISABLE_RESTRICTED_BY_VALIDATION_RULE` (the code is in the `@objectstack/spec` error-code ledger) instead of keeping a second copy. Nothing existing changes: every door answers exactly as before.
0 commit comments