feat(spec)!: 六个注册类型收紧,skill 的 permissions 不再假装是权限门(#4001 批 4) - #4528
Merged
Conversation
…s` stops pretending to be a gate (#4001) Mechanical work on the registered-type line with `strictObject`: `report`, `dataset`, `email_template`, `skill`, `job`, `book`. One call each, plus the aliases that fit the surface's own vocabulary — `sections`/`chapters`/`toc` → `groups` on a book, `cron`/`interval` → `schedule` on a job, `title`/`content`/ `html` → `subject`/`body` on an email template. One of the six is not mechanical, and it is the class this campaign exists for. `skill` accepted a `permissions` key and dropped it. Skill invocation was never permission-gated, so an author who wrote `permissions: ['order.manage']` believed they had restricted who could invoke the skill, and had not. A silent permission hole — the same shape as `visibleWhen` → `visible` in #3746, where the most valuable alias was not a typo but a key that READS as a security control and silently is not one. A test pinned that strip as correct behaviour. Its comment even carried the right answer — gate at the AGENT via `access`/`permissions`, enforced since #1884 — but a comment in a test file reaches everyone except the author who got it wrong. The rejection now carries the prescription; the test asserts the rejection. That is the fourth test in this campaign found codifying a strip-era fiction as expected behaviour (`position.parent`, `object.namespace`, the retired `compactLayout` alias, and now this one). The pattern is consistent enough to state: when a schema is silently lenient, its tests eventually assert the leniency, and the assertion then reads as intent. Registered types closed at the top level: 16 of 25, up from 9 when this line started. Still open: action, agent, dashboard, field, mapping, page, translation, view. The warning layer's covered population drops 12 roots → 6, which is the parse taking over rather than coverage rotting; nested strip sites under a closed root still report, unchanged. Verified: spec 284 files / 7187 tests, `tsc --noEmit` clean, all 8 generated artifacts current, all 15 `check:*` gates green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
enabled auto-merge
August 1, 2026 17:09
This was referenced Aug 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#4001 批 4(清单)。批 1–3b = #4514 / #4519 / #4522 / #4527,均已合并。
注册类型线上的机械工作,用
strictObject:report·dataset·email_template·skill·job·book。每个一次调用,加上贴合各自词汇表的别名——book 的sections/chapters/toc→groups,job 的cron/interval→schedule,email template 的title/content/html→subject/body。但其中一个不是机械工作,而且正是这场战役存在的理由
skill接受一个permissions键,然后把它丢掉。技能调用从来就没有权限门。 一个写下
permissions: ['order.manage']的作者,以为自己限制了谁能调用这个技能——实际上没有。这是一个静默失效的权限漏洞,和 #3746 里的
visibleWhen→visible同形:别名表里最值钱的那条从来不是错别字,而是一个读起来像安全控制、实际不是的键。有个测试把这个剥离钉成了正确行为。它的注释里甚至写着正确答案——在 agent 层用
access/permissions门控(自 #1884 起真正生效)——但一句写在测试文件里的注释,能到达所有人,除了写错的那个作者。现在拒绝信息带上这句处方,测试改为断言拒绝。
一个已经四次的模式
这是本战役第四个被发现把「strip 时代的假象」固化成预期行为的测试:
position.parent被接受object.namespace被剥离是对的compactLayout被剥离是对的skill.permissions被剥离是对的规律稳定到可以陈述:一个 schema 只要默认宽松,它的测试最终会断言那份宽松,而那条断言读起来就像「这是有意为之」。
进度
注册类型顶层已关闭:16 / 25(这条线开始时是 9)
仍剥离:
action·agent·dashboard·field·mapping·page·translation·view告警层覆盖的根从 12 降到 6——这是解析接管,不是覆盖腐烂。被关闭的根下面那些仍是 strip 的嵌套站点照常告警(那是 #4522 修掉的回归)。
验证
@objectstack/spec:284 文件 / 7187 用例通过(对合并后的 main 重跑),tsc --noEmit干净check:*全绿参考
visibleWhen先例)、[P0][security] Agent access control is a no-op (permissions/visibility/access) #1884(agent 层权限门)🤖 Generated with Claude Code
https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY
Generated by Claude Code