DAMA 独立回查 dama-recheck-workbench-entity-isolation-20260922 的 §4b/§5 两处待办:
1. POST /api/cma/tenant/switch 审计行原来不可归属:
- user_id=None → 改为注入会话用户(user=Depends(require_auth_401))
- target_type/target_id 从 system_config/None 对齐为 entity/<entity_id>,
与 /auth/switch-entity 的 switch_entity 共用目标维度 ⇒ 按账套可过滤,零 DDL
- action 字面 switch_tenant_state 保留不合并(与会话级 switch_entity 语义不同),
口径登记 docs/audit-and-notification-caliber-20260922.md
2. /api/cma/notifications/logs 增加 policy/note 口径字段,前端发送记录表
empty-text 提示同一口径 —— 避免「B2 上线后 e1/e2 均 0 条」被当成页面故障
(现库 8 行历史记录全为 alert_id IS NULL 的 OKR 复盘提醒,无账套归属)
回归:tests/test_workbench_entity_isolation_20260922.py 22/22;全量 1370 passed;前端 vite build 通过
4.6 KiB
4.6 KiB
口径登记:审计留痕(operation_logs)与通知发送记录(notification_logs)
- 立档: wecom-fullstack,2026-09-22
- 来源: DAMA 独立回查
dama-recheck-workbench-entity-isolation-20260922(2026-09-22 11:07–11:20) §4b(审计字面与库内既有口径不一致 / 无entity_id列 /user_id=None)与 §5(B2 上线后/notifications/logs在 e1/e2 均为 0 条 = 口径副作用)两处待办 - 性质: 口径登记 + 代码收口说明。不含任何数据订正(数据订正另立单 + 审批)
一、operation_logs 审计字面字典(换账套类)
| action 字面 | 写入端点 | 语义 | target_type | target_id |
|---|---|---|---|---|
switch_entity |
post /api/cma/auth/switch-entity(app/api/auth.py) |
改用户自己的会话账套(重签 token、旧 token 下线) | entity |
目标 entity_id |
switch_tenant_state |
post /api/cma/tenant/switch(app/api/tenant.py) |
改平台全局状态记录 system_configs.current_tenant(项目Bot 分发 A2A 任务用;非数据维度) |
entity |
目标 entity_id |
为什么两个字面不合并:两者作用域不同(个人会话 vs 全局单值键),合并后审计上不可分辨
「谁把自己切走了」与「谁改了全平台状态」。DAMA 复核提出「统一为 switch_entity 或登记字典」——
本档取后者(登记不合并),原因是前者会丢语义可分辨性;若后续裁定要求合并,改动面为
app/api/tenant.py 一行字面 + 本表一行(可逆)。
可归属与可过滤(2026-09-22 收口,随本档同一提交落地):
operation_logs无entity_id列(仅user_id / action / target_type / target_id / detail / created_at)。 故「按账套查换账套记录」不靠新列,而靠目标维度:SELECT * FROM operation_logs WHERE target_type='entity' AND target_id=? ORDER BY id DESC;/tenant/switch原写user_id=None(端点无当前用户注入)⇒ 事后无法追操作人。 已改为注入会话用户(user=Depends(require_auth_401)→user_id=user.id), 并把target_type='entity'/target_id=entity_id与switch_entity对齐。detailJSON 仍保留entity_id / entity_name / source / previous(人读明细)。
现网实况(只读核对,2026-09-22 11:15,cma_reader 16/16 PASS):
switch_entity = 49 行、switch_tenant_state = 0 行(本单尚未部署 ⇒ 字面是新引入的,
上线前库里无该字面属正常)。ops 止血那次 POST /tenant/switch(10:36:01,部署码)没有审计行——
部署码该端点无审计,正是本单补齐项。
二、/api/cma/notifications/logs 口径(发送记录页)
- 归属口径:
notification_logs无entity_id列 ⇒ 经父键 join 归属:notification_logs.alert_id → kpi_alerts.id → kpi_alerts.entity_id;按会话账套过滤, 与 batch5 对kpi_data_quality_log的处置同口径(宁少勿错)。 alert_id IS NULL的行:无可归属父键 ⇒ 不返回给任何账套(不跨账套暴露)。 现库 8 行历史记录(2026-09-11/12「OKR 季度复盘提醒」)100% 属此类, 写入方 =backend/scripts/okr_review_reminder.py(复用本表留存审计,alert_id留空)。- 上线后现象(须预期,不是故障):
/notifications/logs在 e1/e2 均返回total=0, 前端发送记录页为空。现役预警推送写入器app/utils/notifier.py必带alert_id, 故此后由预警产生的新记录会正常显示;只有「无父键历史行」永不出现在该页。 - 页面与接口的提示(随本档同一提交落地):
- 接口返回
policy="alert-linked-only"+note(说明「仅显示与预警关联的推送」); - 前端
NotificationManage.vue发送记录表empty-text写明同一口径。
- 接口返回
- 未做(留待 P2 裁定):为无父键通知单列只读视图(需先给
notification_logs补账套维度, 属 DDL/迁移,超出「零迁移 B2」范围)。
三、本档未覆盖(另立单,见对应任务文件)
kpi_alertsid 589/590 跨账套错挂(entity_id=1挂 e2 的BH_ADM_EXPENSE):数据订正须 另立单 + 任总放行(生产写)。kpi_id=1兜底残留清点(9 行、其中 1 行pending)与归属裁定。- 同源全局键继续拆账套:
kpi_alert_higher_better、kpi_visibility(DAMA §7 反向挑错新增漏项)、budget_mode/budget_driver_mode(batch5 §七 已记录未施工)。