Skip to content

[design] ADR-0104: field runtime value-shape as a first-class contract (spec-owned), typed action handlers, file-as-reference#3412

Open
os-zhuang wants to merge 5 commits into
mainfrom
claude/field-value-shape-contract-1z4pil
Open

[design] ADR-0104: field runtime value-shape as a first-class contract (spec-owned), typed action handlers, file-as-reference#3412
os-zhuang wants to merge 5 commits into
mainfrom
claude/field-value-shape-contract-1z4pil

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

纯设计文档:新增 docs/adr/0104-field-runtime-value-shape-contract.md(Status: Proposed),不含任何代码改动。

背景

#3405 / #3406(内联 lookup 参数的 reference.strip 静默吃掉)修掉的是一个键;这份 ADR 处理它背后的类问题:**字段的运行时值形状(value shape)在整个平台里不是任何人的契约。**代码盘点(全部带 file:line 证据,见 ADR 正文)发现:

  • 值形状知识在 4 处手工重复:record-validator.ts(私有 MULTI_CAPABLE_TYPES,单值 lookup / file / location 等完全不校验,line 341「opaque payloads」)、import-coerce.ts(6 份自己的类型集合)、driver-sql(JSON_COLUMN_TYPES / NUMERIC_SCALAR_TYPES)、verify/read-coercion.ts(只覆盖 3 个类型)。
  • spec 导出的 3 个值 schema 全部无人消费,其中 2 个与实际存储直接矛盾(CurrencyValueSchema{value,currency},实际存裸 number;LocationCoordinatesSchema{latitude,longitude},field-zoo 存 {lat,lng})——正是 ADR-0078 禁止的「导出但惰性」。
  • 动作参数声明(type/required/multiple/accept/maxSize)只喂给客户端弹窗;服务端 handleActions 原样透传 reqBody.params(http-dispatcher.ts:3882,MCP 路径同样),沙箱 input: unknown,handler 注册签名 (ctx: any) => any,现有 handler 全靠裸 as 强转。
  • 文件字段存无 schema 的内联 JSON blob({url,name,size}),完全绕开平台已有的 sys_file 一等文件原语(生命周期 GC、下载鉴权、稳定 /files/:fileId 解析器)——attachment-lifecycle.ts:27-29 自己就写着字段列的引用是 join-row 计数看不见的。后果:无引用完整性、清空字段永久泄漏 blob、非附件文件全部匿名 capability URL、FieldSchema 里连 accept/maxSize 都没有、client.storage.upload() 甚至拿不到 fileId(complete 响应把它丢了)。

决策概要

备注

🤖 Generated with Claude Code

https://claude.ai/code/session_01SHpGw3GBA9aFpfwVArRWfd


Generated by Claude Code

…ract

Design for three coupled gaps with one root cause (the runtime value shape
of a field is nobody's contract):

- D1: spec-owned valueSchemaFor(field) + semantic type classes; converge the
  four hand-duplicated type lists (record-validator, import-coerce,
  driver-sql, verify); reconcile the three dead value-schema exports; wire
  the field-zoo oracle to the contract.
- D2: typed action handlers — declared params validated at REST/MCP dispatch,
  typed ctx.params via FieldValue<T>, file params become fileId references.
- D3: file-as-reference — Field.file/image values store sys_file ids instead
  of inline {url} blobs, joining the existing lifecycle/GC/authz machinery.
- D4: three-phase rollout (non-breaking convergence -> param enforcement ->
  protocol-major file migration).

Generalizes the #3405/#3406 silently-stripped-param incident; relates #3407,
#1878/#1891.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SHpGw3GBA9aFpfwVArRWfd
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 22, 2026 10:06pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation size/m labels Jul 22, 2026
claude added 2 commits July 22, 2026 20:52
…get sections

Nine named risks (legacy-row stranding, warn-first rollout, unknown-key
allowlist, GC freeze during migration, public-posture inventory, sub-key
read breakage, external-URL retirement, cross-repo sequencing, spec purity)
and the performance budgets/benchmark gates for each phase, so the phase
PRs inherit them as acceptance items.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SHpGw3GBA9aFpfwVArRWfd
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 size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants