wecom-fullstack
b8493f8d04
feat(db): 新表授权面收敛机制落地(白名单驱动 · 增量锚定 · fail-closed · 只增不减)
依据:A 侧(wecom-yanxue)裁定 编号 2「准予但需调整」+ R1(裁定件
yanxue-20260928-newtable-grant-surface-impl-plan-ruling.md,md5 272d1a8b4db0db0e9f35f5e62695ae50)
三条开口 (a) 空锚=合法零集 / (b) --anchor-file 载体等价 / (c) drill WARN 不阻断(两条独立分支)
改动面(3 件,全部开发工作树):
- 新增 backend/scripts/grant_surface_sync.py:项目侧原型逐字复制 + Δ1/Δ2/Δ3/Δ4 + R1
Δ1 锚语义(未给=缺锚 rc=2 / 空集=合法零集)、Δ2 连接身份与 db_migrate 同口径并拒绝 cma_api、
Δ3 --anchor-file(读 db-migrate-journal 指针件)、Δ4 anchor_source 入 JSON
R1-a 同源自证(journal 在册 + status=applied + finished_at 一致 + 目录内最新 -applied)
R1-b 未收敛锚累积由 db_migrate.write_anchor_pointer 实现、R1-c 收敛回写 converged_at
- db_migrate.py 加性 +2 处:新增 write_anchor_pointer()(原子写 journal/last-anchor.json);
cmd_apply 成功/失败两路径各调一次;零变更面未动(列级差异只告警 / create_all 幂等 /
--check 不写指针 / --rollback 与 resolve_journal 语义 / JSON 键集)
- deploy.sh 加性 1 步 [4b-2/5] 授权面收敛(插在「✓ 结构迁移完成」与「# 5. 重启后端服务」之间):
apply 跑 --apply --anchor-file ... --drift-policy warn,rc!=0 ⇒ 打印缺裁定清单 + exit 1
(后端不重启、旧码继续服务);drill 跑 --check,读数原样打印、WARN 不阻断
证据(全部零生产面):
- py_compile x3 通过;bash -n deploy.sh 通过(PYTHONPYCACHEPREFIX 隔离,仓内零新增 pyc)
- 纯函数用例 11/11(零连库):语句均为 GRANT / 无 REVOKE / 语句表 ⊆ write_tables / 域外权限 SystemExit
- 沙箱 S1–S9 回归 9/9 一致(SUMMARY.txt 与项目侧基线逐字节相同 md5 1a697e002a2cba8ae9b5ad9cc71b022d)
- 锚/R1 新例 18/18:缺锚/缺件/status=failed/R1-a 四负例均 rc=2 零写入;空锚 rc=0 executed=[]
- R1 验收链:发布1 建表 X(∉白名单) ⇒ rc=3 零写入 + 片段 exit 1 ⇒ 不修白名单重跑 ⇒ 仍 rc=3 ⇒
补白名单 ⇒ rc=0 + X 获授权 + converged_at 落定 ⇒ 三次重跑 executed=[](幂等)
- 既有 backend/tests:1509 passed / 0 failed,改前(HEAD 导出树)与改后失败集零差异
边界:本地 commit,零 push / 零部署 / 零重启 / 零连生产库 / 零 DDL-DML-GRANT-REVOKE;
上线(push + 部署 ⇒ 授权面生效)另单另铸 approval ID 且必附 R2 预演 diff(本单不为任何动作铸 ID)
2026-09-28 17:01:39 +08:00
..
2026-09-14 17:39:53 +08:00
2026-09-11 17:25:24 +08:00
2026-09-15 18:12:05 +08:00
2026-08-28 09:59:07 +08:00
2026-09-16 06:53:28 +08:00
2026-08-31 15:33:07 +08:00
2026-08-31 15:33:07 +08:00
2026-08-31 15:33:07 +08:00
2026-07-12 17:46:08 +08:00
2026-07-12 17:46:08 +08:00
2026-08-31 15:33:07 +08:00
2026-07-12 17:46:08 +08:00
2026-08-31 15:33:07 +08:00
2026-08-31 07:44:00 +08:00
2026-05-28 17:32:22 +08:00
2026-09-25 22:42:25 +08:00
2026-07-12 17:46:08 +08:00
2026-09-14 16:41:15 +08:00
2026-09-16 23:46:48 +08:00
2026-09-11 19:33:52 +08:00
2026-08-10 23:56:14 +08:00
2026-08-31 17:05:21 +08:00
2026-09-12 23:34:35 +08:00
2026-09-12 23:34:35 +08:00
2026-08-30 12:05:36 +08:00
2026-07-12 17:46:08 +08:00
2026-08-31 15:33:07 +08:00
2026-08-31 15:33:07 +08:00
2026-08-27 15:51:19 +08:00
2026-09-03 18:15:05 +08:00
2026-05-28 17:32:22 +08:00
2026-09-28 17:01:39 +08:00
2026-07-14 16:02:33 +08:00
2026-07-14 16:02:33 +08:00
2026-06-05 07:51:20 +08:00
2026-07-14 16:02:33 +08:00
2026-09-23 23:08:26 +08:00
2026-06-05 07:51:20 +08:00
2026-07-12 17:46:08 +08:00
2026-08-31 15:33:07 +08:00
2026-09-12 23:34:35 +08:00
2026-09-11 17:25:24 +08:00
2026-08-28 09:59:07 +08:00
2026-07-12 17:46:08 +08:00
2026-07-29 18:16:37 +08:00
2026-09-28 17:01:39 +08:00
2026-09-23 16:20:43 +08:00
2026-09-12 23:34:35 +08:00
2026-09-12 23:34:35 +08:00
2026-09-16 01:17:09 +08:00
2026-09-23 18:29:52 +08:00
2026-09-14 17:25:49 +08:00
2026-09-25 07:07:01 +08:00
2026-07-14 16:02:33 +08:00
2026-07-14 16:02:33 +08:00
2026-09-14 18:21:33 +08:00
2026-09-25 10:39:18 +08:00
2026-09-14 19:05:16 +08:00
2026-09-23 21:39:24 +08:00
2026-09-23 21:39:24 +08:00
2026-07-22 17:43:59 +08:00
2026-09-22 11:06:02 +08:00
2026-08-27 15:51:19 +08:00
2026-09-12 23:34:35 +08:00
2026-09-15 18:12:05 +08:00
2026-09-23 18:29:52 +08:00
2026-07-14 16:02:33 +08:00
2026-09-25 10:39:18 +08:00
2026-08-27 10:59:56 +08:00
2026-07-14 17:32:22 +08:00
2026-07-21 23:41:40 +08:00
2026-09-11 19:33:52 +08:00
2026-08-04 15:35:15 +08:00
2026-09-23 21:39:24 +08:00
2026-08-30 19:16:19 +08:00
2026-09-12 01:03:31 +08:00
2026-08-30 12:05:36 +08:00
2026-07-12 17:46:08 +08:00
2026-06-05 07:51:20 +08:00
2026-07-12 17:46:08 +08:00
2026-07-16 16:39:24 +08:00
2026-08-28 07:18:54 +08:00
2026-07-12 17:46:08 +08:00
2026-09-28 13:56:16 +08:00
2026-09-12 23:34:35 +08:00
2026-07-12 17:46:08 +08:00
2026-07-21 17:30:50 +08:00
2026-07-12 17:46:08 +08:00
2026-08-11 00:11:25 +08:00
2026-07-13 09:52:06 +08:00
2026-07-21 17:22:43 +08:00
2026-08-19 22:58:10 +08:00
2026-07-14 16:02:33 +08:00
2026-07-14 16:02:33 +08:00
2026-09-16 14:59:02 +08:00
2026-09-18 06:04:48 +08:00
2026-09-15 20:02:56 +08:00
2026-09-03 18:41:44 +08:00
2026-07-14 16:02:33 +08:00
2026-09-08 13:43:20 +08:00
2026-09-12 20:35:20 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 18:44:39 +08:00
2026-09-14 17:39:53 +08:00
2026-09-13 07:38:58 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-15 18:12:05 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-14 17:39:53 +08:00
2026-09-16 01:17:09 +08:00
2026-09-14 17:39:53 +08:00
2026-09-16 00:38:01 +08:00
2026-09-14 17:39:53 +08:00
2026-09-11 17:25:24 +08:00
2026-09-06 16:47:25 +08:00