Skip to content

feat(spec)!: view 面收紧 —— #4001 最后一批 - #4534

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

feat(spec)!: view 面收紧 —— #4001 最后一批#4534
os-zhuang merged 1 commit into
mainfrom
claude/strict-schema-authz-surface-s8vnok

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

#4001 最后一批清单)。批 1–6d = #4514#4533,均已合并。

为什么 view 最会藏

视图是作者用眼睛迭代的那个面——所以一个被丢弃的键在这里最隐蔽:视图照样渲染,只是不是他描述的那个样子

FormFieldBase / FormSection / FormButtonConfig 早在 ADR-0089 D3a 就关了。文件里另外四十多个形状,保持的正是那三个当年被救出来的姿态。

defineView 的守卫,是第五个「只守一扇门」的补丁

它的注释自己写着理由:

ViewSchema strips unknown top-level keys,所以一个扁平的 list view 会解析成一个空容器。

这是本战役找到的第五个为绕开静默剥离而建的 bespoke 守卫,而且和前四个一样——它只守了 defineView 这一扇门。走元数据门(Studio / API / agent)的,拿到的是一个静默的空容器。

现在拒绝在解析层,两扇门都覆盖,而且带上「该怎么包起来」的指令。守卫留着,管 strict 看不见的那个 case:defineView({})——没有未知键,照样零视图注册

三处刻意不转,每处都把理由写进文件

形状 为什么
FormSectionSchema 早已关闭,带 strictVisibilityError 和归一化 .transform()。转换 = 重写可用且有测试的行为
UserFiltersSchema 故意 strip 掉 page-only 的 tabs/showAllRecords,有测试钉着。改成拒绝需要单独验证——这批没验证就不动,点名留在文件里
扁平 Studio overlay 必须开放:承载 isPinned/sortOrder 等往返键,saveMetaItem 原样持久化

第三处正是账本预告过的 .extend() 陷阱.extend() 继承 strictness,关闭 ListViewSchema 让这个 overlay 静默变严——对平台自己写入的形状 422

抓到它的是一个测试的名字

"preserves auxiliary Studio round-trip keys without a strict-mode 422"

有人在这场战役存在之前,就精确命名了未来某次收紧会造成的失败。

⚠️ 我在最后两批里,同一个错误犯了四次

假处方 实际 谁抓到的
action.permissions「没有权限键」 requiredPermissions 有,403 强制——照做会删掉一个正在工作的门 docs-drift 清单
action.locationlocations 反了,把正确的键改名到不存在的键 同上
view.name / view.label 容器带自己的身份,平台自己在写 @objectstack/objectql
view.object 容器靠它绑定对象,getViewsByObject() 读它 @objectstack/cli

没有一次是靠写 schema 时发现的。

最后管用的不是「更小心」,是换方法:把仓库里每一个真实的 container 载荷扫一遍,只保留没有任何真实载荷反驳的 guidance 条目。九条活六条,杀三条——一条命令,而且能在第一次 CI 红之前抓到全部四个

一个墓碑断言的是「没有任何合法的东西会写这个键」。那是一个关于代码库的经验性主张,而代码库是可以被问的。

推论两条,已写进账本:拒绝信息里的散文是行为,不是文档(一条自信地写错的比没有更糟,因为作者没有理由怀疑它);关闭一个注册类型的影响半径是每一个解析那个类型的包

🏁 view 是终点,不是最后一笔欠债

注册的 view 是三个运行时形状的 union,union 的严格程度取决于它最开放的成员——那个成员就是上面那个 Studio overlay,一个穿着同一个类型名的 wire 形状

所以战役停在 24 / 25 关闭,第 25 个是有据可查的永久例外。这段写在反向钉旁边,免得后来者「为了凑齐」硬把它关上

关掉的是作者写的全部;留开的,正是账本开头那条分类规则要划的线——在最后一步以答案的身份出现,而不是以例外的身份

战役结账

起点 现在
注册类型顶层关闭 9 / 25 24 / 25(第 25 个有据可查)
ADR-0010 信封欠债 8 0
告警层覆盖的根 15 1

一个为「警告 strip 模式元数据」而建的层,几乎没有东西可警告了——那是棘轮走到头。 它的测试在原地写着:把下限改成 0 并刻意断言空集,永远不要删掉这个测试——因为一个没人选择的空结果,和一个坏掉的推导,长得一模一样

验证

  • 全仓测试套件 132 / 132 任务全绿
  • @objectstack/spec7241 用例tsc --noEmit 干净
  • 8 个生成物 up-to-date10 个 spec check:* 全绿
  • liveness:三个新键如实分类(object = live 附消费者;name/label = dead 的 body 键,行上的列才是活的)

授权影响:这些形状没声明的键从「静默丢弃」变成「拒绝」——本来就已经被忽略。

🤖 Generated with Claude Code

https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY


Generated by Claude Code

Views are the surface an author iterates on visually, which is why a dropped key
hides here: the view still renders, just not the way it was described.
`FormFieldBase` / `FormSection` / `FormButtonConfig` closed years ago under
ADR-0089 D3a; the other forty-odd shapes kept the posture those three were
rescued from.

`defineView`'s guard was another one-door workaround — its own comment says
"`ViewSchema` strips unknown top-level keys, so a flat list view would parse to
an empty container". Fifth bespoke guard this campaign has found built around
silent stripping, and like all of them it covered exactly one door. The
rejection now lives in the parse, reaches both, and carries the wrap
instruction. The guard stays for what strict cannot see: `defineView({})`.

Three shapes deliberately left open, each with its reason in the file rather
than a silent skip: `FormSectionSchema` (already closed with its own error map
and a transform), `UserFiltersSchema` (deliberately strips page-only keys, with
a test asserting it — changing that needs its own verification), and the
flattened Studio overlay in `ViewMetadataSchema`, which must stay open.

That last one is the `.extend()` trap the ledger warned about: closing
`ListViewSchema`/`FormViewSchema` silently closed the overlay too, turning a
shape the platform itself writes into a 422. Both `.strip()` back. It was caught
by a test whose name is the whole contract — someone wrote "preserves auxiliary
Studio round-trip keys without a strict-mode 422" before this campaign existed.

The container's `name`, `label` and `object` were tombstoned in the first draft
and should not have been: the platform writes all three. Fourth false guidance
claim in three batches. What fixed it was not more care but a different method —
scan every real payload of the shape in the repo and keep only the entries no
real payload contradicts. Six of nine survived. A tombstone asserts "nothing
legitimately writes this key", which is an empirical claim, and the codebase can
be asked.

`view` is the end state, not the last item of debt: its registered schema is a
union of three runtime shapes and a union is only as closed as its most open
member — the Studio overlay, a wire shape wearing the same type name. So the
campaign finishes at 24 of 25 closed with the 25th a documented permanent
exception, recorded beside the reverse pin so nobody closes it by force.

Verified: full monorepo suite 132/132 tasks green, spec 7241 tests, tsc clean,
8 generated artifacts current, all 10 spec gates green.

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 21:34
@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 9:34pm

Request Review

@os-zhuang
os-zhuang enabled auto-merge August 1, 2026 21:34
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests protocol:ui tooling size/m labels Aug 1, 2026
@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 48fbacb Aug 1, 2026
21 checks passed
@os-zhuang
os-zhuang deleted the claude/strict-schema-authz-surface-s8vnok branch August 1, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants