fix(spec): protocol-17 rationale 改述 area 项级门禁的现状 —— #4722 已关闭「服务端不走 areas」那条 caveat (#5337) - #5796
Conversation
…#4722 closed the "server does not walk `areas`" caveat (#5337) `MIGRATIONS_BY_MAJOR[17].rationale` still carried the caveat written at the #4651 retirement: per-item gating inside an area is enforced by the shell only, since the server does not walk `areas`. #4722 landed in the same 17.0.0 window and made that false — `filterAppForUser` runs the same `filterNav` over every `areas[].navigation`, so an item's `requiredPermissions` / `requiresService` is stripped server-side in both trees. That prose is not a comment: `docs/protocol-upgrade-guide.md` is a pure projection of it (ADR-0087 D4), i.e. the page an author upgrading 16 -> 17 reads, and the sentence sent them off to restructure their navigation tree for a gate they can now write in place. - registry.ts: history anchored ("At the time of the retirement …") and the caveat replaced with the corrected fact — #4722 named, both trees named, area-LEVEL keys explicitly still retired, `visible` (CEL) explicitly still client-side only at every level. - `.changeset/app-area-fail-open-gates-removed.md`: same sentence corrected (repo is in changesets pre mode, so that file is still a live input to the v17 GA notes). - `docs/protocol-upgrade-guide.md` regenerated via `gen:upgrade-guide`, not hand-edited. - migrations.test.ts: five pins on the step-17 rationale. Wording mirrors the schema-side prescriptions landed by PR #5336 and the `areas.navigation` note in `packages/spec/liveness/app.json`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 110 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
越界发现补记(更正正文最后一节)正文写「未发现需另开单的越界缺陷」时尚未查到第四处。收尾复查发现一处,未在本 PR 修复,已按 Prime Directive #10 独立开单: #5809 — 判为 observation-class( CI24 项检查全部完成,零失败(success 或 skipped)。其中与本单直接相关的: 机器人落定后读回的标签: Generated by Claude Code Generated by Claude Code |
Fixes #5337
前提复核(先于实现)
对
origin/main(1624f4a)逐处核实,三处全部命中,单据属实:packages/spec/src/migrations/registry.ts:672–674grep "One honest caveat"命中(单行 grep 整句零命中,正是单据提醒的读数陷阱)docs/protocol-upgrade-guide.md:173.changeset/app-area-fail-open-gates-removed.md:54–58反证一侧同样核实:
packages/rest/src/rest-server.ts的filterAppForUser在 2441 行带[#4722]注释,2520 行filterAreas对每一棵areas[].navigation复用同一个filterNav(2526 行),项级requiredPermissions/requiresService在两棵树被同等强制;2449–2452 行同时写明visible(CEL)与requiresObject仍只在客户端求值。一处补充发现,与本单口径相关且已一并处理:仓库处于 changesets pre 模式(
.changeset/pre.json的mode: "pre"),所以app-area-fail-open-gates-removed.md虽然已经进过packages/spec/CHANGELOG.md的17.0.0-rc.2段落,文件本身仍留在.changeset/里,并且仍是 v17 GA 发布说明的法定输入 —— 即 PM 裁定「一并改」的效力是真实的,不是改一份已消费掉的稿子。已发布的CHANGELOG.md属既成历史,本 PR 零改动。改了什么
1.
registry.ts的 protocol-17 rationalechecks/walks/never reads改为过去时并前置At the time of the retirement。理由:紧邻一句新写的「filterAppForUser 只走 app 顶层 navigation —— areas[] 里的 nav 项权限过滤仅客户端生效(#4651 移除假闸门后剩下的真缺口) #4722 已关闭该边界」,前半段若仍是现在时,同一段落会自相矛盾。这也正是 PR fix(spec): 两条 area 退役处方在 #4722 之后改口径 —— 项级闸门在两棵树都由服务端剥离 (#4749) #5336 在ui/app.zod.tsdocblock 里采用的处理(682–689行:at the time of the retirement … read … walked ONLY … never touched),本 PR 按同一蓝本对齐。areas[].navigation、点明被门禁的条目根本不进/meta响应体。visible的口径:显式写visible(CEL)与requiresObject在每一层仍只在客户端求值,所以绝不可到达浏览器的东西写在requiredPermissions,永远不写在visible—— 这是 filterAppForUser 只走 app 顶层 navigation —— areas[] 里的 nav 项权限过滤仅客户端生效(#4651 移除假闸门后剩下的真缺口) #4722 之后新出现的误读风险(「area 现在有门了,那visible也行吧」),fix(spec): 两条 area 退役处方在 #4722 之后改口径 —— 项级闸门在两棵树都由服务端剥离 (#4749) #5336 的处方同样把它钉住了。措辞蓝本:PR #5336 落地的
AREA_VISIBLE_RETIRED/AREA_REQUIRED_PERMISSIONS_RETIRED,以及packages/spec/liveness/app.json的areas.navigation记录。2.
.changeset/app-area-fail-open-gates-removed.md同一句按 PM 裁定一并改(裁定否决窗口已过)。retirement kit 表格两行未动 —— 它们本来就叫作者把门禁下沉到 area 的
navigation项上,#4722 之后这条建议只是从「壳层强制」升级为「服务端强制」,原文无需改。⛔content/docs/releases/零改动。3.
docs/protocol-upgrade-guide.md未手改,由
pnpm --filter @objectstack/spec gen:upgrade-guide重新生成;check:upgrade-guide复验up to date。反向验证(方向:预测为红,实测为红)
把 caveat 那句还原成改前措辞(仅这一句,其余不动)后重跑
migrations.test.ts:第 5 条
still carries the #4651 history the step exists to explain按预期保持绿:它钉的是被保留的历史前半段,而反向实验只还原了 caveat 一句 —— 这条本就不该随之变红,如实记录而非凑成「五条全红」。一条 pin 在编写过程中被实测证伪并按事实修正:最初写的
not.toMatch(/enforced by the shell only/i)会连引用旧论断的历史陈述一起判红,而新措辞刻意保留了这句引用(读者需要知道旧建议作废,而不是让处方对areas[]悄悄闭嘴 —— 那会让他以为旧边界仍然成立)。改为钉时态:not.toMatch(/is enforced by the shell only/i)+toMatch(/was CLOSED by #4722/)。测试
Changeset
带自己的 changeset(
patchon@objectstack/spec),不走skip-changeset。理由:MIGRATIONS_BY_MAJOR[17].rationale是@objectstack/spec导出的运行期数据(os migrate meta打印给消费者),docs/protocol-upgrade-guide.md是面向读者的投影 —— 两者都不是纯测试/纯工作流改动。落地前注意
check:authorable-surface在--check模式下也会重写authorable-surface.base.json—— 一次纯核验会改工作区,且任何无关 PR 都能因此静默推进删除门的锚点 #5358:任何 spec build/gen 会顺带改写packages/spec/authorable-surface.base.json。已逐文件核git status,该文件未出现在本 PR 中(gen:upgrade-guide单独跑不触发它)。docs/protocol-upgrade-guide.md在.gitattributes的 os-regen 驱动路径上。合入 main 时按四步走:git merge origin/main→git checkout origin/main -- 生成物→ 先提交 merge → 整体重新生成 → 断言兄弟条目仍在。⛔ merge 未提交时不得跑 gen 脚本(os-regen 驱动指示的gen:schema在 merge 未 commit 时运行,会把 authorable-surface 锚点倒退回旧 merge-base —— 生成器写入、门全绿、静默撤销 main 的锚点推进 #5370)。越界
本 PR 只碰
packages/spec/src/migrations/registry.ts、其生成物、两份.changeset/*.md与migrations.test.ts。packages/spec/src/ui/app.zod.ts/app.test.ts只读未改(PR #5336 已落地)。未发现需另开单的越界缺陷。🤖 Generated with Claude Code
https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
Generated by Claude Code