# Booking 邮件处理架构 v0.5 | 项目 | 内容 | | --- | --- | | 文档状态 | 权威架构;V2 durable runtime本地实现,外部运行放行 HOLD | | 架构版本 | `booking-architecture-v0.5` | | 契约版本 | `booking-contracts-v2` | | 决策依据 | ADR-011、ADR-012、ADR-015 | | 业务基线 | `booking-business-agent-v1.0` | | 范围终点 | 用户逐项确认;不调用 PMS、Opera、OHIP、付款或部门流转 | ## 1. 核心不变量 所有业务任务与处理结果的最终判断权只属于 Layer 5。字段名称相同不构成跨层授权:Layer 3 的 `SOURCE_ACTION_KIND=NEW` 仍只是来源事实,必须由 Layer 5 结合当前正文、逐来源动作、目标和 Layer 4 确定性结果重新决定是否为 `NEW_BOOKING`。历史生命周期不能改写当前任务类型。 `business_type`、`action_kind`、General/Risk/Ignored、TaskCard、linked action 和 derived action 均不得由 Layer 1–4 产生。Layer 6 不改型,Layer 7 不重算。 ## 2. 七层边界 | 层 | 只负责 | 标准输出 | 禁止行为 | | --- | --- | --- | --- | | 1 接入 | 捕获 AgentBus/EML、身份、幂等、revision | `SourceMessageEnvelopeV2` | 看主题/来源建业务对象 | | 2 材料 | Current/History 分离,正文、附件/图片/工作簿结构与证据;对批准的current `LLT...xlsx`只做文件名与OOXML包级安全快照 | `MaterialPackageV2` | 根据材料建任务;读取History附件、shared strings或名单明细 | | 3 解析 | 来源事实、原始值、中立 mention/binding/relationship、材料处置和解析 issues;最终merge后追加current Rooming中立observation/binding | `Layer3ResultV2` | action hint、Booking Type、业务完整性放行、Trace/Payment/Rooming/Allotment业务判断 | | 4 上下文 | 按 Tour Code/来源目标整理来源单元,独立解析 Roomtype;QBD 输出一项同时适用 FIT/GROUP 的 Rate 套餐方案,普通 LianTai 同时输出 FIT/GROUP 两项;把安全通过的Rooming中立材料投影为typed resolution | `DecisionContextV2.order_contexts[]`+`rooming_list_resolutions[]` | 按房量决定 Booking Type、查询数据库订单/任务历史、用历史补来源、判断重复 New/生命周期/任务顺序 | | 5 决策 | 5A每封白名单入站调用 Booking Agent判断类型/目标;5B由信息系统复制Layer3/4固定字段并组装typed payload | `CompactDecisionV1` → `CandidateDecisionV2` | 系统替Agent做业务分类、写 TaskCard、生命周期准入、调用 PMS | | 6 校验 | schema/evidence/目标/必填、Booking Type 对应 Rate option 等值、幂等及 review | `ValidationResultV2` | 查询生命周期/重复 New/前序任务;新增或替换业务类型、重算 Candidate | | 7 展示确认 | 一对一展示 Candidate+Validation,接受逐项确认 | `ConfirmationProjectionV2` | 聚合/解释/重算业务参数、执行 PMS | ## 3. 唯一 Layer 5 调用边界 ```text SourceMessageEnvelopeV2 → MaterialPackageV2 → Layer3ResultV2 → DecisionContextV2 → BookingDecisionInputV2 (canonical JSON + SHA-256) └─ short transaction: persist Layer3/4/input + enqueue one execution → COMMIT / AWAITING_BOOKING_AGENT → durable worker claim (lease + fencing) └─ outside database transaction ├─ Booking Business Agent (compact input → compact business decision) ├─ expected platform Profile ID gate + published version audit └─ Layer 5B deterministic Candidate assembler + strict decoder / fail-closed Risk → short transaction: persist one CandidateDecisionV2 → recoverable Layer6 claim → ValidationResultV2 → ConfirmationProjectionV2 / validated V4 compatibility projection ``` 白名单入站邮件每封只建立一个Booking Agent业务execution并只接受一份有效Candidate;临时网络故障可在同一 execution内进行有限Provider attempt,不能产生第二份业务结果。New/Update/Cancel/General也不得由本地规则提前返回。Facade 向 Agent 发送专用精简投影,而不是完整内部对象:保留 Current、完整有序邮件 History 正文、按物理行组织的必要事实、 Layer 4解析状态和当次短引用,排除完整Layer3技术包装、evidence registry、History附件、数据库订单/任务历史和生命周期准入结论。 Agent只判断业务;Layer 5B再从canonical输入复制日期、房型、数量、价格、对应Rate/早餐和证据。每个 run 只保存一个权威 Candidate;shadow 结果只能作为 不可写比较 artifact。 确定性组装器校验同一 run/message/revision/version,保留 Layer3ResultV2,不覆盖来源事实,按显式 `source_unit_ref/room_item_ref` 绑定,并以稳定顺序合成唯一 `BookingDecisionInputV2`。Layer 4 不查询数据库; 来源字段缺失直接形成 null/`UNRESOLVED`,由后续人工确认。 ## 4. 业务类型与关系 - New/Update/Cancel:Agent 根据当前来源动作/正文和目标识别;类型与目标明确后字段缺失仍保留原类型。 Booking Type 由 Layer 5 按独立订单有效房量 1–4 FIT、5+ GROUP;确定后只能使用对应 Layer 4 Rate option。 本期不自动检查重复 New 或生命周期资格。 - Trace:Layer 3 structured mention 仅是来源语义;Booking Agent 决定是否形成 Trace、服务项和部门候选。 - Rooming List:Layer 2/3只按current完整`LLT...xlsx`文件名和OOXML包级安全结构形成中立材料;Layer 4安全通过 才给Excel/标签/唯一Tour Code typed resolution。Agent只消费该resolution,不读取文件内容,业务判定仍在Layer5。 - Payment:本期不是业务类型,只作为未归类原文。 - Allotment:target business type 不含 ALLOTMENT。只有当前正文明确 Allotment 操作时处理;定量 source deduction 按符合条件的物理目标行独立派生,不聚合、不查 old/remaining;整块取消按唯一 source 一项。 - General 是可与任务并存的未归类原文区;Risk 按不明确事项局部隔离;Ignored 只作错误方向安全兜底。 - 单目标业务关系使用 typed `linked_actions[]`;跨目标共享效果只用 `derived_actions[]`。 ## 5. Current、History、附件与安全 内部 `BookingDecisionInputV2` 与 Agent 输入都保留 Current 和有序邮件 History 正文。Agent 专用输入只提供当前 附件说明、按单元整理的必要Layer3/4业务材料和当次短引用;完整evidence registry、History附件、数据库订单/任务历史和生命周期结论不进入。 输入不包含附件二进制/Base64、签名 URL、Cookie、Secret、数据库连接或隐藏推理。外部 Agent adapter 必须从同一 canonical对象确定性投影compact输入;短引用只在本次调用有效,不能成为第二个事实来源。 文件名型Rooming附件不会进入Parsing Agent request,其文件名、bytes与内容均排除。信息系统仅在本地保存 隐私最小化snapshot和Evidence;History附件仍完全不读取。名单内容Parser是独立能力,本链不调用。 Roomtype 只按来源房型精确映射;Rate 使用目录公司、显式 option 类型、来源房型、来源价格和早餐条件,严禁使用 canonical Roomtype。Rate 唯一性按不同 `{Rate Code+早餐+餐厅}` 套餐计算。同一 Tour Code 内每个 option 分别收敛;普通 LianTai 两项同时输出,Layer 5 判断 Booking Type 后选中对应项。来源缺失不触发历史查询。 ## 6. Validator、展示与确认 - Layer 6 对 target 和 derived action 独立返回 `VALID/REVIEW_REQUIRED/RISK/REJECTED`,并保持 Candidate canonical hash 不变。 - derived action 被阻断时,不回滚其他已通过的 target。 - Layer 7 只显示 Layer 5 已给出的逐物理行 source deduction/whole cancel 和 Layer 6 状态,不计算库存余额。 - 确认按 item 幂等。部分 target 已确认而 derived action 仍 review 时,run 为 `PARTIALLY_CONFIRMED`。 ## 7. 入口、持久化与迁移 - Manual EML 与 AgentBus 始终先落 SourceMessage,并进入同一 persistence-neutral orchestrator。 - PostgreSQL/MySQL 只是 Port 实现,不决定是否走 Layer 5。 - 最终Layer3、Layer4、canonical input、唯一Booking Agent execution和`AWAITING_BOOKING_AGENT`必须在短事务中 提交;任何Provider网络等待都必须发生在事务外,失败不得回滚已完成的Parsing结果。 - V11 execution使用稳定input-hash幂等、`SKIP LOCKED`、lease/fencing和有限退避;Candidate单独提交后是Layer6 的恢复点,重启或重复唤醒不得重呼Provider或生成不同Candidate。 - 每个Provider attempt写受控审计;raw回答不落库。不可重试契约错误和重试耗尽形成安全Risk Candidate,仍须 进入Layer6,不能直接创建任务。 - 新 V4 Booking TaskCard 只允许从 validated v2 projection 创建,并保存 run/candidate/validation provenance。 - v1/V4 历史数据只读;新运行不写 `action_hint/booking_type` lower-layer business hints,不做批量回填。 - `SHADOW` 只比较不写业务,`AUTHORITATIVE` 独占写入,`CAPTURE_ONLY` 只捕获并产生安全 Risk/review。 - 切换或回退不得恢复 legacy Parser/Agent 直接建卡。 ## 8. 运行状态与放行边界 ```text RECEIVED → MATERIAL_READY → PARSER_COMPLETE → CONTEXT_READY → AWAITING_BOOKING_AGENT → BOOKING_AGENT_IN_PROGRESS → [BOOKING_AGENT_RETRY_WAIT → BOOKING_AGENT_IN_PROGRESS]* → BOOKING_AGENT_CANDIDATE_RECEIVED → LAYER6_VALIDATING → VALIDATED → AWAITING_CONFIRMATION → PARTIALLY_CONFIRMED | CONFIRMED ``` 重试耗尽先暴露`BOOKING_AGENT_RETRY_EXHAUSTED`,不可重试Candidate错误先暴露 `BOOKING_AGENT_CANDIDATE_REJECTED`;二者随后都持久化安全Risk并进入Layer6。真实Provider当前Profile复核、 Booking PostgreSQL V1–V11、非生产live chain、production authoritative切换和PMS/Opera/OHIP均需独立审批, 本架构文档不构成发布授权。 ## 9. 替代关系 - 本文、`booking-business-agent-rules-v1.md` 与 `booking-email-contracts-v2.md` 是新运行的权威基线;业务语义 以 rules-v1 为准,wire shape 以 contracts-v2 为准。 - architecture-v0.4/contracts-v1 仅用于历史 artifact/V4 读取和迁移回归,不再定义新业务写入边界。 - M002/M012/BR00 旧实现记录若与 ADR-012 冲突,以 ADR-012、rules-v1 和本架构为准;旧 payload 不回写。