归档CEO财务兜底任务(07-28-ceo-finance-fallback)
这个提交包含在:
@@ -0,0 +1 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
@@ -0,0 +1,63 @@
|
||||
# CEO 本人报销财务兜底设计
|
||||
|
||||
## 1. Boundary
|
||||
|
||||
本任务复用现有审批规则和工作流快照机制,不新增角色、数据表、迁移或公开端点。`finance_mgr` 保持兼容;本公司的新默认和生产规则改为 `finance`。
|
||||
|
||||
## 2. Cross-layer Contract
|
||||
|
||||
```text
|
||||
审批规则配置
|
||||
ownerSelfFallbackRole: finance | finance_mgr | null
|
||||
-> API 白名单校验
|
||||
-> ApprovalRule 持久化
|
||||
-> 报销提交加载规则
|
||||
-> CEO 本人且 manager 无法解析时使用 fallback
|
||||
-> 移除本人 ceo 节点 + 角色去重
|
||||
-> 校验 active 非本人角色持有人
|
||||
-> 冻结 workflow_steps_snapshot
|
||||
```
|
||||
|
||||
创建 API、省略字段时的默认值和前端新建表单默认值统一为 `finance`。旧规则返回 `finance_mgr` 时前端仍可展示、编辑和保存,避免破坏兼容数据。
|
||||
|
||||
## 3. Target Rule Matrix
|
||||
|
||||
| 金额档 | 普通员工规则 | CEO 本人快照 |
|
||||
| --- | --- | --- |
|
||||
| 小额 | `manager -> finance` | `finance` |
|
||||
| 中额 | `manager -> finance` | `finance` |
|
||||
| 大额 | `manager -> ceo -> finance` | `finance` |
|
||||
|
||||
CEO 本人快照只由现有标准步骤完成:`manager` 缺失时插入 `finance` fallback;随后相同 `finance` 节点去重,申请人自身 `ceo` 节点移除。无需添加按金额或人员姓名硬编码的特殊分支。
|
||||
|
||||
## 4. Validation And Failure Behavior
|
||||
|
||||
- fallback 不在 `finance|finance_mgr`:`400 VALID_001`。
|
||||
- CEO 同时持有 fallback:`409 VALID_001 / owner_self_fallback_self_role`。
|
||||
- 无 active 非本人 fallback 持有人:`409 VALID_001 / owner_self_fallback_role_unavailable`。
|
||||
- 非 CEO:不触发 owner-self fallback,保留正常规则快照。
|
||||
- 生产规则数量、金额区间或当前角色结构漂移:回填事务停止,零写入。
|
||||
|
||||
## 5. Production Rollout
|
||||
|
||||
1. 部署代码与前端,使 runtime 能读写 `finance` fallback;`seed:config` 对既有审批规则只保留不覆盖,避免部署提前改写生产规则。
|
||||
2. 核对公网构建号和 runtime smoke。
|
||||
3. 生产只读冻结 3 条规则、active `finance` 持有人、CEO 身份、角色/binding/历史快照计数。
|
||||
4. 单事务更新 3 条启用规则:中/大额 `finance_mgr` 节点改为 `finance`,全部 fallback 改为 `finance`;逐条写脱敏审计。
|
||||
5. 只读解析三档 CEO 快照和普通员工快照,不创建真实报销。
|
||||
|
||||
## 6. Rollback
|
||||
|
||||
- 代码兼容 `finance_mgr`,生产规则可在精确冻结原值后原子恢复。
|
||||
- 回滚规则只影响回滚后新提交单据;既有 `workflow_steps_snapshot` 保持不变。
|
||||
- 任一生产检查失败时先回滚规则,不改员工角色或历史单据。
|
||||
|
||||
## 6.1 Seed Safety
|
||||
|
||||
- 空库首次初始化时创建三条新默认规则。
|
||||
- 只要审批规则表已有任意记录,`seed:config` 保留全部既有规则,不删除、不覆盖、不补写;生产规则只允许走获批的独立原子事务。
|
||||
- 部署日志只记录创建/保留计数,不输出规则 ID、人员或业务内容。
|
||||
|
||||
## 7. Trade-off
|
||||
|
||||
不采用“给现有财务追加 `finance_mgr`”方案,因为该角色同时包含主数据、预算、集成、AI、资产和薪酬等更宽权限,超出“审批 CEO 本人报销”的最小职责。允许 `finance` 作为兜底能复用已有 `expense.approve`,权限面更小。
|
||||
@@ -0,0 +1 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
@@ -0,0 +1,49 @@
|
||||
# CEO 本人报销财务兜底实施计划
|
||||
|
||||
## 1. Implementation
|
||||
|
||||
- [x] 扩展后端 owner-self fallback 白名单为 `finance|finance_mgr`,创建默认值改为 `finance`。
|
||||
- [x] 将三档种子默认规则统一为财务 `finance` 收口,保留大额 `ceo` 节点。
|
||||
- [x] 更新前端 API 类型、创建/编辑选项、默认值和推荐文案;兼容展示 `finance_mgr`。
|
||||
- [x] 更新工作流、规则 API、报销提交回归测试,覆盖 CEO 三档唯一 `finance`、普通员工链、自审、无持有人和 legacy `finance_mgr`。
|
||||
- [x] 修正 `seed:config` 对既有审批规则的删除重建副作用;仅空库创建默认规则,生产既有规则保留到独立原子回填阶段。
|
||||
- [x] 新增默认 dry-run、双确认 apply 的生产规则回填脚本;事务内锁定并校验三档规则、CEO/财务/admin/binding 基线,更新三条规则、写三条脱敏审计并复核受保护计数。
|
||||
- [x] 生产 dry-run 发现原生 `audit_logs` 插入未携带 Prisma 客户端侧 UUID;事务已回滚。脚本已改为显式写入审计 UUID,并新增执行级回归覆盖三条审计 SQL 与 dry-run 回滚。
|
||||
- [x] 更新当前业务事实源,区分目标、代码部署和生产规则回填状态。
|
||||
|
||||
## 2. Local Validation
|
||||
|
||||
- [x] `cd server && node --check src/utils/workflow.js && node --check src/routes/approvalRules.js && node --check src/scripts/seed-config.js && node --check src/scripts/apply-ceo-finance-fallback.js`
|
||||
- [x] `cd server && npx vitest run tests/unit/utils/workflow.test.js tests/unit/routes/approvalRules.permissions.test.js tests/unit/routes/reimbursements.expense-standards.test.js tests/unit/scripts/seed-config.defaults.test.js tests/unit/scripts/apply-ceo-finance-fallback.test.js`(58 项通过)
|
||||
- [x] `cd server && npm run prisma:validate`
|
||||
- [x] `cd client && npm run typecheck && npm run build`
|
||||
- [x] `node scripts/qa/check-process-contract.mjs --baseline --json`
|
||||
- [x] `node scripts/qa/audit-docs.mjs --check-registry`(0 error,保留既有 22 个未注册文档 warning)
|
||||
- [x] `python3 ./.trellis/scripts/task.py validate 07-28-ceo-finance-fallback`
|
||||
- [x] `node scripts/qa/check-trellis-governance.mjs && git diff --check`
|
||||
- [x] `bash scripts/check-minimal.sh`(167 个测试文件、1053 项后端测试、前端 build 与矩阵门禁通过)
|
||||
- [x] dry-run 缺陷修复后复跑 Prisma validate 与 5 个聚焦测试文件(59 项通过)。
|
||||
|
||||
## 3. Review Gate
|
||||
|
||||
- [x] 只读 review 权限白名单、自审阻断、普通员工链、历史快照不回写、API/UI 类型一致性和生产事务边界;发现并修复部署 seed 提前覆盖规则问题后复核无剩余阻断。
|
||||
|
||||
## 4. Deployment And Production Apply
|
||||
|
||||
- [x] 提交并推送已验证代码。
|
||||
- [x] 修复部署脚本已知的数据目录保护缺陷:同步根目录与数据目录任一方向重叠时在 SSH 前阻断,自定义同步树内 `.env` 动态保护;隔离备份/恢复合同通过。
|
||||
- [x] 部署后核对 `/ready` 构建号、migration 状态、runtime smoke、external deps smoke 和前端 bundle。
|
||||
- [x] 生产只读冻结规则结构、active `finance`、CEO、角色、binding、历史快照和审计基线。
|
||||
- [x] 原子更新恰好 3 条启用规则并逐条写脱敏审计;任一预条件漂移则零写入停止。
|
||||
- [x] 只读解析 CEO 小/中/大额快照均为唯一 `finance`,普通员工链符合目标;不创建真实报销。
|
||||
- [x] 复核无角色、主管、binding、历史快照或企微写入变化。
|
||||
|
||||
部署执行备注:`3594872` 首次部署通过,并将附件从同步树内迁至独立数据目录、保留校验一致的回退副本;首次生产 dry-run 因审计表 UUID 缺失失败并完整回滚。修复提交 `a74cba1` 随后部署,`/ready`、migration、runtime/external-deps smoke、92 个公网资源扫描通过;4 个自动运维 timer 已刷新运行身份。第二次 dry-run 为 `DRY_RUN_PASS`,apply 原子写入 3 条规则与 3 条脱敏审计,受保护计数稳定;只读解析 CEO 三档均为唯一 `finance`、普通员工链符合目标,0 条真实报销、0 次企微写入。
|
||||
|
||||
## 5. Stop Conditions
|
||||
|
||||
- 生产 active `finance` 不是唯一非 CEO 持有人,或目标人员 inactive/unbound。
|
||||
- 启用规则不是恰好 3 条,金额区间或角色结构与冻结基线不符。
|
||||
- 部署路径仍可能删除 `.env`、附件或数据库宿主目录。
|
||||
- 任一测试出现自审、管理员代批、历史快照重写或普通员工链异常。
|
||||
- 真实 CEO 报销验证未取得单独批准。
|
||||
@@ -0,0 +1,69 @@
|
||||
# CEO 本人报销财务兜底修正
|
||||
|
||||
## Goal
|
||||
|
||||
让 `majianyong(ceo)` 本人提交任一金额档报销时,在禁止自审的前提下只进入 active 非本人 `finance` 审批;`wangshunli` 的系统管理员身份不进入业务审批链,也不通过给现有财务附加 `finance_mgr` 扩权来绕过问题。
|
||||
|
||||
## Scope
|
||||
|
||||
- 报销审批工作流的负责人本人 fallback 白名单、快照解析和失败关闭行为。
|
||||
- 审批规则 API、前端配置页与三档默认种子规则的 `finance` 默认值和 `finance_mgr` 兼容。
|
||||
- 部署同步根目录与 PostgreSQL、附件和环境文件的安全隔离合同。
|
||||
- 经部署与公网验证后,对生产恰好 3 条启用报销规则进行一次原子回填和脱敏审计。
|
||||
|
||||
## Background
|
||||
|
||||
- 用户确认 `majianyong` 是公司 CEO、无直属主管;`wangshunli` 仅承担系统开发和系统管理。
|
||||
- 生产有 3 条启用报销金额规则,均使用 `owner_self_fallback_role=finance_mgr`,中/大额规则还包含 `finance_mgr` 节点。
|
||||
- 生产有 1 名 active 且已绑定企微的 `finance`,没有 active `finance_mgr`;当前 CEO 本人报销会以 `owner_self_fallback_role_unavailable` 失败关闭。
|
||||
- 代码、审批规则 API、前端配置页和种子默认值目前只把 `finance_mgr` 作为负责人本人兜底角色。
|
||||
- 现有工作流已具备 CEO 自审节点移除、重复角色去重、active 非本人持有人检查和历史审批快照冻结能力。
|
||||
|
||||
## Requirements
|
||||
|
||||
- `finance` 和兼容保留的 `finance_mgr` 均可作为 `ownerSelfFallbackRole`;新建规则默认使用 `finance`。
|
||||
- 小团队默认金额规则调整为:小额 `manager -> finance`、中额 `manager -> finance`、大额 `manager -> ceo -> finance`,三档 `ownerSelfFallbackRole` 均为 `finance`。
|
||||
- CEO 本人申请在三档规则下均生成唯一 `finance` 节点:替换无法解析的 `manager`、移除本人 `ceo`、去除重复 `finance`。
|
||||
- `finance` 兜底必须存在 active 非本人持有人;CEO 若同时持有 `finance` 或无可用持有人,继续失败关闭。
|
||||
- 普通员工的工作流仍按规则顺序生成,不引入 CEO 本人专属的全局跳步;历史 `workflow_steps_snapshot` 不回写。
|
||||
- 审批规则 API 和前端配置页同时支持 `finance`/`finance_mgr`,默认与推荐值显示为 `finance`;不开放 `admin`、`system_admin`、`hr` 或其他角色作为负责人本人兜底。
|
||||
- 部署后以原子事务将生产 3 条启用规则从现状修正为上述三档结构并写脱敏审计;写入前必须重新确认规则数量、金额区间、角色结构、active 财务持有人和 CEO 身份,任一漂移即停止。
|
||||
- 生产回填不改员工角色、直属主管、既有报销审批快照、密码、企微 binding 或企微通讯录。
|
||||
- 公网验证只创建一条由 CEO 本人发起的低风险测试报销时,必须再次取得真实业务写入批准;本任务默认只做规则只读解析/smoke,不自动创建真实报销。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] 后端工作流单元测试证明 CEO 本人小/中/大额快照均只有一个 `finance` 节点。
|
||||
- [x] 无 active 非本人 `finance`、CEO 同时持有 `finance`、不支持的兜底角色均失败关闭且不创建半截工作流。
|
||||
- [x] 普通员工规则快照保持 `manager -> finance` 或 `manager -> ceo -> finance`,无自审放宽。
|
||||
- [x] 审批规则 API 接受 `finance` 和兼容的 `finance_mgr`,拒绝非白名单角色;新建默认值为 `finance`。
|
||||
- [x] 前端类型、创建/编辑选项和推荐文案支持 `finance`,默认选择 `finance`,typecheck/build 通过。
|
||||
- [x] 种子默认三档规则与目标链一致,相关回归测试通过。
|
||||
- [x] 只读 review 确认权限、自审、状态机、历史快照和生产回填边界无扩大。
|
||||
- [x] 部署后公网 `/ready` 构建号匹配,runtime smoke 和关联认证/工作流检查通过。
|
||||
- [x] 生产恰好 3 条启用规则按目标结构回填并留下脱敏审计;active 账号、角色、binding 和历史审批快照计数无意外变化。
|
||||
- [x] 当前事实源、管理员手册和任务结论不再宣称 `finance_mgr` 是本公司推荐兜底。
|
||||
|
||||
## Test Plan
|
||||
|
||||
- 后端语法、Prisma validate,以及 workflow、审批规则 API、报销提交和默认种子规则聚焦测试。
|
||||
- 前端 typecheck/build 与审批规则配置页聚焦 Playwright。
|
||||
- 部署环境静态合同、隔离备份恢复演练、流程合同、文档审计、Trellis task/governance 和敏感内容扫描。
|
||||
- 部署后核对 `/ready` 构建号、migration、runtime/external-deps smoke 和公网 bundle。
|
||||
- 生产回填前后只读冻结规则、角色、binding、历史快照和审计计数;只读解析 CEO 三档与普通员工链,不创建真实报销。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 不删除 `finance_mgr` 角色或改变其现有权限。
|
||||
- 不给现有财务人员新增 `finance_mgr`、`manager` 或其他角色。
|
||||
- 不改变普通报销金额阈值,不重构通用工作流引擎,不修改历史审批快照。
|
||||
- 不让 `admin`/`system_admin` 获得业务审批权,不允许任何申请人自审。
|
||||
- 不执行真实付款、企微写入或未经再次批准的真实 CEO 报销提交。
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- 后端白名单与快照:`server/src/utils/workflow.js`。
|
||||
- 审批规则 API:`server/src/routes/approvalRules.js`。
|
||||
- 默认规则:`server/src/scripts/seed-config.js`。
|
||||
- 前端类型和页面:`client/src/api/approvalRules.ts`、`client/src/pages/ApprovalRulesPage.tsx`。
|
||||
- 聚焦测试:`server/tests/unit/utils/workflow.test.js`、`server/tests/unit/routes/approvalRules.permissions.test.js`、`server/tests/unit/routes/reimbursements.expense-standards.test.js`。
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "ceo-finance-fallback",
|
||||
"name": "ceo-finance-fallback",
|
||||
"title": "CEO 本人报销财务兜底修正",
|
||||
"description": "让 CEO 本人报销在禁止自审的前提下由 active 非本人 finance 审批,并以最小权限修正代码、默认规则和生产配置。",
|
||||
"status": "completed",
|
||||
"dev_type": null,
|
||||
"scope": "server, client, deploy/trialrun, workflow tests, current docs, production approval rules",
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "shunli",
|
||||
"assignee": "shunli",
|
||||
"createdAt": "2026-07-28",
|
||||
"completedAt": "2026-07-28",
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户