test(spec): 把「有单条写就必须有批量」做成全仓棘轮,防 #3745 复发 (#3026) - #3755
Merged
os-zhuang merged 1 commit intoJul 28, 2026
Conversation
…across every object (#3026) #3745 fixed eight objects that 405'd `/batch` and the `*Many` routes while exposing the same write verbs one record at a time. The bug was not a wrong judgement — it was an audit whose SCOPE was a package name (`platform-objects`) while the gap lived in three packages nobody thought to open. This replaces that manual sweep with a scan of every `*.object.ts` under `packages/`, so a new declaration anywhere is covered by construction. Three invariants, plus a floor on the scan size so an empty sweep cannot pass vacuously: - a whitelist granting `create`/`update`/`delete` must also grant `bulk`, unless registered in `SINGLE_RECORD_WRITE_ONLY` with a reason (empty today); - a whitelist may only author the six primitives — since the #3543 shrink a legacy verb is stripped at parse, so declaring one is silently dead metadata; - the exemption list may not hold stale entries. Scanning source rather than importing the packages keeps the check next to the derivation table without inverting the spec → * dependency direction, the same technique as `system/constants/platform-object-names.test.ts`. Verified as real evidence, not a green rubber stamp: removing `'bulk'` from `sys_permission_set` turns the ratchet red with the offending object, its whitelist and its file path in the failure message. `@objectstack/spec` 259 files / 6721 tests pass with it in place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CkdX2VCuKfcsFBbvtATe7V
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
July 28, 2026 02:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
#3745 修掉了 8 个对象「单条写全开、批量路由 405」的缺口。根因不是判断错,而是审计范围:#3391 P1 把 bulk 门禁改成
bulk ∧ derived(child)后,配套的「给显式白名单补bulk原语」被写成了「platform-objects包审计」,而缺口在plugin-security/plugin-approvals/metadata-core—— 三个没人想到要打开的包。同类问题会再犯:今天全仓 58 处
apiMethods声明散在多个包里,靠人再扫一遍不可靠。本 PR 把这次的人工排查换成 CI 每次都跑的扫描。改动
新增
packages/spec/src/data/api-methods-batch-conformance.test.ts—— 扫描packages/**下每一个*.object.ts,提取apiMethods数组字面量,断言三条不变量:create/update/delete任一,就必须同时授予bulk;否则必须登记进SINGLE_RECORD_WRITE_ONLY并写明理由(今天为空:全仓要么授予了bulk,要么根本不授予写)。外加一条扫描量下限断言(
> 40):扫不到文件的实现会让上面三条全部真空通过 —— 那正是本文件要防的失败模式。为什么扫源码而不是 import
跟
system/constants/platform-object-names.test.ts同一套技术:import 全部对象包会反转 spec → * 的依赖方向,而扫源码能把检查放在派生表旁边,且新包新对象自动被覆盖(这次缺口的形状正是"新包没人扫")。防假绿
不是绿橡皮图章 —— 把
sys_permission_set的'bulk'拿掉重跑,棘轮如实变红,失败信息直接给出对象名、白名单内容和文件路径:随后已还原。
验证
@objectstack/spec259 files / 6721 tests 全过(含新增 4 条)changeset:空 changeset(test-only,不发布任何包)。
关联
bulk原语 (#3026) #3745(本棘轮要防复发的那个缺口)、跟踪:UI 操作按钮与 apiMethods 白名单一致性契约落地(#3026 设计定稿) #3391 P1(bulk 门禁语义)、P2:ApiMethod 枚举收缩至 6 原语(breaking,独立版本) #3543(枚举收缩)Generated by Claude Code