Skip to content

[决策] readonly 剥离的 strict/reject 模式落在哪一层 —— B(WriteObservabilityOptions)推荐,A/C/D 各有代价(#4903 后续) #5126

Closed

Description

@claude

要拍板什么

readonly 剥离的 strict/reject 模式(供 cron/服务端插件在调用点选择「被剥离即响亮失败」而非静默丢列)落在哪一层。#4903(PR #5123)已把可发现性与文档修好,strict 半边因四个候选落点全部触碰 packages/spec/**(本车道冻结)而止步。

四个选项(完整两轴分析见 PR #5123 正文,此处摘要)

选项 落点 要害
A EngineUpdateOptionsSchema(可序列化 Zod 袋) 可跨 RPC/REST —— 但客户端可设置,在安全相邻路径上开新攻击面;拖动生成物
B(推荐) strictReadonlyWrites 挂 WriteObservabilityOptions(TS 契约,onFieldsDropped 所在) 进程内、客户端不可达、与既有先例同类;抛 ERR_READONLY_FIELD_REJECTED 带字段清单
C 部署级开关(env/构造配置) 全局改行为 —— REST 边界的伪造输入也从剥离变报错,兼容性变更;无法表达「只这一个 cron 要响」
D objectql 包内私加 ⛔ 实现而不声明 —— PD#12 反形,不建议

推荐 B:两轴同向 —— 唯一让 AI 写的 cron 在调用点拿到点名异常(而非绿调用 + 数周后发现 null 列)、又结构性不给客户端碰的方案。若你想覆盖 RPC/VDE 面,那是 A 的独立放宽,应单独定而非顺手带。

两个关联输入(#5123 报告的,同一次拍板可一并看)

  1. ExecutionContext 无 origin/channel 标记 —— isSystem 是唯一信任位,故剥离接缝无法区分伪造 REST body 与可信服务端代码;任何按来源分级的策略都以补这个标记为前提;
  2. onFieldsDropped 不跨 RPC/VDE 边界(契约已文档化)—— strict 决策应顺带说清远程调用方拿什么。

Blocked-by: objectstack-ai/objectstack#4903(PR #5123 合并后动手)
落点:packages/spec/src/contracts/data-engine.ts + objectql —— spec 车道或维护者授权例外。


Generated by Claude Code

Activity

  1. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Aug 4, 2026
  2. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    Contributor

    维护者拍板:取 B

    strictReadonlyWrites 挂 WriteObservabilityOptions(TS 契约,onFieldsDropped 所在),被剥离时抛 ERR_READONLY_FIELD_REJECTED 并带字段清单。不取 A(可序列化 Zod 袋 —— 客户端可设置,在安全相邻路径上开新攻击面)、不取 C(部署级开关 —— 无法表达「只这一个 cron 要响」,且把 REST 边界的伪造输入一并变成报错)、不取 D(实现而不声明,PD#12 反形)。needs-user-decision 摘除。

    依据:B 是唯一让 AI 写的 cron 在调用点拿到点名异常(而不是绿调用 + 数周后发现 null 列)、同时结构性不给客户端碰的方案。若日后要覆盖 RPC/VDE 面,那是 A 的独立放宽,单独立单定,不顺手带进来。

    正文列的两个关联输入按此处理:ExecutionContext 的 origin/channel 标记是另一单的前提(任何按来源分级的策略都要它,但 B 不依赖它 —— B 靠的是「进程内可达 / 客户端不可达」这条结构边界);onFieldsDropped 不跨 RPC/VDE 的既有文档化事实,在 B 的实现里顺带在契约 TSDoc 上说清远程调用方拿到什么(即:拿不到,strict 是进程内语义)。

    路由:归 spec 车道(本车道硬禁区)

    落点 packages/spec/src/contracts/data-engine.ts + packages/objectql,跨 spec 与 engine。spec 半边(在 WriteObservabilityOptions 上声明 strictReadonlyWrites + ERROR_CODE_LEDGER 登记 ERR_READONLY_FIELD_REJECTED)是阻塞前置;声明落地后 objectql 的实施半边可由本车道接。Blocked-by: #4903(PR #5123)仍然有效,先确认它已合入再动工。

    急迫度:低 —— 今天的行为是静默剥离 + onFieldsDropped 可观测(#4903 已修好可发现性),strict 是补一条响亮出路,不是修一个正在漏的洞。spec 车道可排在 #5158 / #5271 / #5239 之后。


    Generated by Claude Code

  3. added
    pm:queueReady for the PM dispatch loop
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Aug 4, 2026
  4. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    Contributor

    维护者裁定(2026-08-05,经 spec 车道 PM session_018fxLGQdatPbBUvCgiVxg6D 誊写):选 B。

    转入队列并即刻派发。


    Generated by Claude Code

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 5, 2026
  6. self-assigned this
    on Aug 5, 2026
  7. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    Contributor

    PM 认领(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05)


    Generated by Claude Code

  8. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    Contributor

    验收通过(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05)—— PR #5610,裁定 B 落地。

    落地暂缓等 #5604(main 全仓红)修复后合 main 重跑 → ready → auto-merge。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions