Repository navigation
Commit 35ffb77
fix(objectql)!: refuse a composed stack's top-level picklist that no package body declares and no object field names (#28231)
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
## 维护者速读
- 问题:带 `packages[]` 的组合栈,若顶层声明了一个
picklist,既没有任何包体声明、也没有任何对象字段引用,启动照常成功,该列表在引擎注册表里静默缺失。
- 修复:`manifest` 服务在注册任何内容之前拒绝这种工件,返回 `INVALID_METADATA`(422),消息点名每个
picklist 和所属栈,并给出处方。
- 处方:在使用它的包的 `packages[]` 条目里声明;或由对象字段引用它;或从顶层删除。
- 不变:被对象字段引用的残余 picklist 保持现有行为(顶层对象"列出但不服务"、包体字段由 picklist 审计拒绝);包体声明的
picklist、无残余 picklist 的栈、不带 `packages[]` 的栈均不变。
- 破坏性:是,收窄(以前能启动的组合现在被拒绝),patch 级 changeset,无 schema 变更,ADR-0087
not-required。
- 文件面:仅 `packages/objectql/src/plugin.ts` 的残余注册段、其残余测试文件和一个 changeset。
Clause-②: yes (narrowing) — a stack with `packages[]` whose top level
declares a picklist that no package body declares and no object field
names booted, and now refuses the boot with `INVALID_METADATA` (422)
Metadata-protocol: none
## What changed
The `manifest` service registers a composed stack's residual (top-level
items no package body declares) under the stack's own id, except
picklists, which stay metadata only (`RESIDUAL_TYPES_WITH_OWN_PATH`). A
residual picklist that an object field names was loud already. One that
no object field names was neither registered nor refused.
`unreferencedResidualPicklistRefusal` (in
`packages/objectql/src/plugin.ts`) reads the residual rule's own answer
(`unclaimedTopLevel`), takes its picklists, and keeps those that no
object field names. "Names" is judged off the artifact alone: its top
level and every package body, objects and `objectExtensions` both,
through the existing `collectManifestPicklistReferences`. It is never
judged off the registry, which is still filling during a boot. If any
are left, `register` throws before anything of the artifact registers.
The refusal uses the existing picklist envelope `picklistMetadataError`
(`INVALID_METADATA`, 422), so no new error code is added. The residual
objects rule's line does not move.
## Measurement (on `main` at `35f20551`, then on this branch)
| Composition | `main` | This branch |
|:---|:---|:---|
| Residual picklist that no object field names | boots, `state=running`;
`resolvePicklistOptions('acme_unused')` is `undefined`; no warning names
it | refused at boot, `INVALID_METADATA`, the message names
`acme_unused` and stack `com.example.acme.release` |
| `packages: []` with only such a picklist on the top level | boots; the
list is absent; nothing names it | refused, as above |
| CONTROL: residual picklist that a residual object's field names |
boots; the object is listed and not served (one warning); the list is
not registered | unchanged |
| CONTROL: picklist a body declares | boots; the list resolves to
`['open']` | unchanged |
## Pins (`manifest-service-residual-objects.test.ts`, new `describe`)
On `main`'s `plugin.ts`: 4 red, 5 green (the 5 controls). On this
branch: 9 of 9 green. Both residual test files: 72 of 72 green. Full
`@objectstack/objectql` suite: green (counts under Gates).
- Red on `main`, green here: the boot refusal (code, status, picklist,
stack, all three remedies); several picklists named in one refusal, and
not one a field names; `packages: []` with only such a picklist; after
`start()`, the artifact is refused before anything of it registers.
- Controls (green on both): a residual picklist a residual object's
field names keeps the listed-and-not-served line, and the list stays
unregistered; a residual picklist a body object's field names still
fails the boot's picklist audit, not this refusal; a body-declared
picklist registers whether or not the top level repeats it; a stack with
no residual picklist boots unchanged; a stack without `packages[]`
registers its unnamed picklist as before.
Ablations, each restored from the committed head:
| Ablation | Red |
|:---|:---|
| A1: drop the throw | the 4 refusal pins |
| A2: treat no picklist as named | both "a field names it" controls, the
"several in one refusal" pin, and the existing listed-and-not-served pin
|
| A3: count references on the top level only, not in bodies | the
body-field audit control |
| A4: take every top-level picklist, not only the residual's | the
body-declared control and the no-`packages[]` control |
| A5: refuse whenever there is a residual | 52 tests, the
no-residual-picklist control among them |
## Gates
Run on the head `b4c76532`, which merges `main` at `7811c3f6`, after a
full rebuild:
- `dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`
derived 61 families. All 61 were run and all exited 0. `--ran` reports
61 run, 0 NOT-MEASURED and 0 UNRUN, and exits 0.
- The derivation names some work outside those 61 that cannot run
locally: 4 families that take a value from the workflow, 5 CI jobs
scheduled by these paths, and 5 type-check lanes. These are NOT MEASURED
here, and CI runs them.
- `pnpm lint`: exit 0. `pnpm --filter @objectstack/objectql run
typecheck`: exit 0.
- Test suites: `@objectstack/objectql` 9732 of 9732 green,
`@objectstack/runtime` 8855 green with 19 skipped,
`@objectstack/metadata` 906 of 906 green.
Fixes #28159
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_016WV4d1Np3hU7RQnA13YZcL
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 03069ca commit 35ffb77
3 files changed
Lines changed: 223 additions & 1 deletion
File tree
- .changeset
- packages/objectql/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
542 | 542 | | |
543 | 543 | | |
544 | 544 | | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
| 52 | + | |
51 | 53 | | |
52 | 54 | | |
53 | 55 | | |
| |||
170 | 172 | | |
171 | 173 | | |
172 | 174 | | |
173 | | - | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
174 | 178 | | |
175 | 179 | | |
176 | 180 | | |
| |||
208 | 212 | | |
209 | 213 | | |
210 | 214 | | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
211 | 269 | | |
212 | 270 | | |
213 | 271 | | |
| |||
831 | 889 | | |
832 | 890 | | |
833 | 891 | | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
834 | 897 | | |
835 | 898 | | |
836 | 899 | | |
| |||
0 commit comments