发现于:cloud 侧把 framework pin 从 ad5fe25 前移到 462b713(cloud#1010)后跑全量测试时,日志里出现的 WARN。
核实基线:objectstack @ 462b713,cloud @ e14553d
未认领 —— 只是记录,谁接手谁 assign。
症状
ee-group-showcase / security-enterprise 的测试里,每次 permission-set backfill 都打出这条:
WARN [security] permission-set backfill into metadata failed (ADR-0094 D4)
{"name":"d8_qc_user","error":"[invalid_metadata] permission/d8_qc_user failed spec
validation: <root>: Unrecognized key(s) on this permission set: `active`.
Until #4001 these were dropped silently — the set still parsed, so the author
believed a capability boundary was declared that the runtime never saw."}
测试是绿的。 失败在 permission-set-projection.ts:770-773 被 catch 成一条 logger.warn,backfilledIntoMetadata 不加一,然后继续。所以没有任何 gate 会因此变红。
因果链
sys_permission_set 有一个 active 存储列 —— 是 framework 自己声明的,sys-permission-set.object.ts:33 把它放进 highlightFields,还有两个动作靠 bodyExtra: { active: true } / { active: false } 来启停一个 set。它是完全正当的运行时状态。
- ADR-0094 D4 的 backfill 走
permissionSetBodyFromRow(row),把数据库行转成 metadata body —— active 跟着进去了。
#4001 把 permission-set 的 spec 形状封成严格键。active 从来不是 spec 上的键,此前被静默 strip,所以第 2 步一直"能用"。
- 严格化之后,
saveMetaItem 对每一个没有 declared body 的 permission set 抛 invalid_metadata,backfill 全线失效。
不是 showcase 数据特有的问题:任何走这条路径的 set 都会命中,因为 active 来自表结构,不是作者写的。
为什么值得单独立一条
这正是 #4001 报错文案自己描述的那类事故,只是发生在 framework 内部而非授权侧:一个存储列被当成 spec 键送去校验,严格化之后整条投影路径静默停摆。catch + warn 的处理让它没有任何自动信号 —— 我是在读一次无关的 bump 日志时偶然看见的。
顺带一提,cloud 那边新加的 audit-spec-changes.mjs(cloud#995)也抓不到它:审计只扫 spec-changes.json 登记过的 surface,而 permission-set 的严格化没有对应条目。
可能的修法(未验证,留给接手的人判断)
permissionSetBodyFromRow() 里显式挑出 spec 认的键,而不是把整行带过去 —— 存储列(active、时间戳、managed_by 等)本来就不该进 metadata body;
- 或者反过来,如果
active 确实应当是 permission set 的声明语义(而不只是行状态),那就该在 spec 上正式加回来,而不是靠 strip 苟活。
先判断哪一边才是它真正的归属,再动手 —— 这个键同时被表列和两个动作使用,不能只看 backfill 这一处。
复现
# cloud @ e14553d(pin 已在 462b713)
pnpm turbo run test --filter @objectstack/ee-group-showcase
# 测试通过;在输出里搜 "backfill into metadata failed"
发现于:cloud 侧把 framework pin 从
ad5fe25前移到462b713(cloud#1010)后跑全量测试时,日志里出现的 WARN。核实基线:
objectstack@462b713,cloud@e14553d未认领 —— 只是记录,谁接手谁 assign。
症状
ee-group-showcase/security-enterprise的测试里,每次 permission-set backfill 都打出这条:测试是绿的。 失败在
permission-set-projection.ts:770-773被catch成一条logger.warn,backfilledIntoMetadata不加一,然后继续。所以没有任何 gate 会因此变红。因果链
sys_permission_set有一个active存储列 —— 是 framework 自己声明的,sys-permission-set.object.ts:33把它放进highlightFields,还有两个动作靠bodyExtra: { active: true }/{ active: false }来启停一个 set。它是完全正当的运行时状态。permissionSetBodyFromRow(row),把数据库行转成 metadata body ——active跟着进去了。#4001把 permission-set 的 spec 形状封成严格键。active从来不是 spec 上的键,此前被静默 strip,所以第 2 步一直"能用"。saveMetaItem对每一个没有 declared body 的 permission set 抛invalid_metadata,backfill 全线失效。不是 showcase 数据特有的问题:任何走这条路径的 set 都会命中,因为
active来自表结构,不是作者写的。为什么值得单独立一条
这正是
#4001报错文案自己描述的那类事故,只是发生在 framework 内部而非授权侧:一个存储列被当成 spec 键送去校验,严格化之后整条投影路径静默停摆。catch+warn的处理让它没有任何自动信号 —— 我是在读一次无关的 bump 日志时偶然看见的。顺带一提,cloud 那边新加的
audit-spec-changes.mjs(cloud#995)也抓不到它:审计只扫spec-changes.json登记过的 surface,而 permission-set 的严格化没有对应条目。可能的修法(未验证,留给接手的人判断)
permissionSetBodyFromRow()里显式挑出 spec 认的键,而不是把整行带过去 —— 存储列(active、时间戳、managed_by等)本来就不该进 metadata body;active确实应当是 permission set 的声明语义(而不只是行状态),那就该在 spec 上正式加回来,而不是靠 strip 苟活。先判断哪一边才是它真正的归属,再动手 —— 这个键同时被表列和两个动作使用,不能只看 backfill 这一处。
复现