Skip to content

feat(spec)!: field 收紧,复用那张早就知道哪条建议是错的表(#4001 批 6b) - #4531

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

feat(spec)!: field 收紧,复用那张早就知道哪条建议是错的表(#4001 批 6b)#4531
os-zhuang merged 1 commit into
mainfrom
claude/strict-schema-authz-surface-s8vnok

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

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

这个对象为自己写了两个 release 的检讨

FieldSchema 携带的「被静默剥离的键」比 spec 里任何一个形状都多,而且它自己一直知道。对象上有两处注释——一处讲 accept/maxSize,一处讲被砍掉的五个治理键——都写着「写下去会 parse 干净、键被静默剥离」,都点名这是 ADR-0104 那一类失败

两次都只能写注释,因为这个对象不是 .strict()。这个 PR 就是那两段注释想要的修复。

guidance 是推导的,不是手写的——因为手写那版当场犯了错

FIELD_KEY_GUIDANCE(在 data/authoring-key-lint.ts)是专为这个表面curated 的二十多条,每一条都是野外抓到的,而且已经被测试守着(每个 to 必须真的是 FieldSchema 声明过的键)。

我第一版在旁边手写了一张 guidance 表。那是真相的第二份拷贝,而它立刻证明了为什么这不行:

lint 那张表特意压掉了 pii 的建议,因为 pii 距离 min 只有 3 个编辑距离

于是一个纯编辑距离的建议器,会对一个「个人可识别信息」的键回答「你是不是想写 min」——自信、错误、而且是完全无关的概念。手写那版不知道这件事,拒绝信息就是这么说的。

现在 FieldSchema 直接读那张表(to → alias,why → guidance)。

注意搬动的是什么:表没变,也没废弃——变的是它的消费者field 关闭后 lint 不再走到它,于是同一份 curation 从「驱动一条告警」变成「驱动一条拒绝」。那正是这张表里每一条的目标终点。

其中最要紧的两条,是读起来像保护、实际不是的那两个:

实际
encryptionConfig 2026-06 被砍,因为它「暗示了从未发生的静态加密
maskingRule 同上,掩码从未被应用

一个声明了它们的字段,存的就是明文,和没声明一模一样,而且一声不吭。拒绝信息现在指向 type: 'secret'requiredPermissions(ADR-0066 D3,由 FieldMasker 真正执行)。

一个整个测试套件都通过了的循环依赖

shared/suggestions.zoddata/field.zod 导入 FieldType。所以 field.zod 一用上 strictObject,图就闭环了:

field → strict-object → suggestions → field

OS_EAGER_SCHEMAS=1build-schemas.ts 的运行方式)下,每个 lazySchema 体在模块初始化时就执行,于是加载器撞上一个半初始化的模块,在任何一个 schema 建出来之前就抛了 Cannot read properties of undefined (reading 'strictUnknownKeyError')

284 个测试文件、7239 个用例,全绿地从它上面开过去。

测试是懒加载的,那个会炸的解析顺序根本不会出现。只有 eager 构建能抓到。 这是第 9 条发现的另一面——那次是仪器报告了它没有的覆盖率,这次是仪器根本不对,而绿色对这个失败模式什么都不意味着。

修法:strictObject 把 error map 推迟到首次使用。代价为零(只有拒绝时才需要它),而且让 helper 对后面每一个 schema 都免疫循环,而不是让每次转换自己去证明「我不在环里」。

property 用一个可观测量钉住了——alias 表上的一个 getter,正好在 map 被构建时触发——并且验证过:把 map 提回构造期,它会报红。

闸门

field 补上 ADR-0010 信封。它是当初那个探针唯一真正检查过的类型(另外 24 个都走了 early return),所以在探针报绿的那段时间里,它是唯一看得见的缺口——结果它比探针藏起来的每一个缺口都活得更久

信封欠债从 8 降到 1(只剩 action)。

SelectOptionSchemaCurrencyConfigSchema 以及 FieldSchema 下的嵌套形状(lookup 列、lookup 过滤、dependsOn、roll-up)一并关闭。

刻意不动的AddressSchema / LocationCoordinatesSchema / CurrencyValueSchema 是运行时形状,全仓没有任何消费者,其中两个已标记随下个 major 移除——它们不是授权面,strictness 不是它们该回答的问题。

进度

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

验证

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

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

参考

🤖 Generated with Claude Code

https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY


Generated by Claude Code

…w which advice would be wrong (#4001)

`FieldSchema` carries more silently-stripped keys than any shape in the spec,
and it said so about itself for two releases. Two notes on the object — one on
`accept`/`maxSize`, one on the five pruned governance keys — both state that a
write "parsed clean and the key was silently stripped", and both name it the
ADR-0104 failure class. Neither could act, because the object was not strict.

The guidance is derived rather than hand-written, and the reason is a bug the
first pass shipped. `FIELD_KEY_GUIDANCE` is twenty-odd curated entries for this
exact surface, already held honest by a test. A hand-written table beside it is
a second copy of the truth, and it proved that immediately: the lint suppresses
the suggestion for `pii` BECAUSE `pii` is three edits from `min`, so a bare
suggester answers a personally-identifiable-information key with "did you mean
`min`?" — confident, wrong, unrelated. The hand-written pass did exactly that.
`FieldSchema` now reads the table (`to` → alias, `why` → guidance). The table is
unchanged; its consumer moved, which is the intended end state for every entry.

The two entries that matter most are the ones that read as protection and were
not: `encryptionConfig` and `maskingRule` "implied at-rest protection that never
happened". A field declaring either was stored in plaintext exactly as if it had
not, silently. The rejection now points at `type: 'secret'` and
`requiredPermissions`.

A cycle the whole test suite passed through. `suggestions.zod` imports
`FieldType` from `field.zod`, so adopting `strictObject` here closed a loop.
Under OS_EAGER_SCHEMAS=1 every lazySchema body runs at module init, so the
loader hit a half-initialized module and threw before any schema was built.
284 files and 7,239 cases went green over it — tests import lazily, so the cycle
never resolved in the order that breaks. Only the eager build caught it.

`strictObject` now defers its error map to first use: free, and cycle-proof for
every schema after this one instead of making each conversion prove it is not in
a loop. Pinned via an alias-table getter that fires exactly when the map is
built, and verified to go red when the map is hoisted back to construction.

`field` gains its ADR-0010 envelope — it was the ONE type the original probe
actually checked, so it was the only gap visible while that probe was green, and
it outlasted every gap the probe was hiding. Debt list down to one, from eight.

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

Verified: 284 files / 7240 tests, tsc clean, 8 generated artifacts current, all
10 spec gates green, and CRM/Todo/showcase/platform-objects build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY
@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:46pm

Request Review

@os-zhuang
os-zhuang marked this pull request as ready for review August 1, 2026 18:46
@os-zhuang
os-zhuang enabled auto-merge August 1, 2026 18:46
@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:data tests 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 07a4e26 Aug 1, 2026
21 checks passed
@os-zhuang
os-zhuang deleted the claude/strict-schema-authz-surface-s8vnok branch August 1, 2026 19:08
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:data size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants