Skip to content

feat(spec)!: mapping/agent/page 收紧,strictObject 不再把作者指向已删除的键(#4001 批 6a) - #4530

Merged
os-zhuang merged 1 commit into
mainfrom
claude/strict-schema-authz-surface-s8vnok
Aug 1, 2026
Merged

feat(spec)!: mapping/agent/page 收紧,strictObject 不再把作者指向已删除的键(#4001 批 6a)#4530
os-zhuang merged 1 commit into
mainfrom
claude/strict-schema-authz-surface-s8vnok

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

#4001 批 6a(清单)。批 1–5 = #4514 / #4519 / #4522 / #4527 / #4528 / #4529,均已合并。

先修这场战役自己捅的娄子

上一批 skill 关闭时,它还带着 retiredKey 墓碑。而 strictObject 的「你是不是想写」候选表取自整个 shape——墓碑也在里面。于是:

Unrecognized key(s) on this skill: `triggerPhrase`. …
Did you mean `triggerPhrase` → `triggerPhrases`?

triggerPhrases是被删掉的键。 照做的作者会撞上墓碑,拿到第二条拒绝,告诉他把刚被指示写下的东西删掉。

账本里已经记了两次的形状,这是第三次——而且第一次出现在共享 helper 里,也就是说它会流向之后每一次转换。两个 helper 各自都是对的,只有组合起来是错的——这种缺陷没有任何单 schema 的测试会去找。

修法不是给墓碑开特例,而是一条更窄也更稳的规则:永远不要建议一个 schema 根本不接受的键。 候选表剔除接受 never 的键(不管包了几层)。

两者是互补的,不是重复:retiredKeyguidance 更强——它把键的类型变成 never,所以即使配置是从变量传进来的也会 tsc 报错,而这正是 excess-property 检查够不到的地方。

agent 有两个安全形状的删除,没有墓碑

visibilitytenantId 当初作为未被强制执行的安全属性被删除——删得对,它们确实什么都没做——但删的时候没留处方,因为那时 shape 是 .strip,根本没有一条拒绝可以挂。

一个写下 visibility: 'private' 的作者,以为这个 agent 被隐藏了。它对所有人可见,而且一直如此。

又是 skill.permissions 那一类:读起来像安全控制、实际不是、写下去还一声不吭。现在两条都指向真正门控 agent 的东西(access / permissions,自 #1884 起在 chat 路由上真正生效)。

route —— 平台自己的测试套件里养了多年的虚构键

stack.test.ts 里写着 route: '/landing'PageSchema 从来没有声明过 route——页面由 name 路由,而在这个测试用的 map 格式里,name 就是 map 的键这正是同一个测试在六行之后断言的东西

第五个被发现「把 strip 时代的假象固化成预期」的测试,而且是最容易被重新发明的一个——route 是任何人在页面上第一个会去写的键。已连同 pathurl 一起立碑。

测试断言的 实际是
position.parent 被接受 层级根本不存在
object.namespace 被剥离是对的 对象会以错误的名字发布
退役的 compactLayout 被剥离是对的 作者拿不到任何提示
skill.permissions 被剥离是对的 一个不存在的权限门
page.route 被剥离是对的 一个从未存在的路由键

顺带立碑(因为现在终于有地方放了)

  • agent.memory.shortTerm —— 声明了一个运行时无人消费的工作记忆窗口(ADR-0013 D3)
  • page.recordReview / page.blankLayout —— 没有渲染器的页面类型(framework#2265)
  • interfaceConfig.visualization —— 显示方式是 visualization,不是 page type,从 appearance.allowedVisualizations 里运行时选
  • guardrails.allowedTopics —— 没有白名单,只有 blockedTopics 黑名单

闸门

mappingpage 补上 ADR-0010 保护信封。信封欠债从 8 降到 2(只剩 actionfield)。

头条数字改成推导,不再手数。 它已经飘了 1 ——在一场反复发现「手工维护的覆盖率度量会腐烂」的战役里。STILL_STRIP 带反向钉,和信封欠债表一样;并且我先验证了它能双向报红才敢信它:把已关闭的 agent 塞进去 → 红;把仍 strip 的 view 拿出来 → 红;恢复 → 绿。

注册类型顶层已关闭:21 / 25。仍剥离:action · dashboard · field · view

告警层覆盖的根从 6 降到 3 —— 验证过是交接不是窟窿agent.zzzpage.zzz、嵌套的 page.regions[0].zzz 现在都被解析拒绝。一个坏掉的遍历和一次成功的毕业,会让这个数字以完全相同的方式变小,所以这条检查就钉在数字旁边。

验证

  • @objectstack/spec284 文件 / 7239 用例通过tsc --noEmit 干净
  • 8 个生成物 up-to-date,spec 全部 check:* 绿
  • CRM / Todo / showcase / platform-objects 构建全部通过

授权影响:这些形状没声明的键从「静默丢弃」变成「拒绝」——本来就已经被忽略,没有在工作的元数据会变。

参考

🤖 Generated with Claude Code

https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY


Generated by Claude Code

…ing removed keys (#4001)

The helper bug first, because this campaign put it there. `skill` closed last
batch while still carrying `retiredKey` tombstones, and `strictObject` built its
"did you mean" candidates from the whole shape — tombstones included. So a
`triggerPhrase` typo was answered with "Did you mean `triggerPhrases`?", a key
that had been REMOVED, and the author who complied got a second rejection
telling them to delete what they had just been told to write.

Third occurrence of a shape the ledger already records twice, and the first one
in a SHARED helper, where it would have reached every conversion after it. Both
helpers were correct alone; only the combination was wrong. Fixed structurally
rather than by special-casing tombstones: never suggest a key the schema cannot
accept. They stay complementary — `retiredKey` is stronger than `guidance`,
since typing the key as `never` also fails `tsc` through a variable, where
excess-property checking would not fire.

`agent` had two security-shaped removals with no tombstone. `visibility` and
`tenantId` were deleted as unenforced security properties — correctly — but
without a prescription, because the shape was `.strip` and there was no
rejection to hang one on. An author who wrote `visibility: 'private'` believed
the agent was hidden; it was listed to everyone, and always had been. The
`skill.permissions` class again. Both now name what actually gates an agent.

`route` on a page was a fiction the platform's own suite carried. `stack.test.ts`
authored `route: '/landing'` for years; `PageSchema` never declared it, and a
page is routed by its `name` — which in the map format under test IS the map
key, which the test asserted six lines below the key contradicting it. Fifth
test found codifying a strip-era fiction, and the likeliest to be reinvented.

`mapping` and `page` gain their ADR-0010 envelope. The undeclared-envelope debt
list is down to two, from eight.

The headline number is now derived instead of tallied — it had already drifted
by one, in a campaign whose recurring finding is that hand-maintained coverage
measurements go stale. `STILL_STRIP` carries a reverse pin like the envelope
list; verified it goes red in both directions before being trusted.

Registered types closed: 21 of 25. Still open: action, dashboard, field, view.

The warning layer's covered roots drop 6 → 3, verified as a hand-off rather than
a hole: `agent.zzz`, `page.zzz` and nested `page.regions[0].zzz` are each now
rejected by the parse. A broken walk and a graduation shrink that count
identically, so the check is pinned next to the number.

Verified: 284 files / 7239 tests, tsc clean, 8 generated artifacts current,
all spec gates green, and the CRM/Todo/showcase/platform-objects builds pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY
@os-zhuang
os-zhuang marked this pull request as ready for review August 1, 2026 18:17
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 1, 2026 6:17pm

Request Review

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang added this pull request to the merge queue Aug 1, 2026
Merged via the queue into main with commit 7cf42fe Aug 1, 2026
21 checks passed
@os-zhuang
os-zhuang deleted the claude/strict-schema-authz-surface-s8vnok branch August 1, 2026 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants