# Orchestrator 未认证与费用申请决策绕过

日期：2026-07-14
文档路径：document/development/2026-07-14/dev-logs/bugs/orchestrator-auth-preview-decision-bypass.md

## 修复记录

- 15:43：记录 bug 修复：Orchestrator 未认证与费用申请决策绕过。
  - Git 提交检查：`git fetch --all --prune` 成功，`origin/main` 没有新提交；本地 ahead 9 条，依次为 `5b246307` 服务端申请预览决策、`a662cfe6` 申请反馈账本、`5ed34c2b` 历史费用 Case 回填、`11275e4b` 迁移所有权安全、`1347366b` 安全时间线与草稿事件、`22669a90` 统一费用时间线、`a616b30c` AI 申请提交事务、`653eda05` Bearer 会话、`661990b2` 事务型费用事件；工作树为 dirty，未执行合并或变基。
  - 修改：`orchestrator.py` 的所有外部来源改为强制认证，`schedule` / `system_event` 进一步要求平台管理员；`OrchestratorService` 用登录态覆盖客户端身份与调度操作人别名并丢弃 preview/decision 注入。`agent_conversations.py` 与 Steward 动作运行时使用可信租户状态隔离会话创建、恢复、幂等检查点和删除；统一申请预览工作流要求 Steward、工作台和小财管家先签发再保存/提交，并复用同会话同快照的 active decision。
  - 操作：把 Orchestrator 申请 decision 保存到服务端会话，草稿保存后的 next decision 继续回写；工作台 Steward 申请动作改为先打开结构化签发预览。过期/已消费 decision 会清空旧 ID 并进入可重新签发状态；租户 A/B 使用相同用户名、conversation 和 trace 时创建独立会话与 decision。所有验证均在 `x-financial-local-linux` 容器 `/app` 内执行，未修改七个用户规则工作簿。
  - 验证：后端组合回归 50 项通过，覆盖服务端预览、Steward 动作/图运行、跨租户 checkpoint、Orchestrator 匿名/普通用户/管理员来源授权与 decision 消费，Python Ruff F/I 通过；前端结构化动作、会话恢复、工作台动作路由、富确认和动作脚本 18 项通过，Vite 生产构建通过。共享工作簿并行读取曾触发 `openpyxl` ZIP 竞争，串行复跑相关套件后全部通过。
  - 影响：未登录用户不能再通过伪造 `source` 调用 Orchestrator，普通用户也不能伪装调度来源触发 Hermes 管理任务；同名用户不能跨租户恢复、删除或重放 Steward 会话检查点。申请保存/提交只消费当前登录会话签发的 decision，重复签发、过期和失败均有确定的安全处理。
