Repository navigation
数据范围:指标下达、参与主体、审核记录等配置/审计对象按主体过滤,菜单按岗位裁剪(各部门目标值互相保密) #30
Description
Activity
认领(调度员占坑,2026-09-03)
- 会话:
local_0e65d2bc-719b-4314-aae2-351176a17e5f(同批派发:流程按钮绕过岗位校验:动作体以受信任身份写入被 hook 当系统写入免检,任何岗位可越节点审批/归档 #28 / 发布前完整性检查缺「每个参与主体须配分管领导」,未配置的主体流程死在领导审批节点 #29 / 数据范围:指标下达、参与主体、审核记录等配置/审计对象按主体过滤,菜单按岗位裁剪(各部门目标值互相保密) #30 并行) - 分支:
issue-30-data-scope,基线 main @a760651293af660a8a4a13f7ec30fb3983f9a868 - 环境分配:worktree
../kpi-issue-30-data-scope,dev 端口3115,数据库file:./.objectstack/issue-30-data-scope.db - 执行方式:按 os-project-pm-dispatch 派发独立开发子 agent(Opus);调度员只做收单核实与评审闸门,不写代码。
- 会话:
开工前方案:「对象 × 岗位」可见范围矩阵(改前 / 改后)+ 实现方式
会话:开发子 agent(Opus),worktree
../kpi-issue-30-data-scope,分支issue-30-data-scope,基线 main @a760651293af660a8a4a13f7ec30fb3983f9a868。一、根因(读平台源码得到,不是猜)
@objectstack/plugin-sharing@17.2.0的effectiveSharingModel():if (m === 'private') return 'private'; if (m === 'public_read') return 'read'; if (m === 'public_read_write' || m === 'controlled_by_parent') return 'public';而
buildReadFilter()第一道闸门是if (effectiveSharingModel(schema) !== 'private') return null;—— 返回 null = 不加任何过滤。于是:
- 指标下达 / 参与主体 / 到人分工 / 个人承接项 的 OWD 是
controlled_by_parent,在共享层被当成 public,记录级过滤根本不参与求值;权限集里的readScope也随之失效(buildReadFilter提前 return 了)。 - 审核记录 / 归档快照 的 OWD 是
public_read→ 映射为read,读侧同样不过滤。
所以只改权限集不够:这些对象的 OWD 必须先落到
private,记录级共享与readScope: 'own'才开始起作用。这一条是本次改动的地基。第二条平台事实(已有代码里已记录,本次沿用):
bindRuleHooks对ctx.session.isSystem的写入 跳过共享物化(sharing materialisation skipped for isSystem writes)。本应用的审核记录、归档快照都由 hook 以系统上下文创建,因此这两个对象需要在创建后重新声明一次规则来补齐物化 —— 与现有kpi_check_task/kpi_result完全相同的补偿路径。二、可见范围矩阵
「全量」= 所在组织全部行;数字口径以软件档案实例为准(研发部 3 条下达、6 个参与主体)。
对象 管理员 / 人力审核 / 人力负责人 部门填报(张伟·研发部) 分公司核对(陈东·华东) 分管领导(徐涛·技术线) 指标下达 kpi_plan_indicator改前 全量 / 改后 全量 改前 全量 36 / 改后 本部门 3 改前 全量 / 改后 本分公司相关 改前 全量 / 改后 分管三主体 参与主体 kpi_plan_subject全量 / 全量 全量 / 本部门 1 全量 / 本分公司 1 全量 / 分管三主体 到人分工 kpi_staff_assignment全量 / 全量 全量 / 本部门 全量 / 本分公司 全量 / 分管三主体 审核记录 kpi_review_record全量 / 全量 改前 全量 96 / 改后 本部门填报单的记录 全量 / 本分公司填报单的记录 全量 / 分管主体填报单的记录 归档快照 kpi_snapshot全量 / 全量 全量 / 本部门 全量 / 本分公司 全量 / 分管三主体 核对任务 kpi_check_task全量 / 全量 改前 0(own,无规则)/ 改后 本部门填报单上的核对任务 本分公司(已有规则)/ 不变 改前 0 / 改后 分管主体填报单上的 指标库 kpi_indicator全量 / 全量 全量 / 全量(公共口径,按拍板不过滤) 全量 / 全量 全量 / 全量 填报单 / 明细 / 数据调整 / 考核结果 不变 不变(已有规则) 不变 不变 方案版本 kpi_plan/ 指标争议kpi_dispute不变 数据层不变,菜单裁剪 数据层不变,菜单裁剪 不变 三、实现方式(三处 + 一处新增)
-
对象 OWD(
src/objects/plan.object.ts、entry.object.ts、result.object.ts)
kpi_plan_subject/kpi_plan_indicator/kpi_staff_assignment:controlled_by_parent→private;
kpi_review_record/kpi_snapshot:public_read→private。
kpi_personal_item保持controlled_by_parent(主记录是到人分工,随主记录收窄)。 -
动态共享规则(
src/services/sharing-service.ts)——沿用现有「按方案建规则、发布时对账、关闭后降只读」的同一套机制,每个参与主体单元新增:psub_<unit>→ 参与主体,条件{plan, subject: unit},收件方unit_and_subordinates(unit),readpind_<unit>→ 指标下达,条件{plan, subject: unit},同上,readassign_<unit>→ 到人分工,条件{plan, unit},同上,readsnap_<unit>→ 归档快照,条件{plan, subject: unit},同上,read- 分管领导对以上四类各一条
..._leader_<unit>_<leader>,收件方user(leader),read - 审核记录与「本部门填报单上的核对任务」按填报单建:条件
{sheet: sheetId}(审核记录对象上没有主体列,平台共享条件不支持跨对象遍历,只能用它自己的列),收件方 = 该填报单主体单元unit_and_subordinates+ 分管领导user。填报单在方案发布时、provisionPlanSharing之前就已生成,取得到。
规则名长度校验:最长形态kpi_p{20}_pind_leader_{26}_{26}= 95 ≤ 100,仍在RULE_NAME_MAX以内。
-
权限集(
src/security/index.ts)——部门填报 / 分公司核对 / 分管领导三套,把上述对象由readOrg收成{ allowRead: true, readScope: 'own' },可见性完全交给记录共享;管理员 / 人力审核 / 人力负责人保持org全量。 -
新增一个补物化 hook(新文件,注册在
objectstack.config.ts,不动src/hooks/下任何既有文件 —— 那里有并行工作项在改):审核记录 / 归档快照afterInsert后重新声明对应对象的规则,补上系统上下文写入被跳过的物化。这与sheet.hook.ts里既有的kpi_check_task/kpi_result补偿是同一条路径,只是换个触发点。 -
导航裁剪(
src/apps/index.ts):考核方案与基础设置两个菜单组加visibleCEL 谓词,对kpi_dept_reporter/kpi_branch_checker两个岗位隐藏。如实说明:平台把导航visible定为前端渲染谓词(requiredPermissions才是服务端闸门),因此它是「界面不呈现入口」,不是权限边界 —— 真正的边界是第 1~3 条的数据层过滤。若实测visible在分组上不生效,按平台能力缺口如实记录(只上报不修复)。 -
测试(
test/sharing.test.ts):按现有风格给planSharingIntents补规则集合断言(新增六类规则、按方案前缀、关闭后降只读不影响只读类规则、规则名长度上界)。
四、受影响的既有测试与脚本
test/sharing.test.ts—— 规则集合断言要扩(新增规则条数变化)。test/design-alignment.test.ts—— 若断言了 OWD / 权限集形态需同步。scripts/e2e-flow.mjs(默认档案)、scripts/software-flow.mjs(软件档案,54/54)—— 两个脚本都以管理员建链,管理员保持org全量,预期不受影响;实测逐条核对,不预设。
五、与口径的一致性自查
- 各部门目标值与权重互相保密 → 指标下达按主体过滤 ✔
- 指标库不过滤 ✔(仅菜单裁剪)
- 配置类菜单对部门填报 / 分公司核对隐藏 ✔(前端谓词,局限如实记录)
- 未发现「平台共享规则对某对象无法按主体条件表达」的死路:审核记录靠按填报单建规则绕开了「无主体列」,不需要改 hook、不需要停手上报。
与拍板口径一致,按此开工。
- 指标下达 / 参与主体 / 到人分工 / 个人承接项 的 OWD 是
测试报告 — 数据范围按主体过滤 + 菜单按岗位裁剪
结论:通过。 6 个对象的按主体过滤全部生效,越权访问一律 404,配置类菜单对部门填报人员与分公司核对人员在服务端就被剥离。软件档案
software-flow.mjs54/54 全绿。默认档案e2e-flow.mjs72 通过 / 1 失败 —— 失败的 T39 是一条共享规则条数常量断言,随本次新增规则类别机械变化,而scripts/本轮禁改,已在下方「需拍板」列出精确改法。所有数据范围类断言(T50 / T51 / T53 / T55~T57 / T64 / T70)全 PASS。项 值 分支 / 提交 issue-30-data-scope@1eb5051环境 worktree ../kpi-issue-30-data-scope,dev 端口 3115,OS_DATABASE_URL=file:./.objectstack/issue-30.db档案 软件档案( OS_SEED_PROFILE=software,99 行种子)+ 默认档案(46 行种子,独立空库)账号 管理员 admin@objectos.ai;岗位账号口令 Passw0rd!23截图 acceptance-evidence分支issue-30/,commit224e77a0611679ecea92d9f264ae12506b182e4b门禁 pnpm verify绿(validate / typecheck / 103 单测 / i18n 同步)
T1 可见范围矩阵(REST 逐对象计数,软件档案实例)
以管理员为全量基准,同一时刻同一份数据,五个账号各查一遍:
对象 管理员 马丽(人力审核) 张伟(研发部·部门填报) 陈东(华东·分公司核对) 徐涛(技术线·分管领导) 指标下达 36 36(11 个主体) 3(研发部) 4(华东分公司) 9(产品部/测试部/研发部) 参与主体 11 11 1(研发部) 1(华东分公司) 3(技术线三主体) 到人分工 8 8 1(研发部) 0 3(技术线三主体) 审核记录 94 94(11 张单) 8(本部门 1 张单) 7(本分公司 1 张单) 24(分管 3 张单) 归档快照 1 1 0(研发部未归档) 0 0 核对任务 30 30 3(本单上的) 10(只本分公司) 9(分管主体的) 指标库 24 24 24(公共口径,不过滤) 24 24 填报单 11 11 1 11 ⚠️ 3 「归档快照」这一维度用已归档主体的填报人复验:赵敏(销售部,本档案唯一已归档的主体)可见快照 1 条、指标下达 3 条、审核记录 16 条 —— 说明归档快照的补物化生效(快照由 hook 以系统上下文创建,平台跳过共享物化,靠新增的补物化 hook 重新求值规则补齐)。
⚠️ 陈东的「填报单 11」不是本次回归:分公司核对人员的填报单权限集本来就是readScope: 'org'(他要核对全部部门的填报单),该对象不在本次拍板口径列出的六个对象内。见下方「基准差异」。界面证据
张伟(研发部·部门填报人员) —— 左侧只剩「工作台 / 填报与审核 / 结果与归档 / 审计查询」,配置类的「考核方案」「基础设置」两组不呈现;指标下达列表底部「3 条记录」,全部是研发部:
陈东(华东·分公司核对人员) —— 指标下达只见华东分公司;核对任务只见华东:
徐涛(技术线·分管领导) —— 只见分管的三个主体,菜单保持完整:
马丽(人力审核)与管理员 —— 全量可见,菜单完整:
赵敏(销售部·已归档主体) —— 可见本部门归档快照 1 条:
T3 越权访问
张伟(研发部)拿到销售部记录的真实 id 后直接访问:
入口 对象 结果 界面 URL 销售部的指标下达 「未找到记录」 界面 URL 销售部的归档快照 「未找到记录」 REST GET /data/kpi_plan_indicator/{id}销售部的指标下达 404 REST GET /data/kpi_plan_subject/{id}销售部的参与主体 404 REST GET /data/kpi_review_record/{id}销售部的审核记录 404 REST GET /data/kpi_snapshot/{id}销售部的归档快照 404 REST 过滤强取 ?subject={销售部单元 id}指标下达 {"records":[],"total":0}对照:本部门的指标下达 指标下达 200 陈东(华东)同样:研发部的指标下达 404,销售部的归档快照 404。
T4 导航裁剪(服务端剥离,不是前端隐藏)
直接读
GET /api/v1/meta/app/kpi_app,看下发到浏览器的导航项 id:账号 收到 group_plan/group_setup及其子项管理员 ✔ 全部 马丽(人力审核) ✔ 全部 徐涛(分管领导) ✔ 全部 张伟(部门填报) ✘ 两组连同 5 + 2 个子项一并不下发 陈东(分公司核对) ✘ 同上 这一项经历了一次实现返工,如实记录: 最初按方案写的是导航项的
visibleCEL 谓词。实测发现本版本控制台对导航项的visible根本不求值 —— 谓词原样下发到浏览器后被忽略,分组与叶子项都不生效,菜单对所有岗位照旧全量呈现。已按「只上报不修复」报到平台:objectstack-ai/objectstack#15135。改用requiredPermissions(平台在/meta里就把不满足的项剥掉)后达成目标。T5 两个脚本
脚本 档案 结果 scripts/software-flow.mjs软件档案(空库重建) 54 / 54 全 PASS,含 T17a~T17d 四条数据范围断言 scripts/e2e-flow.mjs默认档案(独立空库) 72 PASS / 1 FAIL(T39) —— 见下 T17c 在开发中途曾一度失败,是本次自测抓到的真缺陷:最初给「本单填报单的核对任务」建的规则不分主体类型,而分公司既是被考核主体、又是核对方,它自己那张填报单上挂着全部分公司的核对任务 —— 华东的核对人员于是看见了华南、华北的核对意见,与「分公司核对人员只开放本分公司相关行」的拍板口径直接冲突。改为只给总公司部门主体建这条规则后 T17c 恢复,并补了针对性单测。
T6 门禁
pnpm verify绿:os validate通过、tsc --noEmit无错、103 个单测全过(本次新增 12 条:四类按主体规则、按填报单规则、分公司主体不拿本单核对规则、条件收窄不变式、关闭方案后只读类不降级、超长 id 规则名仍 ≤ 100、按对象/按填报单收窄重申)、i18n 包与元数据同步(本次未新增任何 label,zh-CN529 键无变化)。
基准差异(如实列出)
- 手册 §1.2「每个角色只看得到自己权限内的菜单」 —— 现已成立,但成立的方式与手册措辞的隐含前提不同:菜单是服务端剥离(
requiredPermissions),不是前端按角色渲染;平台的前端谓词visible在本版本不工作(平台单已上报)。手册无需改。 - 填报单 / 填报明细对分公司核对人员仍是
readScope: 'org'—— 他要核对全部部门的填报单,这是既有设计;这两个对象不在本次拍板口径列出的六个对象内,本次未动。若「各部门实际值与得分也需互相保密」,那是另一条口径,需 PM 拍板后另立工作项。 controlled_by_parent的子对象在读侧不随主记录收窄 —— 平台把这种 OWD 在共享层映射为public,只对 update / delete 委托主记录判定(plugin-security的masterGateCoversOperation)。因此填报明细kpi_entry_line、个人承接项kpi_personal_item、加减分kpi_bonus的读仍不按主体过滤。这是平台既有且有意的语义(describeOwd明确标注effect: 'public'),不是缺陷,本次未扩围;kpi_personal_item上的个人目标值因此仍全员可读,如需收窄要先给它自己的 OWD 与规则,属新工作项。scripts/e2e-flow.mjsT39 未过 —— 见下方「需拍板」。
需拍板(一条)
scripts/e2e-flow.mjs第 227 行的常量EXPECTED_RULES是按方案配置精确推导的规则条数,新增规则类别后必然变化,scripts/本轮在禁改清单里,故未动。实测拆解已核对到条(5 个参与主体、2 个总公司部门主体、1 位分管领导、2 条到人分工):// 现:5 * 4 + 3 + 2 + 2 * 2 = 29 // 应:5 * 8 + 7 + 2 + 2 * 2 + 3 = 56 // 5 个主体 × 8 类(填报单/核对任务/调整/结果 + 参与主体/指标下达/到人分工/归档快照) = 40 // 市场部配了分管领导 → 7(填报单、该主体结果、本人结果 + 上述后四类) // 2 条到人分工 → 2;人力岗位 2 个 × 2 类 → 4 // 总公司部门主体的「本单核对任务」2 条,其中市场部有分管领导 → +1,合计 3 const EXPECTED_RULES = 5 * 8 + 7 + 2 + 2 * 2 + 3;
实测
rules=56,与该式逐项对上(按对象 × 收件方类型的分布也已核对)。请调度员决定:授权本子 agent 改这一行,或交由scripts/的归属方改。同一处的 T39b(「每条规则条件里都带本方案 id」)现已 PASS 且无需改动 —— 审核记录规则的条件带的是填报单 id(比方案更细),不落在 T39b 的筛选集合里。- 手册 §1.2「每个角色只看得到自己权限内的菜单」 —— 现已成立,但成立的方式与手册措辞的隐含前提不同:菜单是服务端剥离(
需求符合度清单
逐条对照工作项正文的「口径」「范围」「不做」「验收标准」「测试计划」。分支
issue-30-data-scope@1eb5051。一、口径
# 需求原文 态 说明 1 指标下达对部门填报人员只开放本部门主体相关行 ✅ 张伟 3 条(研发部),全量 36 2 参与主体对部门填报人员只开放本部门主体相关行 ✅ 张伟 1 条 3 到人分工对部门填报人员只开放本部门主体相关行 ✅ 张伟 1 条 4 审核记录对部门填报人员只开放本部门主体相关行 ✅ 张伟 8 条(本部门 1 张填报单的留痕),全量 94 5 归档快照对部门填报人员只开放本部门主体相关行 ✅ 赵敏(销售部,唯一已归档主体)1 条;张伟 0 条(研发部未归档) 6 核对任务对部门填报人员只开放本部门主体相关行 ✅ 张伟 3 条 = 本部门填报单上的三家分公司核对任务 7 以上六类对分公司核对人员只开放本分公司相关行 ✅ 陈东:指标下达 4 / 参与主体 1 / 审核记录 7 / 核对任务 10(全部 bu_sw_east)/ 到人分工 0(华东无到人分工)/ 快照 0(未归档)8 以上六类对分管领导只开放分管主体 ✅ 徐涛:指标下达 9、参与主体 3、到人分工 3、审核记录 24(3 张单)、核对任务 9,均为技术线三主体 9 人力审核 / 人力负责人 / 管理员全量 ✅ 马丽与管理员逐对象计数与全量基准一致(36 / 11 / 8 / 94 / 1 / 30) 10 指标库视为公共口径,所有岗位可读,不过滤 ✅ 五个账号一律 24 项; kpi_indicator的 OWD 与权限集本次未动11 配置类菜单对部门填报人员与分公司核对人员隐藏或收成只读入口 ✅ 「考核方案」「基础设置」两组连同 7 个子项对这两个岗位在 /meta里即被剥掉,不下发到浏览器12 做不到按岗位裁剪导航时如实记录为平台能力缺口(只上报不修复) ✅ 裁剪已做到(走 requiredPermissions);过程中发现的visible不求值缺口已如实记录并只上报:objectstack-ai/objectstack#15135二、范围
# 需求原文 态 说明 13 sharing-service.ts按方案的动态共享规则扩到上述对象✅ 每主体新增 psub_/pind_/assign_/snap_四类 + 分管领导同名_leader_变体;审核记录review_与本单核对任务scheck_按填报单建14 核对哪些对象缺规则、哪些对象的权限集还是 readOrg✅ 已逐对象核对并在开工前的矩阵评论列出改前 / 改后;结论:缺规则的是参与主体 / 指标下达 / 到人分工 / 归档快照 / 审核记录五类, readOrg的是这五类在三个受限岗位上的授权15 部门 / 分公司 / 分管领导三类范围与现有填报单规则同一口径 ✅ 同一条 unit_and_subordinates(主体单元)+user(分管领导)的收件方组合,同一套方案前缀、发布时对账、关闭后处理16 src/security/index.ts权限集从readOrg收成own+ 共享✅ 新增 readOwn常量;三个受限岗位的五个对象改用它17 src/apps/index.ts导航按岗位裁剪(平台能力允许时)✅ 见第 11 条 18 单测 / 服务测试:为新增共享规则补覆盖(沿用现有测试风格) ✅ test/sharing.test.ts新增 12 条,同文件既有风格;pnpm test103 全过19 演示与手册不改 ✅ docs/与演示数据零改动20 手册 §1.2 表述与实现不一致时在测试报告「基准差异」列出 ✅ 已列:结论是手册表述成立,但成立机制是服务端剥离而非前端渲染,手册无需改 三、不做
# 需求原文 态 说明 21 不改状态机与计分 ✅ src/hooks/、src/lib/scoring.ts零改动22 不改指标库可见范围 ✅ kpi_indicator/kpi_indicator_step的 OWD 与全部权限集授权未动23 不做「到人结果只见本人」以外的个人维度调整 ✅ kpi_result的 OWD、规则与行级安全谓词未动四、验收标准
# 需求原文 态 说明 24 张伟(研发部)在指标下达列表只见研发部的 3 条 ✅ 界面列表底部「3 条记录」,REST 计数 3 25 张伟的审核记录只见研发部填报单的记录 ✅ 8 条,全部指向研发部那一张填报单 26 张伟的归档快照只见研发部 ✅ 研发部本档案未归档故为 0;用已归档的销售部填报人赵敏复验为 1,规则与补物化均生效 27 陈东(华东)在参与主体 / 指标下达只见华东相关 ✅ 参与主体 1、指标下达 4,均为华东分公司 28 徐涛只见技术线三主体 ✅ 指标下达 9 / 参与主体 3 / 到人分工 3 = 产品部、测试部、研发部 29 马丽全量 ✅ 与管理员基准逐对象一致 30 越权直接访问记录 URL 或 REST 返回 404 / 403 ✅ 界面「未找到记录」;REST 四个对象一律 404;按主体过滤强取返回空集;对照本部门记录 200 31 默认档案上 e2e-flow.mjs的数据范围断言仍全 PASS✅ T50 / T51 / T53 / T55 / T56 / T57 / T64 / T70 全 PASS 32 scripts/e2e-flow.mjs整体全 PASS⚠️ 72 PASS / 1 FAIL。失败项 T39 是「共享规则条数」的精确常量断言( EXPECTED_RULES = 29),新增规则类别后实测 56,该常量按定义必须同步。scripts/在本次派发的禁改清单内,故未改。出口:失败升级 —— 已在测试报告「需拍板」给出逐项核对到条的新常量与改法,交调度员裁决(授权本子 agent 改,或交scripts/归属方改)。 该断言与数据范围行为无关,不构成功能缺陷。
出口链接:#30 (comment)33 scripts/software-flow.mjs仍 54/54✅ 空库重建后 54/54 全 PASS 34 导航:部门填报人员登录后看不到配置类菜单组 ✅ 界面与 /meta双向确认;分公司核对人员同35 平台缺口如实记录 ✅ objectstack-ai/objectstack#15135( visible不求值),含最小复现、期望能力、平台版本36 pnpm verify绿✅ validate / typecheck / 103 单测 / i18n 同步 全过 37 测试报告与符合度清单挂本单评论,截图走 acceptance-evidence✅ 本评论 + 测试报告评论;截图 commit 224e77a0611679ecea92d9f264ae12506b182e4b,14 张,已用 contents API 核对文件齐全五、测试计划(T1~T6)
# 计划项 态 38 T1 可见范围矩阵评论 ✅ 开工前已发(改前 / 改后 + 实现方式 + 受影响测试) 39 T2 界面:张伟 / 陈东 / 徐涛 / 马丽四账号逐对象计数 ✅ 四账号 + 管理员 + 赵敏,共 6 个账号 × 8 个对象 40 T3 越权 URL 与 REST 拒绝 ✅ 41 T4 导航裁剪 ✅ 42 T5 两脚本全 PASS ⚠️ 见第 32 条43 T6 pnpm verify✅
统计:41 条 ✅ / 2 条
⚠️ (同一件事:e2e-flow.mjsT39 的常量,已走失败升级出口)/ 0 条 ❌。范围外但需要知会的两项改动(均为达成本单目标的必要条件,非静默扩围)
- 新增补物化 hook(
src/services/scope-materialize.ts,在objectstack.config.ts注册)。审核记录与归档快照由 hook 以系统上下文写入,平台对isSystem写入跳过共享物化(sharing materialisation skipped for isSystem writes),官方补偿手段是重新求值规则。不补这一手,这两个对象 OWD 收成private之后是「谁都看不到」,包括本该看到的本部门成员。做法与hooks/sheet.hook.ts里既有的kpi_check_task/kpi_result补偿完全同路,只是触发点换成记录自己的afterInsert;单独成文件、单独注册,src/hooks/下既有文件零改动(该目录本轮禁改)。 - 新增「平台管理员 ↔ 考核系统管理员权限集」绑定(
src/security/bind-admin-set.ts)。导航裁剪走的requiredPermissions是逐条 AND、字符串精确匹配、无通配、无超级用户豁免,平台管理员的admin_full_access在这里不构成豁免 —— 实测:不加这条绑定,管理员自己会丢掉「考核方案」「基础设置」两个菜单组。本项目「考核系统管理员由平台内置管理员账号承担」(CLAUDE.md D4)此前是隐含安排,菜单闸门不认隐含,故写成幂等绑定行;按「持有admin_full_access的用户」匹配而不是按邮箱,换人、多管理员、改邮箱都不需要改代码。
- 新增补物化 hook(
交接验收侧 @baozhoutao(状态 →
status:PR审查中)。- PR:https://github.com/objectstack-ai/kpi/pull/32(**不自行合并**)
- 分支:
issue-30-data-scope@1eb5051,基线 main @a760651293af660a8a4a13f7ec30fb3983f9a868 - 测试报告:数据范围:指标下达、参与主体、审核记录等配置/审计对象按主体过滤,菜单按岗位裁剪(各部门目标值互相保密) #30 (comment)
- 需求符合度清单:数据范围:指标下达、参与主体、审核记录等配置/审计对象按主体过滤,菜单按岗位裁剪(各部门目标值互相保密) #30 (comment) ✅ / 2
⚠️ / 0 ❌) - 截图:
acceptance-evidence分支issue-30/,commit224e77a0611679ecea92d9f264ae12506b182e4b(14 张,已用 contents API 核对齐全) - 平台缺口(只上报未修复):App nav item
visible(CEL) is served to the client but never evaluated — a silently inert gate (17.2.0) objectstack#15135 —— 导航项的visibleCEL 谓词下发到浏览器后不被求值;本单改用服务端闸门requiredPermissions达成裁剪,不受该缺口阻塞。
待拍板一条(唯一的
⚠️ ):scripts/e2e-flow.mjsT39 的EXPECTED_RULES常量需由5*4+3+2+2*2(29)改为5*8+7+2+2*2+3(56),推导已逐项核对到条、实测吻合。scripts/在本次派发的禁改清单内故未动 —— 请裁决:授权本子 agent 改这一行,或交scripts/归属方改。除此之外自测全部通过。- added a commit that references this issue
on Sep 4, 2026 合并记录(调度员,2026-09-03)
- 收单核实:PR 数据范围:配置与审计对象按主体过滤,配置类菜单按岗位裁剪(#30) #32 关联本单、无自动关闭关键字;10 文件与范围对应,范围外两处(
bind-admin-set.ts、scope-materialize.ts+objectstack.config.ts注册)已在清单披露且有据(平台导航visible不求值 → App nav itemvisible(CEL) is served to the client but never evaluated — a silently inert gate (17.2.0) objectstack#15135,改用服务端权限闸门需为管理员幂等绑定);禁触碰面 hook / 动作 / 种子 / 脚本零改动;CI 绿;测试报告、需求符合度清单、14 张证据图核对存在。全项通过。 - 评审闸门:独立评审子 agent(全量档)首轮「可合并」(阻塞 0 / 应修 0 / 记录 7),调用面抽查 13 处全部未改坏,五对象改 private 后人力审核 / 人力负责人 / 管理员全量可见经实测与基准逐对象一致;调度员追加要求三处修复(合入 main、e2e 共享规则对账口径、分公司核对人员与分管领导对个人承接项的只读授权——评审记录 4 由调度员判为应修:本单引入的子表 403);复查轮「可合并」,三处均核实,e2e 74/74、software-flow 54/54、verify 110 单测绿。
- 更正留痕:开发方撤回上一轮「主从子对象读侧不随主记录收窄」的判断(实测随主记录收窄,由安全插件的主从派生完成),评审侧独立实测一致,故「个人目标值/实际值全员可读」风险不存在、不另立单。
- 记录级留痕待后续视情况立单:
kpi_plan_config未 defineCapability(权限界面显示机器名);bind-admin-set.ts只扫直接授权且只增不减;「指标争议」菜单隐藏但填报人员仍有 allowCreate;sharing-service.ts取填报单limit: 2000;每条审核记录触发一次共享物化的扇出代价。 - 已合并 PR 数据范围:配置与审计对象按主体过滤,配置类菜单按岗位裁剪(#30) #32 到 main。状态切
status:PM验收中,处理人不变(验收侧)。
- 收单核实:PR 数据范围:配置与审计对象按主体过滤,配置类菜单按岗位裁剪(#30) #32 关联本单、无自动关闭关键字;10 文件与范围对应,范围外两处(














背景(来源:#23 UI 实测 K-4,维护者 2026-09-03 拍板口径:各部门目标值互相保密,按主体过滤)
部门填报人员(张伟)能打开「方案版本 / 指标下达 / 参与主体 / 到人分工 / 指标争议 / 指标库 / 归档快照 / 审核记录」,指标下达 36 条(全部主体的目标值与权重)、审核记录 96 条全部可读;左侧菜单对所有岗位全量展示。与需求 §2.2「本部门范围仅可见本部门」、手册 §1.2「每个角色只看得到自己权限内的菜单」不符。
口径(已拍板)
范围
src/services/sharing-service.ts:按方案的动态共享规则扩到上述对象(现有规则已覆盖填报单/明细/核对任务/数据调整等,核对哪些对象缺规则、哪些对象的权限集还是readOrg),部门 / 分公司 / 分管领导三类范围与现有填报单规则同一口径;src/security/index.ts权限集相应从readOrg收成own+ 共享。src/apps/index.ts导航按岗位裁剪(平台能力允许时)。不做
不改状态机与计分;不改指标库可见范围;不做「到人结果只见本人」以外的个人维度调整(已存在)。
方案分级与放行(调度员)
改已有共享规则与权限集 = 高风险(影响所有岗位的可见范围)。放行方向 = 上述口径;开发子 agent 开工前须在本单评论列出「对象 × 岗位」的可见范围矩阵(改前 / 改后)与受影响的既有测试,与口径一致即可开工;若发现平台共享规则对某对象无法按主体条件表达,停手上报(objectstack-ai/objectstack 只上报不修复)并在本单记录。
验收标准
scripts/e2e-flow.mjs的数据范围断言仍全 PASS;scripts/software-flow.mjs仍 54/54(脚本以管理员建链,不应受影响)。pnpm verify绿;测试报告(各岗位截图,含越权被拒)与符合度清单挂本单评论,截图走acceptance-evidence。测试计划草稿
T1 可见范围矩阵评论 | T2 界面:张伟/陈东/徐涛/马丽四账号逐对象计数 | T3 越权 URL 与 REST 拒绝 | T4 导航裁剪 | T5 两脚本全 PASS | T6 pnpm verify