Files
X-Financial/document/development/2026-07-17/feature/hermes-ontology-tenant-security/CONCEPT.md
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

6.1 KiB
Raw Blame History

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 保存租户快照。

非目标

  • 不提供客户端选择或覆盖租户的兼容参数。
  • 不实现跨企业合并分析、集团穿透报表或平台运营后台。
  • 不在本切片中重构预算分配等仍属旧模型的全部业务域。

信任边界

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 → 00280028 → 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 迁移、反向回滚和安全回归。