Repository navigation
Commit a545a04
fix(runtime, metadata-protocol): the permission-set clone door copies a set that grants on an object this deployment does not install, and member_default's feed grants re-land (#30310)
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgFMKmBZQVKU38CQ6a3dqyHp)_
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
## 维护者速读
- **改了什么:** 两件事放在一个 PR 里:一是把 #30108 重新落地(`member_default` 授予
`sys_comment` 读建改、`sys_activity` 读,与 #30222
逐字节相同);二是修权限集克隆门:副本从源集合继承来的授权键交给保存门,保存门的未知对象拒收不再审这些键。
- **为什么改:** #30222 合入后 main 红了。没装审计插件的部署里,这两个对象没有注册,克隆 `member_default`
会被 422 拒收。上个 PR #30262 先回退止血,这个 PR 把功能和修复一起带回来。
- **风险与回滚:** 拒收门只放过「副本从源集合原样继承」的键;副本新加的未知对象、`/meta`
保存、草稿发布,照拒不误。`saveMetaItem` 的请求多了一个可选键,在 metadata-protocol 的公开类型里可达,所以申报
Clause-② yes (widening)。回滚即撤本 PR。
- **先看:**
`packages/metadata-protocol/src/protocol-save-door-refusals.ts` 新增的过滤,再看
`packages/runtime/src/domains/permission-set-clone.ts` 第 7 步保存。
- **两分钟验证:** 在 `packages/qa/dogfood` 跑 `pnpm exec vitest run
test/permission-set-clone-door.dogfood.test.ts`(依赖先构建),预期 11 条全绿。
- **需要您做的:** 无,席位按 Clause-② yes 安排契约复审后落地。
Fixes #30255
Fixes #30108
Clause-②: yes (widening) —
`ObjectStackProtocolImplementation.saveMetaItem`'s request gains one
optional key, `inheritedGrantObjects`, reachable from
`@objectstack/metadata-protocol`'s `.` entry types
Metadata-protocol: none
## Why main went red, measured
Run 41961254209 (`797f9257`), `Dogfood Regression Gate (2/3)`, case
`permission-set-clone-door.dogfood.test.ts` "a platform set (the
lock-and-clone rule's commonest source) copies into its shipping
package's pair": `422 INVALID_METADATA` with two findings,
`objects.sys_comment` and `objects.sys_activity`, each "no package
registers an object of that name and none is saved here".
- `@objectstack/verify`'s `bootStack` constructs no `AuditPlugin` (fact
3 of
`packages/cli/src/commands/serve-audit-registration.contract.test.ts`),
and the showcase's `requires` does not name `audit`. So neither object
is registered on that boot. `sys_inbox_message` and
`sys_notification_receipt`, which `member_default` already granted, pass
because the showcase requires `messaging`.
- The save door's unknown-grant refusal (#28990) judges every grant of a
NEW item, and a clone is a new item. Its docblock assumed that platform
objects are always registered. That does not hold for an optional
platform plugin.
- Not dogfood-only: any deployment that does not install
`@objectstack/plugin-audit` could not clone `member_default` once #30222
landed.
## What changes
**The clone door is told which grants it inherits**
(`packages/runtime/src/domains/permission-set-clone.ts`). Step 7's
`saveMetaItem` call passes `inheritedGrantObjects:
inheritedGrantObjectsOf(clone)`, which is the keys of the copy's
`objects` map. `clonePermissionSetDefinition` carries every one of them
unchanged from the source.
**The refusal leaves inherited grants to the source's save**
(`@objectstack/metadata-protocol`):
- `protocol-door-requests.ts`: `SaveMetaItemRequest` gains
`inheritedGrantObjects?: readonly string[]`, documented as server-set
only.
- `protocol-save.ts`: the save path forwards it to the refusal. Draft
and publish mode are both covered, and a `migrate-stored` save is still
exempt as before.
- `protocol.ts` and `protocol-save-door-refusals.ts`:
`unknownGrantObjectSaveRefusal` takes it as a trailing parameter and
drops those keys from the unknown list, after the existing "the set's
current definition already grants on it" step. This is that rule applied
to a copy: the grant was introduced by the source and is judged where
the source introduced it. The method's docblock gains the bullet.
- Unchanged: an unknown object the save does not say it inherits is
refused exactly as before. That covers a `/meta` save, a re-save that
adds a grant, a copy that adds one, and a draft's publish
(`promoteDraftForPublish` and the restore doors pass no inherited set).
No HTTP door forwards the key: `PUT /meta` builds its request field by
field.
**#30108 re-landed:** reverting `119c2db1` (PR #30262, the revert)
restores `member_default`'s two grants, their tests and their changeset.
`git diff 490d136 HEAD` over those five paths is empty apart from the
changeset's one added bullet, which says the grant now lands with this
fix. #30108's measurements are in PR #30222's body.
**Changesets:** `.changeset/30108-member-default-feed-grants.md`
(restored, `@objectstack/plugin-security` patch, with one bullet added
that names this fix) and
`.changeset/30255-clone-inherits-held-grants.md`
(`@objectstack/metadata-protocol` and `@objectstack/runtime` patch, both
declaration lines).
## Clause-②, measured
`@objectstack/metadata-protocol`'s `exports` map has one entry, `.`,
typed by `./dist/index.d.ts` and `./dist/index.d.cts`. Built on this
tree, `dist/index.d.ts` declares `SaveMetaItemRequest` (a non-exported
alias) with `inheritedGrantObjects?: readonly string[]`, and the
exported class `ObjectStackProtocolImplementation`'s
`saveMetaItem(request: SaveMetaItemRequest)` references it. So the key
is reachable from the entry's type graph: a widening of the published
surface. Nothing a metadata author writes changes, so
`Metadata-protocol: none`.
## Verification
On head `591198e4` (branch off `main` `ef2ad31c`), under
`scripts/pm/os-verify-lock.sh`:
- `pnpm install` exit 0, then the dogfood dependency closure build
(`pnpm --filter '@objectstack/dogfood^...' build`) exit 0.
- `packages/qa/dogfood`, run with `vitest run`:
`permission-set-clone-door.dogfood.test.ts`,
`permission-unknown-grant-object-refusal.dogfood.test.ts`,
`comments-permission-matrix.dogfood.test.ts`,
`me-apps-and-everyone-baseline.dogfood.test.ts`. Result: Test Files 4
passed (4), Tests 34 passed (34). This includes the case that was red on
`main`, and the #28990 refusal's own dogfood file.
- `@objectstack/plugin-security`:
`member-default-feed-grants.integration.test.ts`,
`member-default-explicit-allow.test.ts`,
`comment-reaction-own-record-floor.test.ts`. Result: Test Files 3 passed
(3), Tests 70 passed (70).
- `pnpm --filter @objectstack/metadata-protocol test`: Test Files 312
passed, 4 skipped; Tests 22356 passed, 26 skipped.
- `pnpm --filter @objectstack/runtime test`: Test Files 541 passed
(541); Tests 8620 passed, 19 skipped.
- `typecheck` exit 0 for `@objectstack/metadata-protocol`,
`@objectstack/runtime` and `@objectstack/plugin-security`.
- The derived gates (`dispatch-gates --commands`, 65 on this change set)
and `pnpm lint`: their readings are in the seat hand-off.
CI does not run the dogfood shards on a pull request or in the merge
queue. The runs above are this PR's dogfood evidence.
<details><summary>Ablations (4 legs, each restored and proven by blob
hash against HEAD)</summary>
Driven through `scripts/ablation-replace.mjs` (WRAP mode, under
`os-verify-lock`), on head `591198e4`.
| Leg | Mutation | Red cases |
|:--|:--|:--|
| F1 | the refusal ignores `inherited` | 1: the new metadata-protocol
case (the copy is refused on its inherited grant) |
| F2 | the save path drops `request.inheritedGrantObjects` | 1: the same
case |
| F3 | the clone door omits `inheritedGrantObjects` | 2: the two
clone-door pins that assert the save request's exact key set and the
key's value |
| F4 | `inherited` widened to every grant of the item | 1: the new
case's second half (a grant the copy adds is still refused) |
The dogfood half of F3 is `main`'s own red: with the grants landed and
no fix, the clone-door case answered 422 (runs 41960290148 and
41961254209).
Full output: project file `server-seat2/30255/ablations-ran.txt`.
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic
(`packages/spec` not touched).
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint`'s reading is in the seat
hand-off.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changesets.
- [x] 6. `packages/spec` touched: n/a.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English (the 维护者速读 block is
Chinese by the Communication rule).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Utp6CatT2ajve5PJf1Hhzj)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 8c9f48f commit a545a04
13 files changed
Lines changed: 709 additions & 24 deletions
File tree
- .changeset
- packages
- metadata-protocol/src
- plugins/plugin-security/src
- objects
- runtime/src/domains
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
22 | 32 | | |
23 | 33 | | |
24 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
579 | 579 | | |
580 | 580 | | |
581 | 581 | | |
| 582 | + | |
582 | 583 | | |
583 | 584 | | |
584 | 585 | | |
| |||
625 | 626 | | |
626 | 627 | | |
627 | 628 | | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
628 | 637 | | |
629 | 638 | | |
630 | 639 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1575 | 1575 | | |
1576 | 1576 | | |
1577 | 1577 | | |
1578 | | - | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
1579 | 1581 | | |
1580 | 1582 | | |
1581 | 1583 | | |
| 1584 | + | |
1582 | 1585 | | |
1583 | 1586 | | |
1584 | 1587 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10306 | 10306 | | |
10307 | 10307 | | |
10308 | 10308 | | |
10309 | | - | |
| 10309 | + | |
| 10310 | + | |
| 10311 | + | |
| 10312 | + | |
| 10313 | + | |
| 10314 | + | |
| 10315 | + | |
| 10316 | + | |
| 10317 | + | |
| 10318 | + | |
10310 | 10319 | | |
10311 | 10320 | | |
10312 | 10321 | | |
| |||
10327 | 10336 | | |
10328 | 10337 | | |
10329 | 10338 | | |
| 10339 | + | |
10330 | 10340 | | |
10331 | 10341 | | |
10332 | 10342 | | |
10333 | 10343 | | |
10334 | 10344 | | |
10335 | 10345 | | |
10336 | 10346 | | |
10337 | | - | |
| 10347 | + | |
10338 | 10348 | | |
10339 | 10349 | | |
10340 | 10350 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
26 | | - | |
27 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
28 | 30 | | |
29 | 31 | | |
30 | 32 | | |
| |||
363 | 365 | | |
364 | 366 | | |
365 | 367 | | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
366 | 387 | | |
367 | 388 | | |
368 | 389 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
37 | | - | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| |||
267 | 267 | | |
268 | 268 | | |
269 | 269 | | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
277 | 274 | | |
278 | 275 | | |
279 | 276 | | |
| |||
291 | 288 | | |
292 | 289 | | |
293 | 290 | | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
294 | 345 | | |
295 | 346 | | |
296 | 347 | | |
| |||
0 commit comments