Files
caoxiaozhu 787bc3a481 feat(platform): close AI expense value loop
Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
2026-07-17 14:14:08 +08:00

107 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hermes、本体解析与财务报告多租户安全 概念文档
更新时间2026-07-17
## 功能一句话
让本体解析、员工行为画像、Hermes 扫描、数字员工看板和定时财务报告从请求到存储全程绑定可信企业,并在任何租户上下文缺失或冲突时停止运行。
## 背景与问题
本体解析曾在建立 `AgentRun` 前调用模型,并从全局员工、组织、客户、供应商、项目和单据字典构造提示词;员工画像详情可按任意员工 ID 查询Hermes 扫描、看板和财务报告存在全表读取、全局收件人以及跨企业复用存储路径的风险。内部 Orchestrator 调用还可在没有认证用户时继续运行,无法证明 `AgentRun` 的企业归属。
## 目标与非目标
### 目标
- HTTP 入口只信任 `CurrentUserContext.tenant_id`,内部任务只接受显式、已注册且启用的 `trusted_tenant_id`
- 本体解析在任何模型调用前创建租户化 `AgentRun`,商业运行上下文和失败证据可追溯。
- 员工、组织、费用、应收、应付、画像、风险、提醒和看板查询在首个 SQL 中限定租户。
- 员工画像仅允许本人、直属领导、财务/高管或管理员读取;越权和跨租户统一返回 404。
- 财务报告按租户配置收件人、生成内容、存储文件和幂等运行账本,不使用全局邮件回退。
- 所有 Hermes 定时任务逐个枚举 `status=active` 的企业,运行记录同时在 route/ontology 保存租户快照。
### 非目标
- 不提供客户端选择或覆盖租户的兼容参数。
- 不实现跨企业合并分析、集团穿透报表或平台运营后台。
- 不在本切片中重构预算分配等仍属旧模型的全部业务域。
## 信任边界
```text
HTTP 请求 ── CurrentUserContext.tenant_id ─┐
├─→ tenant-scoped AgentRun
内部任务 ── active trusted_tenant_id ──────┘ ├─ route_json.tenant_id
└─ ontology_json.tenant_id
```
- 客户端 `context_json.tenant_id` 会被可信租户覆盖,不能参与授权。
- 同时传入登录用户和内部租户时,两者必须一致。
- 内部任务租户必须存在于租户注册表且状态为 active缺失、停用或不存在均在创建 Run 前拒绝。
- 后台消费者从数据库 Run 恢复租户,并校验 route/ontology 两份快照一致。
## 功能设计
### 本体解析
- 接口覆盖请求中的 user id并把认证企业传给 `SemanticOntologyService`
- `parse()` 先建立 `running/pending_model_analysis` Run再加载租户字典、商业运行上下文并调用模型。
- 模型、规则降级和失败路径都更新同一 Run失败不会留下无企业、无状态的调用。
- 员工、部门、费用申请、应收、应付和项目参考目录均以租户作为第一层 SQL 条件。
### 员工画像
- 快照保存 `tenant_id`,并用 `(tenant_id, subject_id)` 复合外键绑定员工。
- Profile Service 的快照、费用单和 Agent Run 查询均先限定租户。
- 详情接口先在当前企业解析目标员工,再执行本人/直属领导/财务/高管/管理员访问矩阵。
- 附带 `claim_id` 时必须同时属于目标员工和当前企业。
### Hermes 与数字员工
- 风险扫描、画像扫描、风险线索、提醒扫描和看板均接受显式租户。
- 调度器只枚举 active 企业,并为每个企业独立创建任务与结果。
- 看板只统计 route/ontology 租户快照均匹配的 Run缺少或冲突快照的历史记录不会被猜测归属。
- 提醒任务的费用单、员工和关联报销查询在首个 SQL 限制当前企业。
### 财务分析报告
- `TenantFinanceReportConfig` 保存企业启停状态和经校验的收件人。
- `TenantFinanceReportRun``(tenant_id, idempotency_key)` 防止同企业同周期重复发送。
- 报告上下文只读取当前企业的费用、风险、画像和 Agent Run。
- 邮件发送只使用当前企业配置;未配置、停用或无有效收件人时 fail-closed。
- 文件存储目录使用企业标识哈希,避免路径注入和跨企业文件覆盖。
## 数据与迁移
`20260717_0028_hermes_ontology_tenant_security.py` 完成:
- 员工行为画像、Hermes 任务配置/日志和风险报告新增租户列、索引、唯一约束和复合外键。
- 新增租户财务报告配置和周期运行账本。
- 旧记录回填为 `default`,再移除 server default后续写入必须显式确定企业。
- 仅支持 PostgreSQLupgrade/downgrade 在任何 DDL 前检查方言,其他数据库直接拒绝。
- downgrade 在存在非默认企业事实或报告账本时拒绝有损回滚。
## 降级与回滚
- 租户缺失、停用、不存在或上下文冲突:不创建 Run、不查询业务数据。
- 跨企业员工、画像、费用单:统一按不存在处理。
- 企业未配置报告收件人:保留失败/跳过证据,不回退环境变量中的全局地址。
- 历史 Run 没有双租户快照:看板不纳入企业统计。
- 生产升级前必须在数据库备份副本演练 `0027 → 0028 → 0027 → 0028`
## 测试与验收
- 两企业本体目录、画像 IDOR、Hermes 扫描、风险线索、看板和报告内容/收件人/路径/幂等隔离。
- Orchestrator 缺租户、停用租户、不存在租户和认证/内部租户冲突均在 Run 前拒绝。
- 本体模型调用前存在 running Run失败后仍保存同企业失败证据。
- PostgreSQL 完成 fresh `base → 0028``0028 → 0027 → 0028` 及旧表回填/外键验证。
- 所有后端测试和 Ruff 均在 `local-x-financial-linux` 容器内执行,单命令不超过 60 秒。
## 本轮实现记录
- 2026-07-17完成本体解析前置 Run、可信商业上下文和租户参考目录。
- 2026-07-17完成员工画像模型、服务和 API 的租户隔离与访问矩阵。
- 2026-07-17完成 Hermes 扫描、提醒、看板、调度和财务报告的逐租户运行。
- 2026-07-17完成 `20260717_0028` PostgreSQL 迁移、反向回滚和安全回归。