Files
th-hotel-simple/docs/project/security-access-control-boundary.md
2026-07-24 11:55:29 +07:00

251 lines
37 KiB
Markdown
Raw 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.

# TH Hotel 接口暴露、权限与审计边界
## 1. 文档定位
本文是当前项目的接口安全边界总表,用于后续新增接口、大改调用方、调整权限或补审计时统一判断:
- 哪些接口给前端用户调用。
- 哪些接口给第三方系统调用。
- 哪些能力只能后端内部使用,不能暴露给前端或第三方。
- 每类接口应采用什么鉴权方式、权限码、酒店隔离和审计策略。
如本文与具体接口契约冲突:
- SuperAgent / MCP / AgentBus 对外契约以 `docs/project/integrations/superagent-api-contract.md``docs/project/integrations/superagent-mcp/README.md` 和对应集成文档为准。
- 前端展示和字段契约以 `docs/project/frontend-backend/README.md` 指向的当前有效文档为准。
- 权限、审计、暴露边界以本文为补充检查清单,接口变更时必须同步更新。
## 2. 调用方分类
| 分类 | 中文说明 | 典型调用方 | 默认鉴权方式 |
| --- | --- | --- | --- |
| `PUBLIC` | 公开基础接口,只能返回非敏感健康或登录入口信息 | 浏览器、运维探活 | 无登录;不能返回业务数据 |
| `FRONTEND_USER` | 普通业务前端接口 | 登录后的酒店业务用户 | Bearer session token + 权限码 + 酒店访问权 |
| `FRONTEND_ADMIN` | 系统管理后台接口 | 系统管理员 | Bearer session token + 管理权限码 + 管理审计 |
| `FRONTEND_DEBUG` | 调试或演示接口 | 开发、测试、受控管理员 | 环境开关 + 登录权限或临时 access key + 调试审计 |
| `THIRD_PARTY_SUPERAGENT` | SuperAgent HTTP 对接接口 | SuperAgent Runtime / Skill | HMAC-SHA256 + timestamp + nonce + body hash |
| `THIRD_PARTY_AGENTBUS` | AgentBus 实时消息入口 | AgentBus WebSocket | AgentBus Token + 环境开关 + 入库幂等 |
| `THIRD_PARTY_MCP` | SuperAgent MCP 写入工具 | SuperAgent MCP Client | Bearer Token + 工具级能力限制 |
| `INTERNAL_ONLY` | 后端内部能力,不对外直接暴露 | Worker、Adapter、Repository、Mapper | 不提供外部入口;通过 Service / Port 调用 |
## 3. 当前接口边界矩阵
### 3.1 公开和登录接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `GET /api/health` | `PUBLIC` | 无登录;返回健康状态和非敏感部署证明字段 `runtime_marker``build_commit``build_time``build_version` | 保持公开,但不得返回配置、版本 Secret、环境变量值、数据库细节、客户数据或外部系统状态`build_commit` 只用于确认测试机 / UAT 是否运行预期构建包 | 不需要业务审计 |
| `POST /api/auth/login` | `PUBLIC` | 用户名密码登录,返回一次性 `access_token` | 增加登录失败频率控制和登录安全审计可后置 | 建议补登录安全审计 |
| `GET /api/auth/me` | `FRONTEND_USER` | 必须 Bearer token | 保持强制登录,返回权限、菜单和酒店上下文 | 不需要每次写业务审计 |
| `POST /api/auth/logout` | `FRONTEND_USER` | 必须 Bearer token | 保持强制登录,撤销当前 session | 可记录安全审计 |
### 3.2 前端业务接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `GET /api/reservation/tasks` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_TASK_READ`;支持可选 `hotel_id` 并校验酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 酒店访问权 | 只读查询默认不写业务审计 |
| `GET /api/reservation/orders` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_ORDER_READ`;支持可选 `hotel_id` 并校验酒店访问权;已返回 V4 继续处理入口和统一 open count 安全字段 | 保持登录 + `RESERVATION_ORDER_READ` + 酒店访问权V4 入口字段只返回 order task / card ID、动作类型、状态和数量摘要`open_work_item_count` 仅返回当前订单待处理数量摘要 | 只读查询默认不写业务审计;不得返回邮件正文、附件 URL、AI 原始 payload 或来源通知原始 payload |
| `GET /api/reservation/orders/{orderId}` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_ORDER_READ`;按订单实际所属酒店校验访问权;已返回旧 `tasks[]`、V4 `order_overview``next_v4_action``related_source_messages[]``v4_order_tasks[]` 安全摘要时间线 | 保持登录 + `RESERVATION_ORDER_READ` + 订单所属酒店访问权V4 时间线读取按订单酒店过滤;`order_overview` 只能从已确认 V4 卡片派生,`next_v4_action` 只返回下一步处理 ID / 动作 / 状态 / 数量摘要,`related_source_messages[]` 只返回来源邮件安全摘要 | 只读查询默认不写业务审计;不得在 `order_overview``v4_order_tasks[].cards[]` 返回未确认 AI 建议、邮件正文、附件 URL、AI 原始 payload、display payload、confirmed payload 或来源通知原始 payload |
| `GET /api/reservation/tasks/{taskId}` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_TASK_READ`;按任务实际所属酒店校验访问权 | 保持登录 + `RESERVATION_TASK_READ` + 任务所属酒店访问权 | 只读查询默认不写业务审计 |
| `GET /api/reservation/workbench-items` | `FRONTEND_USER` | 已实现 M002 V4 CP5强制 Bearer 登录 + `RESERVATION_TASK_READ` + 酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 酒店访问权;统一返回 V4 业务订单任务和 S10/S99 来源通知摘要 | 只读查询默认不写业务审计;不得返回邮件正文、附件 URL、AI 原始 payload 或来源通知原始 payload同来源时间下使用 `updated_at` / `created_at` / 数字 ID 稳定排序 |
| `GET /api/reservation/order-tasks` | `FRONTEND_USER` | 已实现 M002 V4 CP5强制 Bearer 登录 + `RESERVATION_TASK_READ` + 酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 酒店访问权;只返回 V4 业务订单任务,不返回 S10/S99 来源通知 | 只读查询默认不写业务审计;不得返回 AI 原始 payload`card_status` 只匹配业务 / 可处理卡,固定来源邮件展示卡不参与筛选 |
| `GET /api/reservation/order-tasks/{orderTaskId}` | `FRONTEND_USER` | 已实现 M002 V4 CP5强制 Bearer 登录 + `RESERVATION_TASK_READ` + 订单任务所属酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 订单任务所属酒店访问权V4 任务详情页展示顺序为 Basic Information、业务卡、SourceMessage DisplayBasic Information 不返回 Agent `target_order`Room Information 展示模型只返回当前酒店本地订单投影、Agent 白名单字段和系统派生值Trace 卡只返回 `trace_items[].text``department_code``target_room_type_code``extra_bed_room_count` 等白名单字段,不返回 `content`;普通业务卡 `display_payload` / `confirmed_payload` 会移除 Agent `target_order`、邮件 HTML、raw evidence、附件原始 URL 和 PMS 原始响应等敏感字段;`fields[].write_target` 只返回前端安全语义不暴露内部列名Payment 卡可返回付款凭证附件安全摘要Payment 第一版 `attachment_ids[]` 只读展示,不支持前端增删或替换附件集合 | 只读查询默认不写业务审计本接口不得直接返回邮件正文、HTML 或附件 URL来源邮件卡正文和 Payment 图片预览 / 非图片下载必须通过 `GET /api/source-messages/{id}/conversation` 的 SourceMessage 原文权限链路读取Basic Information、Room Information 展示模型、Trace 卡和普通业务卡不得返回 PMS 原始响应、价格明细、AI 原始 payload、Agent 原始 `target_order``content`、raw evidence 或跨酒店订单值Payment 安全摘要只能包含 `attachment_id``file_name``content_type``size_bytes``is_image``preview_available``download_available`、可选 `external_media_id` / `unavailable_reason_code``external_media_id` 只用于前端匹配会话媒体对象,不是 URL不得返回 `ai_payload_json`;同批次 `adapter_contract_errors[]` 只返回白名单诊断字段;前端普通业务卡如遇 URL-like 附件字符串必须二次脱敏 |
| `GET /api/reservation/order-tasks/{orderTaskId}/audits` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_AUDIT_READ` + V4 订单任务所属酒店访问权 | 保持登录 + `RESERVATION_AUDIT_READ` + 订单任务所属酒店访问权;返回卡片确认、复核解阻和 `V4_ROOMING_LIST_AUTO_DEF` 自动 DEF 审计摘要 | 查询审计不再写审计返回快照必须脱敏不返回原始邮件正文、HTML、附件 URL、AI 原始 payload、token 或 secret |
| `GET /api/reservation/source-notifications/{notificationId}` | `FRONTEND_USER` | 已实现 M002 V4 CP5强制 Bearer 登录 + `RESERVATION_TASK_READ` + 来源通知所属酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 来源通知所属酒店访问权 | 只读查询默认不写业务审计;邮件正文和附件读取仍走 SourceMessage 原文权限;不得返回来源通知原始 payload 或附件 URL前端普通通知卡如遇 URL-like 附件字符串必须二次脱敏 |
| `GET /api/reservation/source-notifications/{notificationId}/audits` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_AUDIT_READ` + 来源通知所属酒店访问权 | 保持登录 + `RESERVATION_AUDIT_READ` + 来源通知所属酒店访问权;仅返回 S10/S99 来源通知 ack 审计摘要 | 查询审计不再写审计返回快照必须脱敏不返回原始邮件正文、HTML、附件 URL、AI 原始 payload、token 或 secret |
| `GET /api/reservation/lookups/accounts` | `FRONTEND_USER` | 已实现 M002 V4 CP11强制 Bearer 登录 + `RESERVATION_TASK_READ` + 酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 酒店访问权;只返回 Account code、显示名、派生 Market / Source 和目录安全元数据 | 只读查询默认不写业务审计;不得返回 PMS 原始响应、Secret 或外部同步错误详情 |
| `GET /api/reservation/lookups/room-types` | `FRONTEND_USER` | 已实现 M002 V4 CP11M002-V4-owner-rate-catalog-data-alignment 后固定初始化目录收敛为 6 个 OWNER RATE Room Type强制 Bearer 登录 + `RESERVATION_TASK_READ` + 酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 酒店访问权;只返回当前酒店可选 ACTIVE 房型目录快照 | 只读查询默认不写业务审计;不得返回 PMS 原始响应、价格敏感细节或跨酒店房型 |
| `GET /api/reservation/lookups/rate-codes` | `FRONTEND_USER` | 已实现 M002 V4 CP11M002-V4-owner-rate-catalog-data-alignment 后固定初始化目录收敛为 OWNER RATE 40 个规范化 Rate Code当前实现仍是酒店级目录 | 2026-07-21 结论是第一阶段继续保持登录 + `RESERVATION_TASK_READ` + 酒店访问权,并按当前酒店 `ACTIVE` Rate Code 目录返回;暂不强制 `account_code` + `booking_type=GROUP/FIT` 过滤,不做真实价格计算 | 只读查询默认不写业务审计;不得返回 PMS 原始响应、价格明细、Secret、跨酒店 Rate Plan未来如新增 Account 适用关系,也不得泄露其他 Account 的 Rate Code 适用关系 |
| `PUT /api/reservation/tasks/{taskId}/draft` | `FRONTEND_USER` | 第一版未全量强制登录actor 仍待迁移 | 登录 + `RESERVATION_TASK_EDIT` + 酒店访问权 | 写草稿审计可按业务需要记录 |
| `POST /api/reservation/tasks/{taskId}/confirm` | `FRONTEND_USER` | 第一版未全量强制登录actor 仍待迁移 | 登录 + `RESERVATION_TASK_CONFIRM` + 酒店访问权 | 必须写业务审计 |
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm` | `FRONTEND_USER` | 已实现 M002 V4 CP6/CP8/CP11强制 Bearer 登录 + `RESERVATION_TASK_CONFIRM` + 订单任务所属酒店访问权 + version 并发校验 + 当前酒店数据库目录校验 | 保持Basic Information 前置确认,确认后卡片锁定,不返回 AI 原始 payloadRooming List 卡确认只表示事项已人工处理不新增名单解析、附件预览、Excel 生成或 PMS 导入权限Payment 第一版确认只提交 `version` 和必要审计说明,不提交 `attachment_ids[]`、附件 URL 或完整附件对象;同订单为 Group 时确认 Rooming List 已自动把可更新 Room Information 确认快照中的 Group Booking Status 置为 `DEF`没有可更新投影时不创建不完整事实Basic Account、Room Type、Rate Code 目录错误返回 `V4_FIELD_VALIDATION_FAILED`Rate Code 第一阶段只校验当前酒店 `ACTIVE` 目录存在,暂不校验 Account 适用关系 | 必须写业务审计actor 使用当前登录用户Rooming List 触发的 Group Booking Status 自动变更或跳过都必须记录 `V4_ROOMING_LIST_AUTO_DEF` 安全摘要 |
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution` | `FRONTEND_USER` | 已实现 M002 V4 CP7/CP8/CP11强制 Bearer 登录 + `RESERVATION_MANUAL_REVIEW_RESOLVE` + 订单任务所属酒店访问权 + version 并发校验 + 当前酒店数据库目录校验 | 保持;仅用于 V4 `REVIEW_REQUIRED` 卡,不开放普通任务任意切换订单;字段指针只允许当前卡 `fields[]` 白名单内可编辑业务字段不允许提交来源邮件、路由、Agent 原始定位、诊断、`manual_review`、附件 URL 或 AI 原始 payload订单归属未解决时必须提交当前酒店下真实可见订单 ID`RESOLVED` 的订单任务不得换绑不同订单 | 必须写业务审计,记录复核字段指针、复核说明和订单归属确认摘要;不返回或写入 AI 原始 payload |
| `POST /api/reservation/source-notifications/{notificationId}/ack` | `FRONTEND_USER` | 已实现 M002 V4 CP6强制 Bearer 登录 + `RESERVATION_TASK_CONFIRM` + 来源通知所属酒店访问权 + version 并发校验 | 保持;只用于 `route_code=S10/S99` 的 V4 来源通知确认已读 / 已处理,不创建订单、不参与订单阻塞;重复 ack 幂等返回当前状态且不新增审计 | 首次确认必须写业务审计,记录已读 / 已处理确认actor 使用当前登录用户 |
| `POST /api/reservation/tasks/{taskId}/manual-review-conversions` | `FRONTEND_USER` | 第一版已写业务审计,但 actor 待迁移 | 登录 + `RESERVATION_MANUAL_REVIEW_RESOLVE` + 酒店访问权 | 必须写业务审计和原因 |
| `POST /api/reservation/tasks/{taskId}/manual-review-resolutions` | `FRONTEND_USER` | 第一版已写业务审计,但 actor 待迁移 | 登录 + `RESERVATION_MANUAL_REVIEW_RESOLVE` + 酒店访问权 | 必须写业务审计 |
| `POST /api/reservation/tasks/{taskId}/opera-operations/{operationId}/execute` | `FRONTEND_USER` | 当前为 OPERA 模拟 | 登录 + `RESERVATION_OPERA_SIM_EXECUTE` + 酒店访问权 | 必须写业务审计和 attempt |
| `POST /api/reservation/tasks/{taskId}/opera-operations/{operationId}/retry` | `FRONTEND_USER` | 当前为 OPERA 模拟 | 登录 + `RESERVATION_OPERA_SIM_EXECUTE` + 酒店访问权 | 必须写业务审计和 attempt |
| `GET /api/reservation/tasks/{taskId}/audits` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_AUDIT_READ`;按任务实际所属酒店校验访问权 | 保持登录 + `RESERVATION_AUDIT_READ` + 酒店访问权 | 查询审计不再写审计 |
| `POST /api/reservation/invoices/manual-generations` | `FRONTEND_USER` | 已实现 M009 CP2强制 Bearer 登录 + `RESERVATION_INVOICE_GENERATE` + 酒店访问权;`task_id` / `order_id` 可为空,传入时反查对象所属酒店 | 保持登录 + `RESERVATION_INVOICE_GENERATE` + 酒店访问权;后续如增加历史列表或预填接口需单独登记权限 | 写业务审计,记录来源类型、模板版本、生成结果摘要;生成失败写入生成记录安全错误摘要 |
| `POST /api/reservation/rooming-lists/generations` | `FRONTEND_USER` | 已实现 M010 CP1 / CP2 / CP3CP3 兼容第二种 `英文姓` + `英文名` 名单样式multipart 上传来源名单并直接下载 `.xlsx`;已在 multipart 参数绑定前前置校验登录和生成权限 | 登录 + `RESERVATION_ROOMING_LIST_GENERATE` + 酒店访问权;第一种来源样式后端从来源 Excel `旅游日期` 派生 Arrival / Departure第二种来源样式由用户提交 Arrival / DepartureAdults 按分房结果计算,目标默认值区域只保留 Payment Type / NationalityPayment Type 默认 `BTQR` 且仅允许 `BTQR` / `CA`;第一版仍不落库、不上传 OSS | CP1 / CP2 / CP3 不落生成记录表;错误响应不得记录完整名单、证件信息、源文件内容或生成文件内容;第二种样式不得回显中文名、护照号、生日、签发地等来源证件字段;后续若增加历史记录再补业务审计 |
### 3.2.1 V4 工作台、订单详情和任务详情页展示层技术信息边界
2026-07-21 已确认:`/reservation/tasks``/reservation/orders/{orderId}``/reservation/order-tasks/{orderTaskId}` 默认是普通酒店员工使用的预订事项工作台、订单总览页和订单事项办理页,不是开发 / 测试调试页。`GET /api/reservation/workbench-items``GET /api/reservation/order-tasks``GET /api/reservation/orders/{orderId}``GET /api/reservation/order-tasks/{orderTaskId}` 为了路由、筛选、并发、提交和排查可以返回 `item_type``order_task_status``card_status``order_id``order_task_id``card_id``source_message_id``version``fields[]``write_target``availability` 等稳定技术字段,但前端普通业务页面不得把这些字段作为主标题、默认筛选文案、顶部摘要、订单总览或业务事项正文直接展示。
展示规则:
- 默认主信息层级使用业务文案,例如“待处理预订事项”“预订事项”“订单总览”“当前确认快照”“下一步处理”“关联来源邮件”“处理记录”“处理预订事项”“预订基础信息”“房型与日期”“付款凭证”“跟进事项”“房表事项”“来源邮件”。
- 普通筛选使用“全部”“待处理”“需要复核”“已完成”“来源通知”等业务文案;`item_type``order_task_status``card_status``route_code``system_process_category` 等技术筛选只能放在高级筛选或受控调试模式。
- 技术 ID、JSON Pointer、payload 字段名、adapter 诊断、内部状态码和模型名只能用于内部逻辑;确需给开发 / 测试排查时,放在折叠区、高级筛选或受控调试模式。
- 技术折叠区或调试模式仍不得展示邮件正文、HTML、附件 URL、AI 原始 payload、raw evidence、PMS 原始响应、Secret、Token、外部签名 URL 或跨酒店数据。
- 如果后续需要单独的 Debug 视图或更完整的技术诊断页,应按 `FRONTEND_DEBUG` 分类、环境开关、专门权限和调试审计重新登记,不能把普通业务页变成调试页。
### 3.3 来源邮件接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `GET /api/source-messages` | `FRONTEND_USER` | 已强制 Bearer 登录 + `SOURCE_MESSAGE_READ`;列表条件中的酒店按当前用户可访问酒店校验 | 保持登录 + `SOURCE_MESSAGE_READ` + 酒店访问权 | 只读摘要不写审计 |
| `GET /api/source-messages/{id}` | `FRONTEND_USER` | 已强制 Bearer 登录 + `SOURCE_MESSAGE_READ`;按消息实际所属酒店校验访问权 | 保持登录 + `SOURCE_MESSAGE_READ` + 消息所属酒店访问权 | 只读摘要不写审计 |
| `GET /api/source-messages/{id}/conversation` | `FRONTEND_USER` | 已强制 Bearer 登录 + `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ`;按消息实际所属酒店校验访问权;返回会话完整 text/html 和媒体 URL | 保持登录 + `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ` + 消息所属酒店访问权V4 任务详情页来源邮件卡读取正文、Payment 图片大图预览和非图片下载都必须走本接口,并且只使用当前触发该 order task 的 SourceMessage 内容和被 Payment `attachment_ids[]` 引用的附件Payment 摘要匹配不得使用跨酒店 SourceMessage 或本系统内部媒体 row ID | 必须写原文读取审计actor 使用当前登录用户稳定 ID前端展示 HTML 优先使用 `html_body_sanitized`;用户触发 Payment 图片预览或非图片下载时DOM `img[src]` / `a[href]` 可以临时持有本接口返回的受权限附件 URL前端不得把附件 `externalUrl` 写入确认 payload、日志、错误上报、URL query 或 localStorage也不得作为页面可见文本展示 |
| `GET /api/source-messages/{id}/original` | `FRONTEND_USER` | 已强制 Bearer 登录 + `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ`;按消息实际所属酒店校验访问权;不再使用原文读取 access key | 保持登录 + `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ` + 消息所属酒店访问权 | 必须写原文读取审计actor 使用当前登录用户稳定 ID |
### 3.4 系统管理后台接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `/api/admin/users/**` | `FRONTEND_ADMIN` | 已强制登录和 `SYSTEM_USER_MANAGE` | 保持;禁用用户撤销 session | 写操作必须记录 `platform_admin_audit_log` |
| `/api/admin/roles/**` | `FRONTEND_ADMIN` | 已强制登录和 `SYSTEM_ROLE_MANAGE` | 保持;内置角色只读 | 写操作必须记录管理审计 |
| `/api/admin/permissions` | `FRONTEND_ADMIN` | 已强制登录和 `SYSTEM_ROLE_MANAGE` | 保持只读;前端不能自造权限码 | 不需要写审计 |
| `/api/admin/menus/**` | `FRONTEND_ADMIN` | 已强制登录和 `SYSTEM_MENU_MANAGE``GET /tree``PUT /tree-order` 已沿用该权限 | 保持;菜单可见性不替代后端权限;批量树排序只允许修改 `parent_id``sort_order``sort_order` 为空时按请求顺序生成稳定排序 | 写操作必须记录管理审计,树排序审计记录调整前后的父级和排序;树查询不写审计 |
| `/api/admin/hotels/**` | `FRONTEND_ADMIN` | 已强制登录和 `HOTEL_MANAGE` | 保持;单酒店阶段只能一家 `ACTIVE` | 写操作必须记录管理审计 |
| `/api/admin/reservation/catalogs/**` | `FRONTEND_ADMIN` | 已实现目录管理后台 CP1前端入口为 `/system/reservation-catalogs`;强制登录、`RESERVATION_CATALOG_MANAGE` 和目标酒店访问权 | 保持;第一版只开放 Account、Room Type、Rate Code 列表、新增、启用 / 停用Market / Source 独立管理和真实 PMS 同步后置;停用目录不再进入普通 lookup | 新增和状态实际变化必须记录管理审计;重复提交相同状态按幂等返回,不新增审计;列表查询不写审计;不得返回 PMS 原始响应、Secret 或外部同步错误详情 |
| `GET /api/admin/audits` | `FRONTEND_ADMIN` | 已强制登录和 `SYSTEM_ADMIN_CONSOLE_ACCESS` | 保持;不返回 Secret、密码或 token | 查询审计不再写审计 |
### 3.5 调试和系统接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `POST /api/system/debug/eml-superagent-runs` | `FRONTEND_DEBUG` | 环境开关 + `X-TH-Hotel-Debug-Upload-Key` | dev/test 可保留 access key长期目标为登录 + `SYSTEM_DEBUG_EML_RUN` + 环境开关 | 写 Debug run必要时补管理 / 调试审计 |
| `GET /api/system/debug/eml-superagent-runs/{runId}` | `FRONTEND_DEBUG` | 环境开关 + access key | 登录 + `SYSTEM_DEBUG_EML_RUN`;避免向普通用户暴露 AI 原始结果 | 只读调试可记录访问日志 |
| `POST /api/system/debug/eml-superagent-runs/stream` | `FRONTEND_DEBUG` | 环境开关 + access key | 登录 + `SYSTEM_DEBUG_EML_RUN`;生产默认关闭 | 写 Debug run 和安全错误摘要 |
| `POST /api/system/document-conversions/excel-to-pdf` | `FRONTEND_DEBUG` | 环境开关 + `X-TH-Hotel-Document-Conversion-Key`;只支持 `.xls` / `.xlsx`PDF 输出到 OSS | 长期目标为登录 + 文件转换调试权限 + 环境开关;生产默认关闭 | CP2 不落库;必要时通过网关访问日志和 OSS 对象路径追踪,后续自动转换任务落库后补转换审计 |
| `GET /api/system/agentbus-probe` | `FRONTEND_DEBUG` | 当前系统状态接口 | 登录 + `SYSTEM_AGENTBUS_PROBE_READ` 或系统管理入口权限 | 不返回 Token、raw frame 或邮件正文 |
| `POST /api/system/reservation/demo-data` | `FRONTEND_DEBUG` | 环境开关 + demo access key | dev/test 使用;生产必须关闭 | 写入演示数据时建议记录调试审计 |
### 3.6 第三方机器接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `POST /api/ai-query/v1/case-context` | `THIRD_PARTY_SUPERAGENT` | HMAC 鉴权 | 保持 HMAC不使用用户 Bearer token | 记录请求 ID、client_id 和安全错误 |
| `POST /api/ai-query/v1/object-detail` | `THIRD_PARTY_SUPERAGENT` | HMAC 鉴权 | 保持 HMAC返回最小必要上下文 | 记录请求 ID、client_id 和安全错误 |
| `POST /api/ai-query/v1/conversation-tasks` | `THIRD_PARTY_SUPERAGENT` | HMAC 鉴权 | 保持 HMAC不返回邮件原文 | 记录请求 ID、client_id 和安全错误 |
| `POST /api/ai-query/v1/conversation-source` | `THIRD_PARTY_SUPERAGENT` | HMAC 鉴权 | 保持 HMAC只按契约返回需要字段 | 记录请求 ID、client_id 和安全错误 |
| `POST /api/integrations/superagent/task-results` | `THIRD_PARTY_SUPERAGENT` | HMAC + nonce + timestamp + body hash | 保持V4 / V3 / V2 共存期均必须用外部 `source_message_id` 匹配 Inbox技术契约错误只落 adapter error不创建用户可处理任务V4 普通业务包只写 V4 订单任务 / 多卡模型,不再创建旧 `workflow_reservation_task`V4 S10/S99 写入来源通知且不创建旧任务 | 记录 batch、transition、adapter error、幂等结果和安全错误 |
| `/mcp` | `THIRD_PARTY_MCP` | Bearer Token提交工具可独立开关`th_hotel_submit_task_results` 已收口为 M002 V4-only旧 V2/V3 submit payload 返回 `MCP_SUBMIT_V4_REQUIRED` | 保持工具级能力限制不暴露无关接口MCP 写入工具不走用户权限码、不接受前端调用、不作为 REST 历史兼容入口 | 记录工具调用结果、业务入站结果和受控 MCP 入站诊断;诊断原文不进入普通前端接口或普通日志 |
| AgentBus WebSocket | `THIRD_PARTY_AGENTBUS` | AgentBus Token + capture 开关 | 保持;只入 SourceMessage不直接建业务任务 | 记录 SourceMessage、payload hash 和 dispatch run |
### 3.7 后端内部能力
| 能力 | 分类 | 暴露规则 | 审计 / 追踪 |
| --- | --- | --- | --- |
| Repository / Mapper / Entity | `INTERNAL_ONLY` | 不对 Controller、前端或第三方直接暴露 | 通过 Service 写审计 |
| SuperAgent Open API Client | `INTERNAL_ONLY` | 只能后端 Adapter 使用Secret 不出后端 | 通过 debug run 或 dispatch run 追踪 |
| OSS Adapter | `INTERNAL_ONLY` | 前端只能拿后端返回的安全 URL不能拿 OSS Secret | 上传和读取入口记录安全摘要 |
| AgentBus dispatch worker | `INTERNAL_ONLY` | 只由后端调度或受控管理入口触发 | `platform_superagent_dispatch_run` |
| Booking Excel 附件预处理 | `INTERNAL_ONLY` | M011 CP1 / CP2 / CP3 已接入 Debug EML 与 AgentBus dispatch测试机 AgentBus 增强已开启;只允许后端在调用 SuperAgent 前通过 Service / Port 使用,不单独暴露给前端或第三方 | 记录安全 warning、附件名、hash 前缀、sheet 名、行号和高亮业务行摘要;不得记录完整 Excel、完整附件 URL、签名参数、API Key、Cookie、Secret 或名单类客户敏感原文 |
| Flyway / bootstrap 初始化 | `INTERNAL_ONLY` | 不提供运行时外部接口 | 通过部署记录和数据库 history 追踪 |
| 未来 OPERA / OHIP Adapter | `INTERNAL_ONLY` | 浏览器不得直接调用;只能业务服务触发 | 必须记录操作、attempt 和外部结果摘要 |
## 4. 权限码规划口径
当前管理后台权限码已经落地。业务接口收口时建议新增或确认以下权限码,不要求一次性全部实现:
| 权限码 | 中文含义 | 适用接口 |
| --- | --- | --- |
| `RESERVATION_ORDER_READ` | 查看订单列表和订单详情 | 订单列表、订单详情 |
| `RESERVATION_TASK_READ` | 查看任务列表和任务详情 | 任务列表、任务详情 |
| `RESERVATION_TASK_EDIT` | 保存任务草稿或编辑可写字段 | 草稿保存 |
| `RESERVATION_TASK_CONFIRM` | 最终确认任务 | 任务确认 |
| `RESERVATION_MANUAL_REVIEW_RESOLVE` | 处理人工复核和 Fallback 转换 | 复核解阻、Fallback 转换 |
| `RESERVATION_OPERA_SIM_EXECUTE` | 执行或重试 OPERA 模拟 / 未来真实操作 | OPERA execute / retry |
| `RESERVATION_AUDIT_READ` | 查看业务审计流水 | 旧任务审计列表、V4 订单任务审计列表、V4 来源通知 ack 审计列表 |
| `RESERVATION_INVOICE_GENERATE` | 生成 Reservation Proforma Invoice | Manual Invoice 生成、未来任务 / 订单预填生成 |
| `RESERVATION_ROOMING_LIST_GENERATE` | 生成 Reservation Rooming List Excel | Rooming List 上传名单并生成 `.xlsx` 下载 |
| `RESERVATION_CATALOG_MANAGE` | 维护 Reservation 受控目录 | 已用于 `/api/admin/reservation/catalogs/**`;第一版支持 Account、Room Type、Rate Code 管理Market / Source 独立管理后置 |
| `SOURCE_MESSAGE_READ` | 查看来源邮件安全摘要 | SourceMessage 列表、详情、会话摘要 |
| `SOURCE_MESSAGE_ORIGINAL_READ` | 查看邮件正文、HTML 和附件外链 | original / conversation 完整正文;必须叠加 `SOURCE_MESSAGE_READ` 使用 |
| `SYSTEM_DEBUG_EML_RUN` | 使用 Debug EML 调试链路 | Debug EML 上传、查询、stream |
| `SYSTEM_AGENTBUS_PROBE_READ` | 查看 AgentBus 安全状态 | AgentBus probe |
如果新增权限码,必须同步:
1. `PlatformPermissionCode` 枚举。
2. 内置角色权限矩阵。
3. `docs/project/security-access-control-boundary.md`
4. 前后端协作文档中对应页面按钮或菜单说明。
### 4.1 新增接口权限固定流程
后续新增需要前端用户或管理员调用的接口时,必须按同一套流程维护权限,避免“接口能调用但系统设置里管不了”或“前端隐藏了但后端没拦”的不一致。
固定流程:
1. **确认接口分类。** 先判断接口属于 `FRONTEND_USER``FRONTEND_ADMIN``FRONTEND_DEBUG`、第三方机器接口还是 `INTERNAL_ONLY`。只有前端用户和管理员接口进入用户角色权限模型SuperAgent、AgentBus、MCP 继续使用机器鉴权,不使用用户 Bearer 权限码。
2. **定义稳定权限码。**`PlatformPermissionCode` 增加稳定英文权限码,例如 `RESERVATION_TASK_ASSIGN`。权限码只表达能力边界,不绑定中文文案、不绑定某个按钮样式。
3. **补启动同步元数据。** 在权限启动同步逻辑中补权限名称、权限分组和状态,确保 `platform_permission` 能自动拥有该权限码。
4. **补内置角色默认矩阵。** 明确 `SYSTEM_ADMIN`、业务操作员、只读角色等内置角色是否默认拥有该权限。内置角色矩阵仍以代码为准;自定义角色后续通过系统设置页面分配。
5. **后端接口强制校验。** 在 Controller 或统一入口中显式调用对应鉴权服务,例如 `requirePermission(PlatformPermissionCode.X.name())`。只读接口同时校验对象所属酒店;写接口还要校验状态、幂等、事务和审计。
6. **前端类型和交互同步。** 在前端权限类型中加入新权限码,路由、菜单、按钮和操作入口按 `/api/auth/me` 返回的 `permissions[]` 控制展示。前端控制只提升体验,不能替代后端权限校验。
7. **系统设置可分配。** 权限启动同步后,系统设置的角色权限页面应能看到该权限码;需要给自定义角色授权时,通过系统设置勾选,用户重新登录或刷新上下文后生效。
8. **补测试。** 至少覆盖无 token、无权限、有权限、跨酒店或对象归属校验。第三方接口要补“不被用户登录拦截误伤”的回归测试。
9. **补文档。** 本文矩阵中登记接口分类、权限码、酒店隔离和审计要求;影响前端时同步 `docs/project/frontend-backend/backend-to-frontend-notes.md`;影响 SuperAgent / MCP / AgentBus 时同步对应集成契约。
最小验收口径:
- 新接口没有 token 时返回该分类约定的 401。
- 已登录但缺权限时返回该分类约定的 403。
- 有权限但访问无权酒店或无权对象时返回酒店 / 对象访问拒绝。
- 权限码能在系统设置角色权限页面看到并分配给自定义角色。
- 前端只做路由、菜单、按钮显示控制,后端仍能拦截直接调用。
- 第三方机器接口不被用户 Bearer 权限模型误拦截。
## 5. 酒店隔离规则
- 前端用户接口必须从当前登录用户解析可访问酒店集合。
- 显式传入 `hotel_id` 时,后端必须校验该用户是否可访问该酒店。
- 未传 `hotel_id` 时,单酒店阶段可按用户默认酒店或系统唯一 `ACTIVE` 酒店解析。
- 直接按 `taskId``orderId``sourceMessageId`、V4 `orderTaskId` 或 V4 `notificationId` 定位的接口,必须反查对象所属 `hotel_id` 并校验访问权;当前已覆盖 Reservation 订单详情、任务详情、任务审计列表、V4 订单任务详情 / 审计、V4 来源通知详情 / 审计和 SourceMessage 摘要详情。
- 第三方 SuperAgent 接口第一版不依赖用户酒店权限,但必须使用系统酒店解析 SourceMessage并防止跨酒店误匹配。
- AgentBus 入站不接受外部随意指定酒店;单酒店阶段由系统唯一 `ACTIVE` 酒店解析。
## 6. 审计分层
| 审计类型 | 当前载体 | 必须记录的动作 |
| --- | --- | --- |
| 管理审计 | `platform_admin_audit_log` | 用户、角色、权限、菜单、酒店的写操作 |
| 业务审计 | `workflow_reservation_audit_log` | 任务确认、人工复核、订单归属确认、V4 来源通知 ack、Rooming List 触发 Group Booking Status 自动 DEF、OPERA 执行 / 重试 |
| 邮件原文读取审计 | `platform_source_message_original_access_audit` | 读取邮件正文、HTML、附件外链、Payment 图片预览和非图片下载 |
| SuperAgent 入站追踪 | `workflow_reservation_ai_batch``workflow_reservation_ai_transition` | task-results / MCP 提交、路由、adapter error |
| SuperAgent MCP 入站诊断 | `platform_superagent_mcp_call_diagnostic` | MCP 原始工具参数、submit adapter 后 payload、空 mapping diagnostics 和安全错误摘要;不保存完整查询 tool 响应V4-only 后旧 V3 事件索引映射已废弃 |
| AgentBus 分发追踪 | `platform_superagent_dispatch_run` | SourceMessage 自动分发 SuperAgent、重试、失败摘要 |
| 安全审计 | 后续可新增平台安全审计表 | 登录失败、签名失败、nonce 重放、越权访问 |
业务侧后续收口重点:
- 业务写操作 actor 从本地占位迁移到当前登录用户。
- 第三方入站 actor 保持机器身份,例如 `SUPERAGENT``MCP``AGENTBUS`
- 审计快照不得写入密码、token、secret、完整邮件正文、附件签名 URL 或支付敏感信息。
## 7. 接口变更同步规则
新增或修改任何 Controller、第三方入口、调试入口或后台 worker 触发入口时,必须先回答:
1. 这个接口给谁调用:前端用户、管理员、第三方系统,还是内部 worker
2. 是否需要登录?如果需要,权限码是什么?
3. 是否涉及 `hotel_id`?如何校验用户可访问酒店?
4. 是否返回敏感数据正文、HTML、附件 URL、AI 原始 payload、trace、Secret
5. 是否是写操作写什么审计actor 从哪里来?
6. 是否生产允许?是否需要环境开关?
7. 是否影响 SuperAgent、MCP、AgentBus 或前端契约?
如果任一答案为“是”,必须同步更新以下文档中相关部分:
- 本文档。
- `AGENTS.md``docs/project/backend-development-guidelines.md` 中的开发规则,如果新增了通用规范。
- `docs/project/frontend-backend/backend-to-frontend-notes.md`,如果影响前端。
- `docs/project/integrations/superagent-api-contract.md` 或 MCP / AgentBus 集成文档,如果影响第三方。
- 对应需求文档,例如 M002、M004、M006、M007。
## 8. 建议实施顺序
后续开发权限收口时建议按以下顺序推进:
1. 已完成 CP1Reservation / SourceMessage 第一批只读查询接口已收口登录、权限码和酒店访问权包括任务列表、订单列表、订单详情、任务详情、任务审计列表、V4 订单任务审计列表、V4 来源通知审计列表、SourceMessage 摘要列表和摘要详情。
2. 已完成 CP2邮件原文和会话完整正文读取已迁移到 `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ`,并按消息所属酒店校验访问权;原文读取审计 actor 使用当前登录用户稳定 ID。
3. 再收口 Reservation 写操作草稿、确认、人工复核、OPERA 模拟。
4. 迁移业务审计 actor 到当前登录用户。
5. 最后处理 Debug、Demo、Replay、AgentBus Probe 等系统调试入口。
每一步都应保持第三方机器接口不被误拦截SuperAgent / MCP / AgentBus 继续使用机器鉴权。