Files
Wyndham-RSVN-0918/docs/project/security-access-control-boundary.md
T
鲨鱼辣椒 f4aa01e1f9
verify / booking-verify (push) Has been cancelled
完善Proposal配额处理、失败收尾及工作台历史功能
补齐C1正文资料交付和C2配额分类规则,完善Proposal人工任务、固定图片过滤及邮件附件展示。
修正失败终态与恢复上限,增加关闭状态的通知组件,永久保留处理历史并完善筛选分页。
同步相关页面修复、迁移、测试和项目记录。

验证:后台复用同源码clean verify结果1155通过/10条件跳过;前端262项及生产构建通过;敏感资料和提交路径检查通过。
2026-09-10 17:01:39 +08:00

387 lines
63 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 接口暴露、权限与审计边界
## 2026-09-10 C1正文关联接收边界(待统一加载)
沿用受控Parsing Provider接收与INTERNAL_ONLY Layer3交付,无新增HTTP、权限或业务写入口。body_binding仅接受同一正文目标、Current正文证据及日期/房型层级,不能冒用Parser目标。正文原值和关联仍为有来源的候选/中立资料,不改变业务状态;旧结果兼容,样本原文仅留本机忽略目录,配置包不包含真实邮件。见[专项证据](../../.project-docs/50-evidence/topics/2026-09-10-c1-body-booking-amend-handoff-fix.md)。
## 2026-09-10 普通邮件返回导航与版本材料边界
普通卡复用既有来源返回参数,不接受任意返回URL;裸链接仅回站内待处理列表。原权限、酒店及确切来源匹配保持,缺失任务版本不会以当前会话替代。仅准确显示失败状态,接口/鉴权及读取内容边界不变;见[证据](../../.project-docs/50-evidence/topics/2026-09-10-ordinary-conversation-return.md)。
## 2026-09-10 工作台历史匹配提示的只读刷新
普通待办理Group投影卡为核实ORDER_UNASSIGNED,复用已有binding-preview及RESERVATION_TASK_CONFIRM权限,不扩大接口/权限/数据返回。请求和响应按当前任务、卡、酒店、路径、团号及版本隔离,迟到/失败/冲突不能清除旧提示或更改办理权限。已有本地测试未单选酒店时沿用后端已授权详情;存在已选酒店时必须一致,未改变任何鉴权配置。真实确认和后台全部校验仍独立执行。见[证据](../../.project-docs/50-evidence/topics/2026-09-10-ordinary-card-confirm-fix.md)。
## 2026-09-10 工作台附件列表目标图过滤
受保护workbench-images只读响应增加filtered_attachment_ids,为同邮件内唯一且确认匹配的下载身份。沿用SOURCE_MESSAGE_READ + SOURCE_MESSAGE_ORIGINAL_READ、酒店校验和原文审计;不新增端点、权限、图片/指纹/底层地址返回或持久化。只用于工作台附件展示;原件、完整会话、来源材料和Agent输入不变。失败、错源、权限变化、身份不明及旧字段均保留。用户指定统一加载后生效。
## 2026-09-10 Proposal会话原表显示
从已存在的任务来源上下文复用既有source-material接口,要求SOURCE_MESSAGE_READ及SOURCE_MESSAGE_ORIGINAL_READ,服务端仍校验酒店与确切材料版本并记录原文读取审计。只有接口提供Proposal专属body_html_raw且来源ID匹配当前消息时,才经既有Proposal文本/表格/引用白名单净化显示;不执行会话html_body或把兼容的html_body_sanitized纯文当HTML。脚本/事件/外部资源/链接目的地及任意定位样式不进入DOM,不展示其他消息的任务材料。缺失、无权、来源不符均退回已有纯文本,任务/酒店变化丢弃旧响应。没有新增端点、权限或业务写入;见[验证](../../.project-docs/50-evidence/topics/2026-09-10-proposal-conversation-format.md)。
## 2026-09-10 Proposal邮件页返回入口
仅前端链接补齐,明确的来源订单任务/卡片身份用于构造固定站内路由,category/search沿用既有列表校验;缺失、重复或非法身份不产生返回链接。没有任意URL跳转、业务写入或新增接口,导航提示不作为授权,任务详情仍按原路由和服务端权限及酒店范围读取。邮件原文与附件权限/审计保持,见[验证](../../.project-docs/50-evidence/topics/2026-09-10-proposal-conversation-return.md)。
## 2026-09-10 回放历史永久保留修订
[历史保留CR](requirements/CR-20260910-replay-history-permanent-retention.md)明确取消本模块旧7天和关联处理证据3个月期限;下文历史描述中的期限门槛已由本节修订。列表新增近三个月/全部历史、has_next分页和处理结果展示,详情/阶段/公开Journal使用既有登录、SYSTEM_DEBUG_EML_RUN、酒店及来源/运行关联与访问审计,不新增敏感字段或外部发送。期限NULL表示永久保留,移除定时日志清理;权限不因记录变旧而放宽。统一加载前实际后台仍为旧行为,状态以工作记录为准。
## 2026-09-09 Proposal保存与Layer6失败归类修复
V19只扩展现有候选任务表的业务类型约束;复用原API、权限、酒店、来源及人工办理边界。Layer6数据完整性失败使用`BOOKING_LAYER6_PERSISTENCE_FAILED`及固定中文说明,暂时内部失败/其他系统失败保持现有恢复与终态行为;不将原SQL、异常正文、邮件或Secret带入错误响应,不新增通知发送或恢复接口。详见[修复及实际验证](../../.project-docs/50-evidence/topics/2026-09-09-proposal-allotment-real-replay-save-failure.md)。
## 2026-09-09 任务列表已保存团号
既有任务列表增加可空tour_code,只投影当前有权读取任务的已保存业务团号;沿用原任务读取权限、酒店和列表范围。不新增端点、原邮件读取、权限或持久化动作,不以FIT姓名或内部目标编号替代团号。前端空值留空,不自行从标题、正文或其他身份猜补。见[列表对接](frontend-backend/backend-to-frontend-notes.md)与[验证](../../.project-docs/50-evidence/topics/2026-09-09-workbench-saved-tour-code.md)。
## 2026-09-09 失败提醒CP1出站边界
独立通知属于`INTERNAL_ONLY`,没有新增HTTP Controller、员工按钮或匿名入口。内部登记只接受明确最终技术失败、稳定酒店/处理身份和固定原因枚举;开放业务事务内禁止登记/发送。内部查询和恢复均校验hotel_id;恢复仅限配置暂停/可重试耗尽,已受理及不确定结果不可普通重发。通知模块不拥有邮件重跑、Agent、工作台保存或PMS调用能力。
Token只从Git忽略的私有文件读取,不进入公共Spring环境、持久记录、日志、toString或前端。只允许声明的四个配置键;URL为无userinfo/query/fragment的HTTPS,x-token原样放出站头,ID严格字符串9998;请求仅id/content。HTTP禁止重定向/正文重放,响应与等待有上限,外部正文和异常message不进入日志/表。来源标题为用户授权出站摘要,清理控制字符并限长,禁止邮件正文/附件URL/原始Agent回答进入提醒。
发送使用专属daemon线程及已提交SENDING租约,异常不向原业务传播。CP1默认关闭、无历史扫描/实际发送/运行切换;前层触发与真实联调待CP2。见[交接](integrations/wechat-failure-notification-cp1.md)及[验证](../../.project-docs/50-evidence/topics/2026-09-09-failure-notification-cp1.md)。
## 2026-09-09 Proposal正式页面消费边界
用户样式确认后已连接并加载5178。body_html_raw经惰性模板解析及文本/表格白名单净化后显示,不复制执行内容、远程资源、链接目的地或任意样式。读取材料遵守既有原文权限和酒店范围;完成仅UUID/版本,失败重试沿用UUID;忽略复用现有动作。保存结果核对任务/卡片/邮件/酒店/终态,失败不移出队列。正式原邮件沿用会话入口,附件只使用已有下载身份。5190私有样例及模拟处理器未带入正式页面,未办理真实任务。见[发布与验收](../../.project-docs/50-evidence/topics/2026-09-09-proposal-allotment-workbench-release.md)。
## 2026-09-09 Proposal确切来源HTML补充
Proposal任务的既有source-material JSON响应增加body_html_raw。仍要求SOURCE_MESSAGE_ORIGINAL_READ和酒店访问权,使用任务回执的材料类型/ID/hash及邮件ID读取确切原始或重复投递载荷,记录既有原文读取审计;不从当前Inbox或最新其他版本取HTML。返回未经净化的原HTML,调用方必须先净化为允许的表格与文本,不执行脚本/事件,不加载外部资源。不存在可用HTML时返回null,既有纯文本/附件继续可读。普通预订/通知不新增HTML能力,不新增端点、权限或原件下载功能。详见[批准补充](requirements/CR-20260909-proposal-exact-source-html.md)与[渲染对接](frontend-backend/proposal-allotment-handoff.md)。
## 2026-09-09 Proposal Allotment独立预览边界
仅独立工作区的proposal-preview模式启用本机5190模拟请求,所有API本地处理且真实代理关闭,其他请求返回405;不连接数据库或修改真实任务。真实EML只存放在Git忽略的私有材料目录;安全展示去除执行标签、事件及远程资源,保留原表格单元格;原EML受限于两个明确样例的来源身份下载。页面展示适配不是正式API授权或状态约定。用户确认样式后,真实操作必须按A的权限、状态、版本及成功/失败说明连接;不将演示路由替换、工具条、请求处理器、私有数据或环境配置带入5178。见[需求](requirements/CR-20260909-proposal-allotment-workbench-preview.md)。
## 2026-09-09 Proposal Allotment 人工完成
不新增端点或权限。沿用任务读取、来源材料/附件读取权限及酒店范围;confirm继续使用RESERVATION_TASK_CONFIRM、卡片版本与operation_id。PROPOSAL_ALLOTMENT来源必须属于当次邮件和酒店、引用必须有输入出处;任务不要求普通预订身份。完成动作拒绝confirmed_payload、basic_information、proposed_tour_code、expected_binding_version等编辑/绑定字段,且拒绝走review-resolution;只保存任务CONFIRMED/COMPLETED、办理人/时间、审计V4_PROPOSAL_ALLOTMENT_COMPLETE和PROPOSAL_COMPLETE回执,不写普通订单、确认预订、Basic、配额或关联业务。完整原文沿用受保护材料接口,不复制到审计。见[对接说明](frontend-backend/proposal-allotment-handoff.md)。
## 2026-09-09 固定邮件文字出站精简
QBD/LianTai 用户批准的两套固定提醒及签名在 Parsing / Booking compact 外发副本中排除;Parsing evidence quote 同步排除。canonical current/history、来源原件、内部hash与原文权限/审计不变,不增加API、页面、权限或持久化。目录只保存非敏感起点、规范文本长度和SHA-256,不保存真实联系人明文;六封用户样本仅显式指定本地路径离线读取,失败断言只打印计数/布尔,不把原邮件内容加入仓库或普通日志。图片与附件选择沿用原规则;本次不新增图片出站字段或读取图片内容。详见[需求](requirements/CR-20260909-fixed-mail-boilerplate-filter.md)。
## 2026-09-09 忽略待处理卡片
| 接口 | 调用方与权限 | 对象/状态边界 | 保存与审计边界 |
|---|---|---|---|
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/ignore` | `FRONTEND_USER`,复用`RESERVATION_TASK_CONFIRM`和既有认证机制 | 校验实际任务酒店访问权、卡片所属任务和version;仅可处理业务卡PENDING_CONFIRM/REVIEW_REQUIRED;非业务展示/Basic/退出当前范围的Rooming拒绝;已忽略幂等 | 只保存IGNORED、version与updated_at;使用确认归属组锁;不接收业务payload,不新增忽略人/确认人/确认时间/恢复历史,不创建或变更预订记录 |
| `POST /api/reservation/source-notifications/{notificationId}/ignore` | `FRONTEND_USER`,复用`RESERVATION_TASK_CONFIRM`和既有认证机制 | 校验实际来源项酒店访问权、version;只允许ACK_REQUIRED且非GENERAL;已忽略幂等 | 只保存IGNORED、version与updated_at;不写ack人/时间、确认审计或原payload;普通GENERAL通知保留原ack动作 |
忽略不扩大详情或来源材料的权限/脱敏范围,不新增账号体系、权限码、忽略人字段、专用操作历史或外部发送。两接口返回既有详情,仅增加IGNORED状态;未授权/跨酒店403、归属不存在404、版本/终态冲突409。用户已明确取消忽略人和恢复记录设计,故不新增忽略审计行。完整产品及测试契约见[CR](requirements/CR-20260909-ignore-pending-cards.md)。
## 2026-09-09 AgentBus日志准确性增量
本次[三项纠错](requirements/CR-20260909-agentbus-log-accuracy.md)沿用既有调试开关、SYSTEM_DEBUG_EML_RUN、酒店/来源/运行关联、保留期与访问审计。保存状态的轻量查询只返回现有FINAL_ANSWER身份元信息,不读取正文;完整journal继续按需受控读取,不扩大ADR-017/019留存边界。延后补齐旧Replay终态时,必须验证实际Processing Run属于同酒店及同来源且有实际结束时间;无关联或读取失败则不写回。无新接口权限、Secret、个人数据类型或外部发送。
## 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 调用 |
### 2.1 SuperAgent 出站完整公开返回边界(2026-08-17,ADR-017)
- 2026-09-09恢复纠错:仅已知run恢复允许唯一同run非用户消息后缀与公开完整final匹配;恢复事件和状态快照身份冲突立即失败,原文先记journal。仍要求公开completed(success)/end和严格业务解码,snapshot正文不作为答案;无新增权限或接口。见[修复证据](../../.project-docs/50-evidence/topics/2026-09-09-parsing-recovery-suffix-fix.md)。
- fixed-channel Parsing Agent 与 Booking Business Agent 是`INTERNAL_ONLY` worker出站能力;两条主线调用必须
携带`include_trace=true`,显式false在Provider调用前fail closed。legacy Field Recovery仍按独立配置使用
no-Trace,不形成外部接口或前端能力。
- Trace模式必须同时收到公开`run.completed(status=success)`与顶层`end`。Provider 实际返回的 session response、
每条公开事件、恢复 run snapshot、HTTP 错误正文和最终答案,按原顺序、原内容进入 V13 共用 journal;它们不能
成为业务事实或绕过Layer 5/6。
- 出站 API Key、Authorization、Cookie、CSRF、数据库密码、请求头和 SuperAgent 未返回的隐藏推理不进入 journal。
Provider 返回本身不再做关键词脱敏、限长或去重;因此读取仍属于受控排障能力,不能进入普通员工页面或普通日志。
- 测试与生产使用相同写入能力;Debug lifecycle V2 的读取继续通过酒店、SourceMessage、processing run、权限、
环境和保留期门禁。按ADR-034,production默认不开放,只有显式启用回放功能后才注册同一受控HTTP能力。
## 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 前端业务接口
| 接口 / 能力 | 分类 | 当前管控 | 目标管控 | 审计要求 |
| --- | --- | --- | --- | --- |
| `POST /api/reservation/booking-email-intakes` | `FRONTEND_USER` | M012 V0.1 已实现;强制 Bearer 登录 + `RESERVATION_TASK_EDIT`,`hotel_id` 由当前用户酒店上下文解析并校验;只接受 `.eml`,默认上限 25 MiB;返回 SourceMessage、任务/通知 ID 和安全 warning | 保持登录、权限和酒店隔离;不得把上传原文、附件字节、完整行、真实邮箱、外链或 AI 原始 payload放入响应/普通日志;相同实际邮件幂等返回已有任务 | SourceMessage 捕获、V4 建卡和后续卡片确认沿用现有审计;导入响应本身不返回原文,上传失败只返回受控错误摘要 |
| `GET /api/reservation/booking-processing-runs/v2/{runId}/trace` | `FRONTEND_USER` | BE-TRACE-01 已实现;强制 Bearer 登录 + `RESERVATION_TASK_READ`,仅按 `processing_run_id` 定位;服务端依次校验 run 持久化酒店、当前用户可访问酒店、`source-message-inbox:{id}` 平台 SourceMessage 及 PostgreSQL linked run 关联 | 固定返回 Layer 1–6 与 Parser、Parsing Agent、Layer 4、Booking Agent、Layer 6 五个组件;只读取已持久化 artifact / invocation audit,缺失数据返回 `unavailable/partial` 与安全 omission,不接受或暴露 Debug replayId,不补算或重跑阶段 | 严格只读,不写 artifact/audit/业务状态;服务端移除 Secret、authorization、credential、token、cookie、签名/附件 URL、原始正文、raw provider answer/reasoning/provider identity;查询不写审计且不得调用 Parser、Agent、PMS/Opera |
| `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/task-cards` | `FRONTEND_USER` | 2026-08-22 已实现逐卡待处理查询;强制Bearer登录 + `RESERVATION_TASK_READ` + 酒店访问权 | 保持;一张业务Task Card一行,只返回列表安全摘要和`order_task_id + card_id`直接详情身份 | 只读查询默认不写业务审计;不得返回display/confirmed payload、邮件正文、附件URL、raw evidence或AI原始结果;按来源邮件时间和稳定兜底字段排序 |
| `GET /api/reservation/order-tasks/{orderTaskId}` | `FRONTEND_USER` | 已实现 M002 V4 CP5;强制 Bearer 登录 + `RESERVATION_TASK_READ` + 订单任务所属酒店访问权 | 保持登录 + `RESERVATION_TASK_READ` + 订单任务所属酒店访问权;V4 任务详情页展示顺序为 Basic Information、业务卡、SourceMessage Display;Basic 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` + 订单任务所属酒店访问权;返回卡片确认、复核解阻和订单归属确认的脱敏审计摘要 | 查询审计不再写审计;返回快照必须脱敏,不返回原始邮件正文、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 CP11;M002-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 CP11;M002-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 原始 payload;Rooming List 卡确认只表示事项已人工处理,不新增名单解析、附件预览、Excel 生成或 PMS 导入权限,也不修改同订单 Room Information、Group Booking Status 或其他业务卡;Payment 第一版确认只提交 `version` 和必要审计说明,不提交 `attachment_ids[]`、附件 URL 或完整附件对象;Basic Account、Room Type、Rate Code 目录错误返回 `V4_FIELD_VALIDATION_FAILED`;Rate Code 第一阶段只校验当前酒店 `ACTIVE` 目录存在,暂不校验 Account 适用关系 | 必须写业务审计,actor 使用当前登录用户;Rooming List 只记录本卡确认审计 |
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/binding-preview` | `FRONTEND_USER` | 2026-08-22 已实现;强制Bearer登录 + `RESERVATION_TASK_CONFIRM` + 订单任务所属酒店访问权 + binding version并发校验 | 只允许New、Update、Cancel、Trace、Rooming List、Cancel Allotment在未归属或Tour Code改变时预览;返回匹配/新建/冲突安全摘要,预览不得写订单、卡片或审计快照 | 只读预览不写业务审计;不得返回其他酒店订单、邮件原文、附件、AI payload或内部匹配证据;实际确认/复核仍按原接口写业务审计 |
| `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 / CP3 / CP4;CP3 兼容第二种 `英文姓` + `英文名` 名单样式,CP4 兼容第三种单列 `英文名` 名单样式;multipart 上传来源名单并直接下载 `.xlsx`;已在 multipart 参数绑定前前置校验登录和生成权限 | 登录 + `RESERVATION_ROOMING_LIST_GENERATE` + 酒店访问权;第一种来源样式后端从来源 Excel `旅游日期` 派生 Arrival / Departure,无旅游日期来源样式由用户提交 Arrival / Departure;Adults 按分房结果计算,目标默认值区域只保留 Payment Type / Nationality;Payment Type 默认 `BTQR` 且仅允许 `BTQR` / `CA`;Nationality 仅允许 `KR` / `CN` / `TH` / `MM` / `RS` / `TW`;第一版仍不落库、不上传 OSS | CP1 / CP2 / CP3 / CP4 不落生成记录表;错误响应不得记录完整名单、证件信息、源文件内容或生成文件内容;无旅游日期来源样式不得回显中文名、护照号、生日、出生地、签发地、联系方式、小费、住宿说明等来源敏感字段;后续若增加历史记录再补业务审计 |
### 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}/workbench-images` | `FRONTEND_USER` | 已实现;强制 Bearer 登录 + `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ`,按消息实际所属酒店校验访问权 | 返回当前邮件经过产品指定整图过滤后的候选图片安全摘要和同源内容路径;不返回OSS URL、本地文件地址、指纹、哈希或过滤结果;功能关闭、失败、超时或低置信度时保留候选图片 | 必须写原文读取审计;列表只限当前SourceMessage,不跨会话拼图;过滤不删除原始媒体 |
| `GET /api/source-messages/{id}/workbench-images/{mediaId}/content` | `FRONTEND_USER` | 已实现;强制 Bearer 登录 + `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ`,按消息实际所属酒店校验访问权,并校验媒体属于当前消息且为图片 | 只以内联响应流式返回当前候选图片内容;前端使用服务端返回的同源路径,不接受外部URL | 必须写原文读取审计;响应使用`private, no-store`、`nosniff`和安全文件名;不得进入日志、确认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 和安全错误摘要 |
| `/api/system/debug/agentbus-eml-replays/**` | `FRONTEND_DEBUG` | 按ADR-034由 `debug.agentbus-eml-replay.enabled` 显式注册;production默认关闭;登录/既有本地测试身份 + `SYSTEM_DEBUG_EML_RUN` + 酒店访问权 + 保留期 | 所有环境共用同一实现,禁止页面自行携带Secret;上传保留文件上限、预览、二次确认和frame完整性校验。通知专用来源仅豁免不适用的Agent能力,不豁免入站/存储/PostgreSQL/V2、权限或酒店门槛 | 写入/确认沿用回放审计;阶段记录 `TRACE_STAGE_READ`,完整日志一次记录 `LIFECYCLE_LOG_READ`;不得把返回payload再写普通日志 |
| `GET /api/system/debug/agentbus-eml-records` 与 `GET /{recordId}` | `FRONTEND_DEBUG` | 与回放使用同一显式功能开关、`SYSTEM_DEBUG_EML_RUN`和认证酒店隔离;按规范ID和保留期查询 | 只读聚合现有SourceMessage/Processing Run/Replay,不推进状态,不触发重试或创建伪Replay;列表只返回发件人、来源、时间、耗时及安全状态元信息,单条手动详情复用既有Replay格式 | 不写业务审计或业务状态;列表不返回主题、正文、附件URL、Agent输入输出;详情不得进入埋点、localStorage、普通错误上报 |
| `GET /api/system/debug/agentbus-eml-records/{recordId}/trace`、`/trace/stages/{stageKey}`、`/lifecycle-log` | `FRONTEND_DEBUG` | 同一开关、登录权限、酒店访问权和保留期;真实来源反查SourceMessage与Processing Run关联,手动来源沿用Replay关系 | 复用原Trace/阶段/完整日志响应,真实来源`replay_id=null`;不得把员工最小Trace权限用于读取此排障payload。关联失效和保留期外拒绝;journal不可用返回503,不输出残缺完整日志 | 阶段和日志按真实资源身份记录原访问审计:自动来源`SOURCE_MESSAGE_TRACE`,手动来源`AGENTBUS_EML_REPLAY`;完整日志一次只记一条`LIFECYCLE_LOG_READ` |
| `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 / Factory | `INTERNAL_ONLY` | 只能后端 Adapter 使用;每个 Agent 外部应用使用独立 API Key,Secret 不出后端,不能用 `external_subject_id` 代替 Profile/凭据隔离 | 现有流程按各自 debug、dispatch 或业务 invocation 追踪;factory/client settings 的字符串表示必须脱敏 key |
| M012 Layer 3 Field Recovery Adapter | `INTERNAL_ONLY` | 只允许 Booking 后端以最小 `RecoveryRequestSet` 调用专用解析 Agent;当前仅 `MANUAL_EML`,不新增浏览器或第三方入口;使用 `booking.field-recovery.open-api.*` 独立 Secret,subject 由来源消息 hash 派生 | `th_hotel_booking.booking_field_recovery_execution` 保存 request/response hash、状态、Provider 安全元数据、PatchSet 与 Assembly;不得保存 API Key、Cookie、raw answer、完整邮件、附件 URL 或思考过程 |
| M012 Fixed-Channel Parsing Agent v1 Adapter | `INTERNAL_ONLY` | CP4只允许pre-Context durable worker发送完整受校验AgentRequest;使用`booking.parsing-agent.*`独立Secret和source hash subject,不新增HTTP/MCP入口,不在AgentBus/手工HTTP callback等待;默认开关仍由部署配置决定 | V5/V6 execution/artifact继续保存安全聚合;V13 `booking_superagent_response_journal` 另按 attempt 保存 API 实际返回的全部公开事件与最终答案原文。不得保存API key、Authorization、Cookie/CSRF、请求头、数据库密码、完整request或附件bytes;未由SuperAgent返回的隐藏思考不记录 |
| M012 当前 Rooming List 文件名识别 | `INTERNAL_ONLY` | 只由 Booking Layer 2–4 处理 `current_material=true` 的当前 `.xlsx` 附件;完整文件名命中批准 `LLT...xlsx` 规则后仅流式检查 OOXML 包结构,不读取 History 附件、shared strings、普通单元格、名单行、姓名、同行关系或证件;无新增 HTTP/MCP/前端入口 | 既有 MaterialPackage attributes 只保存文件名候选、规范 Tour Code、safe/reason、Sheet 数和识别器版本;Layer 3/4 只保存中立 observation/binding/resolution 与 Evidence。不得在日志、DecisionInput、Agent wire 或新持久化中保存名单内容、附件 bytes/Base64/URL;Parsing Agent request 排除该附件文件名和内容 |
| M012 Layer 5 Booking Business Agent Adapter | `INTERNAL_ONLY` | 只允许 PostgreSQL V11 durable worker 在 Layer 3/4、canonical `BookingDecisionInputV2` 与 `AWAITING_BOOKING_AGENT` 已可靠提交后,使用 `booking.agent.open-api.*` 专用配置和独立 Secret 在数据库事务外调用。输入含 Current subject/body、完整有序 History 正文、当前附件安全引用及 Layer 3/4 结果;排除 History 附件、数据库订单/任务历史、bytes 和 URL。不新增浏览器/第三方入口,不在 WebSocket callback 或保存 Parsing 结果的事务中等待 Provider | `booking_agent_execution` / `booking_agent_invocation` 继续记录执行与安全聚合;V13 journal 另保存每次 attempt 实际收到的公开事件与最终答案原文。Candidate 仍须严格 decoder 后单独提交并经 Layer 6;不得保存 API Key、Authorization、Cookie/CSRF、请求头、数据库密码或出站完整request,也不得把 Provider 原文写普通应用日志 |
| 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;AgentBus EML replay、两来源统一处理记录、阶段详情与统一生命周期日志 |
| `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、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、重试、失败摘要 |
| SuperAgent 出站安全聚合 | Parsing execution / Booking invocation audit 的 `public_trace_events` | 保留兼容的安全摘要、状态、hash和失败分类;不作为完整返回权威来源 |
| SuperAgent 出站完整公开返回 | `booking_superagent_response_journal`(PostgreSQL V13) | 测试/生产按实际接收顺序保存公开事件和最终答案原文及 session/run/attempt/时间;不保存出站请求、请求头、API Key、Authorization、Cookie、CSRF、数据库密码或未返回的隐藏推理 |
| 安全审计 | 后续可新增平台安全审计表 | 登录失败、签名失败、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. 已完成 CP1:Reservation / 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 继续使用机器鉴权。
## 9. M012 房型与 RATE CODE 目录配置化边界
- M012 不新增 Controller、权限码或外部系统调用;既有 lookup 与 V4 Order Task 详情继续使用 `FRONTEND_USER`、对象所属酒店校验、分页和脱敏边界。
- 版本化目录资源只在后端与受控 Booking Skill source 中使用。前端接口不得返回 Excel / Word 原文、来源行以外的原始资料、价格、邮件正文、附件 URL、AI 原始 payload 或 PMS / OHIP 响应。
- Catalog 管理仍属于 `FRONTEND_ADMIN` + `RESERVATION_CATALOG_MANAGE` 及既有管理审计。历史组合 RATE CODE 只可为兼容读取或入站规范化使用,不能借此绕过目录校验、酒店隔离、人工确认或审计。
- 本变更不执行生产数据库写入;V27 是加性部署迁移。Booking Skill 仅产生受控建议与人工复核原因,不直接读写 Catalog、PMS、Opera 或 OHIP。
## 10. AgentBus 统一处理记录读取边界(2026-09-08)
- 页面进入、筛选、刷新及浏览器恢复只发起只读记录查询;当前详情每10秒读取阶段索引/选中阶段,终态或离开即停。不允许通过列表、Trace或日志GET发起Parser、Agent、投影重试、通知ACK或业务确认。
- 邮件发件人是列表允许的必要信息;不返回主题、正文、附件地址或Agent输入输出。自动收件使用Inbox系统创建时间,上传使用EML系统入站时间,不能以外部邮件头作为“系统接收时间”。
- `source-{id}`必须反查自动邮件身份、酒店与关联运行;与手动Replay关联的SourceMessage不可重复冒充真实来源。自动来源仅使用内存只读适配,不能创建持久Replay或复制第二套业务产物。
- 通知专用来源的FRESH回放复用原规则、保存与员工投影;预览标记只帮助前端选择按钮门槛,实际执行仍按后端已校验frame和规范化发件人规则判断。不得因无需双Agent而降低来源权限、文件/frame校验或存储持久化要求。
- 详情URL仅保留稳定记录ID和用户明确要求的日期/发件人/异常筛选,不保存邮件正文、附件地址或Agent payload。字段与错误边界见[统一处理记录契约](frontend-backend/agentbus-eml-records-integration-guide.md)。
## 2026-09-09 来源附件受控下载
新增GET /api/source-messages/{id}/attachments/content,双原文权限、消息所属酒店、原附件精确身份与成功访问审计;同源凭证下载,不接收客户端URL,固定attachment/octet-stream/no-store/nosniff、25MiB上限,限制OSS基址与真实本地根目录并拒绝符号链接逃逸。详见[附件CR](requirements/CR-20260909-source-attachment-download.md)。
## 2026-09-10 最终失败收尾 CP2a(独立副本待合并)
无新增HTTP入口、权限、外部传输或前端凭据;只修正既有授权调试结果的终态,沿用酒店/来源/运行身份校验。工作台回执核对通过既有repository边界只读完成,按完整酒店/来源/运行/hash/revision匹配,不读取其他酒店内容。Layer6恢复记录只新增次数与UTC时间,不保存邮件/附件/Token;终态更新使用既有PG事务和lease/fencing。真实邮件、通知触发与部署均未在本批执行。范围及验收见CR-20260909-final-failure-notification的CP2a补充。
## 2026-09-10 统一加载附记
CP1通知组件/V39和CP2a失败收尾/PG V21已与最新C1及历史保留共同加载当前本地后台;发送关闭,未接自动失败发现/登记,未发送或补发。当前业务数据保留。见[实际运行证据](../../.project-docs/50-evidence/topics/2026-09-10-unified-runtime-load.md)。