三、需要继续修复的代码问题
F01 · P0 · 静态确认 · 文件安全
失败清理可能沿符号链接父目录删除非任务文件
位置:finance/exporting.py → process_formula_export()。先设置 target,再检查 target.parent 是否为符号链接;拒绝后进入异常分支,仅检查 path.is_symlink(),未检查父目录。父目录为链接而最终文件本身为普通文件时,unlink 会跟随父目录删除链接目标下同名文件。
影响:需要本地存储目录被操纵这一前提,不能描述为普通远程用户已可利用;但违背“异常清理只删除自己创建的文件”的边界。
推荐修复:路径完整验证前不要将目标登记为可清理文件;只清理本次实际创建、且位于受控目录中的文件,必要时用目录描述符及不跟随链接的文件操作。不要用失败清理代替旧孤儿文件回收。
验收:父目录链接到受保护目录,预置同名文件;执行必须失败且受保护文件字节不变,任务为 failed;覆盖根目录链接、目标链接、写盘失败与正常重试。
F02 · P1 · 静态确认 · 故障清理
清理失败被忽略,敏感孤儿文件缺少回收路径
位置:finance/exporting.py 与 cleanup_formula_exports.py。异常清理吞掉 OSError 后清空 job.path;清理器主要处理已成功且过期的文件及旧 .tmp,失败任务残留 .xlsx 可能不再被追踪。
修复:记录不含敏感数据的清理失败日志及任务编号,为安全范围内的孤儿 .xlsx 制定保留期与回收规则;不要删除仍处于活动任务的文件。
验收:注入 unlink 权限错误,任务失败状态仍保存;可观察到告警,恢复权限后回收成功,其他任务文件不受影响。
F03 · P1 · 静态确认 · 证据弹窗
重复点击当前期间可能让已加载列表停在“加载中”
位置:frontend/src/dialogs.tsx → EvidenceDialog.selectSide()。第 0 页点击当前已选期间会清空 result,但 side/page 没变化,依赖这些值的 effect 不会重新请求。
修复:同期间同页直接返回,或明确触发刷新;补加载、空集、失败重试状态。
验收:当前期间重复点击、快速本期/基期切换、第二页切期间、空列表和请求失败均不显示过期数据或永久加载。
F04 · P1 · 静态确认 · 定义复用后的对话
载入已保存定义后追问,没有把原定义带给模型
位置:FormulaExportDialog.loadDefinition()/send()。载入定义会清空 messages,随后只发送新增描述;“把刚才公式改成乘以 100”之类指代不能可靠关联已载入表达式。
修复:在可见、经同意的对话上下文中明确附带原定义,或建立服务端定义引用;仍要求重新确认,不让旧定义静默覆盖新解释。选择空选项也应同步清理当前定义,避免选择状态与预览不一致。
验收:保存 A、重开载入 A、发送依赖 A 的修改,检查模型请求实际包含 A;未发送补充时禁止生成,修改后生成的公式符合新定义。
F05 · P1 · 静态确认 · 定义库并发与审计
50 条上限不是原子约束,同名更新没有冲突检测
位置:finance/formula_views.py → formula_definitions()。先 count 再 update_or_create,并发不同名字可能突破上限;同名更新采用最后写入覆盖,未携带 revision。保存/删除与审计也不在同一外层事务内。
修复:事务内锁定稳定的用户/数据集所属行,原子检查配额;引入 revision 和 409 冲突响应;变更和审计一同提交,保存增加合理限流。前端明确同名更新行为。
验收:PostgreSQL 并发保存不能产生第 51 条;两个标签页更新不静默丢失;模拟审计写入失败后定义变更回滚。
F06 · P1 · 静态确认 · 工作簿可解释性
“产品毛利率可编辑”说明与实际公式引用不一致
位置:finance/exporting.py → 参数与口径 / GrossCalc。参数页毛利率写成字典文本并标为可编辑,实际明细公式引用每行 MarginRate,修改参数页文本不会联动。说明页还提到“本页分组维度”,但没有完整的维度键与显示名称字典。
推荐:近期明确参数页为只读快照,写清需要修改计算明细的哪类输入;如必须按产品统一模拟,则实现真实产品毛利率参数表与 lookup 依赖,并验证 direct 毛利不受影响。
验收:每个标为可编辑的输入都对应真实依赖;收入、成本、原价、直接毛利、lookup 毛利率分别改值重算,说明页列出字段、单位、来源、缺失含义和固定结构边界。
F07 · P1 · 静态确认 · 财务校验范围
对账采用统一 0.01 阈值,自定义公式没有独立服务器参考
位置:finance/exporting.py → 对账检查。人数、金额、比率共享差异阈值;对小数形式的比率,0.01 是一个百分点,未必适用业务。自定义列标记“需业务验收”,不是自动对账通过。
修复:财务批准后按指标配置比较规则:人数严格相等、金额按币种和舍入精度、比率独立阈值;用 Decimal 白名单表达式解释器计算自定义指标参考,不能执行任意代码。保持原始金额文本不变。
验收:阈值边界、大数、抵消、极小值、除零、缺失和多层表达式独立黄金样例通过;不得为消除报错而放宽容差。
F08 · P1 · 验证缺口 · 权限撤销与任务生命周期
执行/下载阶段需要覆盖角色撤销、超时与崩溃恢复
当前有组织、任务所有者、科室范围检查,但 worker 不重新要求 admin/analyst 角色;下载接口也未声明同创建接口的角色白名单。是否允许被降为 viewer 的账号下载旧导出,需要明确政策,不能默认授权语义已完整。
推荐:敏感公式工作簿在申请、执行、下载时统一核验角色、组织、账户有效性和科室;补任务超时、重复请求、过期下载、worker 发布后崩溃的测试及运维告警。
验收:排队后撤权、成功后撤权均按签署政策处理;半成品不能下载;重启不重复发布或无限停留 processing。生产 PostgreSQL 锁语义单独验证。