24 KiB
M002 V4 真实目录与 Lookup API 设计
文档信息
| 项目 | 内容 |
|---|---|
| 文档版本 | 0.2 |
| 日期 | 2026-07-19 |
| 状态 | CP11 已落地第一版数据库目录与 lookup API;后续真实 PMS 同步和目录管理后台继续后置 |
| 适用范围 | M002 V4 Account、Market、Source、Room Type、Rate Code 目录来源、数据模型、前端 lookup、缓存、酒店隔离、权限和失败兜底 |
| 不适用范围 | 真实 OPERA / OHIP 写操作、真实价格计算、前端页面实现、SuperAgent Prompt 修改、目录管理后台、SuperAgent 机器目录接口 |
1. 文档定位
M002 V4 CP8 已实现第一版固定种子目录校验;M002 V4 CP11 已把该目录迁移为数据库目录和前端 lookup API:
- Basic Information 的
account_code必须存在于当前酒店数据库 Account 目录。 - Market / Source 由 Account 派生,不由 SuperAgent 输出。
- Room Type / Rate Code 第一版使用当前酒店数据库目录校验和字段选项提示。
- 目录错误会让对应 V4 卡片进入
REVIEW_REQUIRED,用户通过复核解阻选择合法 code。
本文记录真实目录和 lookup API 的设计与 CP11 第一版实现。CP11 新增 workflow_reservation_catalog_account、workflow_reservation_catalog_code 两张表,并通过 Flyway 初始化 HOTEL-TEST、HOTEL-DEV 以及迁移执行时已存在的 ACTIVE 平台酒店的固定种子目录;同时新增 ReservationV4CatalogBootstrapRunner,在平台默认酒店由启动流程创建后,如果该酒店目录为空,会补一份 FIXED_SEED_IMPORT 初始化目录。不再在运行时代码中把固定种子作为全局目录事实。workflow_reservation_catalog_sync_run、真实 PMS / OPERA / OHIP 同步、目录管理后台和 SuperAgent 机器目录供给接口继续后置。
后续若本文与 M002-v4-agent-callback-field-contract.md 的 Agent 输入字段冲突,以 Agent 字段契约为准;若与 security-access-control-boundary.md 的接口权限冲突,以安全边界为准。
2. 当前固定种子目录
CP11 之前固定种子实现位于后端 ReservationV4DirectoryService 和 FixedReservationV4DirectoryServiceImpl。CP11 起实现改为 ReservationV4DatabaseDirectoryServiceImpl,目录读取只走数据库目录表;固定种子通过 V24__create_reservation_catalog_tables.sql 初始化导入 dev/test 基准酒店和迁移时已有 ACTIVE 酒店,并由 ReservationV4CatalogBootstrapRunner 补齐迁移后才创建的默认 ACTIVE 酒店,来源标记为 FIXED_SEED_IMPORT。
| 目录 | 当前用途 | 当前固定值 | 当前限制 |
|---|---|---|---|
| Account | Basic Information 可选目录;SuperAgent 和用户提交都使用稳定 code | QBD_TRAVEL、LIAN_TAI、HANATOUR_TD |
已进入数据库初始化目录,仍不是 PMS 全量 Account,管理后台后置 |
| Market | 由 Account 派生的订单级 Market | 当前 Account 均派生 LEISURE |
已进入通用代码目录,前端仍不直接编辑 |
| Source | 由 Account 派生的订单级 Source | 当前 Account 均派生 TRAVEL_AGENT |
已进入通用代码目录,前端仍不直接编辑 |
| Room Type | 房型 code 校验和字段选项提示 | TWN、KING、DBL、SGL、TRP、RM1、RM2、RM3 |
已进入数据库初始化目录,仍不是 PMS 全量房型 |
| Rate Code | Rate Code 校验和字段选项提示 | BAR、RACK、PACKAGE、GROUP、FIT |
已进入数据库初始化目录,不按日期、账号、房型过滤,不含价格 |
当前固定种子只能支撑开发和演示闭环,不能作为生产长期事实源。
3. 设计目标
真实目录能力要解决以下问题:
- 前端不再硬编码 Account、Room Type、Rate Code 选项。
- 后端确认和复核仍然是最终校验者,前端 lookup 只用于选择体验。
- 每个目录都按
hotel_id隔离,不能跨酒店泄露目录。 - 目录有来源、版本、更新时间和启停状态,便于排查 SuperAgent 输出 code 与系统目录不一致的问题。
- PMS / OPERA / OHIP 不稳定或暂未接入时,系统仍可使用最后一次成功目录快照或系统管理目录兜底。
- 固定种子目录可以作为 dev/test 或导入初始化兜底,但生产不应默认靠代码固定值。
4. 目录来源分层
目录来源按阶段分三层,后续可以逐步切换,不要求一步接真实 PMS。
| 阶段 | 来源 | 中文说明 | 适用目录 |
|---|---|---|---|
| Phase 0 | FIXED_SEED_IMPORT |
CP11 已将固定种子通过 Flyway 和启动补种子流程导入数据库,不再作为运行时代码全局 Map | 当前 Account、Market、Source、Room Type、Rate Code |
| Phase 1 | SYSTEM_MANAGED |
本系统数据库目录,由初始化脚本、管理后台或导入文件维护 | Account、Market、Source;也可临时维护 Room Type、Rate Code |
| Phase 2 | PMS_SYNC |
后端从 PMS / OPERA / OHIP 同步目录到本系统本地表,业务查询只读本地快照 | Room Type、Rate Code 优先;Account、Market、Source 视 PMS 能力再接 |
原则:
- 业务确认接口只依赖本系统目录服务,不直接调用外部 PMS。
- 真实 PMS / OHIP Adapter 只负责同步目录快照,不把厂商 DTO 直接暴露给业务服务或前端。
- 同一目录可有
source_system标记,但业务接口只使用稳定code。
5. 目录归属建议
| 目录 | 第一版真实来源建议 | 未来 PMS / OPERA / OHIP 方向 | 前端是否可编辑 | 说明 |
|---|---|---|---|---|
| Account | 本系统管理目录优先 | 可选同步 PMS profile / company / travel agent 主数据,但本系统仍维护映射 code | 是,Basic Information 选择 Account | Account 影响 Market / Source 派生,第一版建议先由系统管理维护,避免 PMS profile 字段未确认导致业务不可用 |
| Market | 本系统管理目录 | 可选同步 PMS market code 配置 | 否,随 Account 派生展示 | 前端不直接改 Market;修改 Account 后后端派生 Market |
| Source | 本系统管理目录 | 可选同步 PMS source code 配置 | 否,随 Account 派生展示 | 前端不直接改 Source;修改 Account 后后端派生 Source |
| Room Type | PMS / OPERA / OHIP 同步目录优先 | 同步酒店有效房型、展示名、人数、启停状态 | 是,业务卡选择房型 | 若 PMS 未接入,可临时由系统管理维护或固定种子初始化 |
| Rate Code | PMS / OPERA / OHIP 同步目录优先 | 同步有效 Rate Plan / Rate Code;价格和日期适用规则后置 | 是,New Booking 选择 Rate Code | 第一版 lookup 只选 code,不做价格计算 |
Department 目录在 V4 字段契约中也会被 Trace 使用,但当前固定种子 CP8 尚未实现。后续可沿用本文模型扩展 DEPARTMENT,不放入本 checkpoint。
6. 数据模型草案
6.1 推荐表:workflow_reservation_catalog_account
Account 单独建表,原因是它不仅有显示名称,还要派生 Market / Source。
| 字段 | 中文说明 |
|---|---|
id |
内部主键 ID |
hotel_id |
酒店 ID,目录按酒店隔离 |
account_code |
Account 稳定 code,大小写敏感 |
account_name |
Account 显示名称 |
market_code |
该 Account 派生的 Market code |
source_code |
该 Account 派生的 Source code |
status |
ACTIVE / DISABLED |
source_system |
SYSTEM_MANAGED / PMS_SYNC / FIXED_SEED_IMPORT |
external_account_id |
外部 PMS profile 或 account ID,可为空 |
catalog_version |
目录版本,用于前端缓存和排查 |
last_synced_at |
外部同步成功 UTC 时间;系统管理数据可为空 |
metadata_json |
扩展元数据,不替代可查询字段 |
version |
乐观锁版本 |
created_at / updated_at |
UTC 创建和更新时间 |
logic_deleted_at / logic_deleted_reason |
逻辑删除时间和原因 |
建议唯一约束:
uk_reservation_catalog_account_code(hotel_id, account_code)
6.2 推荐表:workflow_reservation_catalog_code
Market、Source、Room Type、Rate Code 可先使用统一 code 表。
| 字段 | 中文说明 |
|---|---|
id |
内部主键 ID |
hotel_id |
酒店 ID,目录按酒店隔离 |
catalog_type |
MARKET / SOURCE / ROOM_TYPE / RATE_CODE |
code |
稳定目录 code,大小写敏感 |
display_name |
前端显示名称 |
status |
ACTIVE / DISABLED |
source_system |
SYSTEM_MANAGED / PMS_SYNC / FIXED_SEED_IMPORT |
external_id |
外部 PMS / OPERA / OHIP ID,可为空 |
sort_order |
前端默认排序 |
effective_from / effective_to |
生效日期范围,可为空;酒店本地业务日期语义 |
catalog_version |
目录版本,用于前端缓存和排查 |
last_synced_at |
外部同步成功 UTC 时间 |
metadata_json |
扩展元数据,例如房型人数、Rate Code 适用说明 |
version |
乐观锁版本 |
created_at / updated_at |
UTC 创建和更新时间 |
logic_deleted_at / logic_deleted_reason |
逻辑删除时间和原因 |
建议唯一约束:
uk_reservation_catalog_code(hotel_id, catalog_type, code)
6.3 推荐表:workflow_reservation_catalog_sync_run
如果接 PMS / OPERA / OHIP 同步,建议记录每次同步运行。
CP11 本轮没有创建该表。原因是当前不接真实 PMS / OPERA / OHIP 同步,暂时没有同步运行事实可记录;后续做同步 worker 或目录管理后台时,再新增该表和对应 Repository。
| 字段 | 中文说明 |
|---|---|
id |
同步运行 ID |
hotel_id |
酒店 ID |
catalog_type |
同步目录类型 |
source_system |
外部来源系统 |
sync_status |
SUCCESS / FAILED / PARTIAL_SUCCESS |
started_at / finished_at |
UTC 开始和结束时间 |
catalog_version |
本次生成的目录版本 |
items_seen_count |
外部返回数量 |
items_upserted_count |
本系统写入或更新数量 |
items_disabled_count |
本系统停用数量 |
safe_error_summary |
安全错误摘要,不保存 Secret 或完整外部响应 |
created_at / updated_at |
UTC 创建和更新时间 |
同步 run 是技术追踪,不直接给普通业务前端展示完整细节。管理后台后续如展示同步记录,应单独登记权限和脱敏规则。
7. 后端服务边界
CP11 已替换当前 FixedReservationV4DirectoryServiceImpl,保留 ReservationV4DirectoryService 作为业务稳定端口。
workflows.reservation.service
ReservationV4DirectoryService
- findAccount(hotelId, accountCode)
- isKnownRoomTypeCode(hotelId, roomTypeCode)
- isKnownRateCode(hotelId, rateCode)
workflows.reservation.repository
ReservationV4CatalogRepository
- 只封装本地目录表查询,不直接调用 PMS
workflows.reservation.service
ReservationV4CatalogLookupService
- listAccounts(...)
- listRoomTypes(...)
- listRateCodes(...)
integrations.ohip / integrations.pms
CatalogSyncAdapter
- 后续从 PMS / OPERA / OHIP 拉取目录并转换为本系统目录草稿
规则:
- V4 入站、确认、复核只调用
ReservationV4DirectoryService。 - 前端 lookup Controller 调用
ReservationV4CatalogLookupService,该服务同样只读本地目录表。 - PMS / OHIP 同步 Adapter 只能写本地目录表或同步 run,不直接参与用户确认事务。
- 如果目录服务不可用,确认接口 fail closed,不接受自由文本。
8. Lookup API 草案
Lookup API 属于前端业务查询接口,不给 SuperAgent 或 AgentBus 调用。
统一要求:
- 分类:
FRONTEND_USER。 - 鉴权:Bearer session token。
- 权限:第一版建议复用
RESERVATION_TASK_READ;目录维护后台另行使用管理权限。 - 酒店隔离:
hotel_id可选;不传时按当前用户默认酒店解析,传入时必须校验用户可访问。 - 返回:只返回目录 code、显示名、状态、来源和安全元数据,不返回外部 PMS 原始响应。
- 分页:
page_num从 1 开始,page_size后端限制最大值。 keyword无匹配时,items=[]且page.total=0;如果当前酒店未过滤的 ACTIVE 目录仍存在,catalog_source/catalog_version继续返回真实目录元数据,不把筛选无结果误报为DATABASE_EMPTY。
8.1 Account Lookup
GET /api/reservation/lookups/accounts
查询参数:
| 参数 | 必需 | 中文说明 |
|---|---|---|
hotel_id |
否 | 当前酒店 ID;未传时按当前用户默认酒店 |
keyword |
否 | 匹配 account_code 或 account_name |
page_num / page_size |
否 | 分页 |
第一版固定只返回 ACTIVE Account,不开放 active_only=false。
响应草案:
{
"hotel_id": "HOTEL-TEST",
"catalog_type": "ACCOUNT",
"catalog_source": "FIXED_SEED_IMPORT",
"catalog_version": "seed-20260719-v1",
"stale": false,
"items": [
{
"code": "QBD_TRAVEL",
"display_name": "Q.B.D. TRAVEL GROUP CO., LTD",
"status": "ACTIVE",
"catalog_source": "FIXED_SEED_IMPORT",
"market_code": "LEISURE",
"market_name": "LEISURE",
"source_code": "TRAVEL_AGENT",
"source_name": "TRAVEL_AGENT"
}
],
"page": {
"page_num": 1,
"page_size": 20,
"total": 1
},
"warnings": []
}
前端用途:
fields[].options_source=reservation_v4_account_catalog时调用。- 用户选择 Account 后,前端可以立即展示响应中的 Market / Source;最终以后端确认接口派生结果为准。
- 不允许用户自由输入 Account code。
8.2 Room Type Lookup
GET /api/reservation/lookups/room-types
查询参数:
| 参数 | 必需 | 中文说明 |
|---|---|---|
hotel_id |
否 | 当前酒店 ID |
keyword |
否 | 匹配房型 code 或显示名 |
page_num / page_size |
否 | 分页 |
第一版固定只返回 ACTIVE Room Type,不接 arrival_date / departure_date,日期适用范围过滤后置。
响应草案:
{
"hotel_id": "HOTEL-TEST",
"catalog_type": "ROOM_TYPE",
"catalog_source": "FIXED_SEED_IMPORT",
"catalog_version": "seed-20260719-v1",
"stale": false,
"items": [
{
"code": "RM2",
"display_name": "RM2",
"status": "ACTIVE",
"catalog_source": "FIXED_SEED_IMPORT",
"adult_capacity": 2
}
],
"page": {
"page_num": 1,
"page_size": 20,
"total": 1
},
"warnings": []
}
前端用途:
fields[].options_source=reservation_v4_room_type_catalog时调用。- V4 业务卡里的
room_items[].room_type_code、business_fields.after.room_items[].room_type_code、加床目标房型等都应从该接口选。 - 前端不要把旧固定种子当 PMS 全量房型。
8.3 Rate Code Lookup
GET /api/reservation/lookups/rate-codes
查询参数:
| 参数 | 必需 | 中文说明 |
|---|---|---|
hotel_id |
否 | 当前酒店 ID |
keyword |
否 | 匹配 Rate Code 或显示名 |
page_num / page_size |
否 | 分页 |
第一版固定只返回 ACTIVE Rate Code,不接 booking_type、account_code、arrival_date / departure_date,适用范围和价格过滤后置。
响应草案:
{
"hotel_id": "HOTEL-TEST",
"catalog_type": "RATE_CODE",
"catalog_source": "FIXED_SEED_IMPORT",
"catalog_version": "seed-20260719-v1",
"stale": false,
"items": [
{
"code": "GROUP",
"display_name": "GROUP",
"status": "ACTIVE",
"catalog_source": "FIXED_SEED_IMPORT",
"pricing_available": false
}
],
"page": {
"page_num": 1,
"page_size": 20,
"total": 1
},
"warnings": []
}
前端用途:
fields[].options_source=reservation_v4_rate_code_catalog时调用。- 第一版只选
rate_code,不展示或计算真实价格。 - V4 契约仍禁止
UPDATE_BOOKING携带 Rate Code;lookup API 不改变该规则。
8.4 Market / Source Lookup
Market / Source 第一版不作为用户可编辑字段,不建议给普通业务表单单独开放选择。
如果后续系统管理后台需要维护 Market / Source,可使用管理接口或通用目录接口,但不应让 V4 Basic Information 页面绕过 Account 派生规则。
9. fields[] 与 lookup 的关系
后端任务详情字段仍是前端渲染白名单。Lookup API 只解决选项来源,不决定字段是否展示或可编辑。
options_source |
对应 lookup | 前端行为 |
|---|---|---|
reservation_v4_account_catalog |
GET /api/reservation/lookups/accounts |
渲染 Account 下拉 / 搜索选择,展示派生 Market / Source |
reservation_v4_room_type_catalog |
GET /api/reservation/lookups/room-types |
渲染房型搜索选择 |
reservation_v4_rate_code_catalog |
GET /api/reservation/lookups/rate-codes |
渲染 Rate Code 搜索选择 |
static_enum |
使用 fields[].enum_options |
不调用 lookup |
system_case_lookup |
后续订单 / 任务对象 lookup | 不属于本目录 checkpoint |
前端提交时仍按卡片确认或复核接口提交字段值。后端确认前再次校验目录,不能因为前端选项来自 lookup 就跳过后端校验。
10. 缓存设计
缓存是优化,不是事实源。本系统本地目录表才是业务查询事实源。
后续建议。CP11 第一版暂不加内存缓存,直接读取本系统本地目录表;原因是当前种子目录规模很小,先保证目录事实源、酒店隔离和确认校验一致。
- 目录 Service 增加内存缓存,缓存 key 包含
hotel_id、catalog_type、keyword、active_only、分页和过滤参数。 - 精确校验类查询,例如
findAccount(hotelId, accountCode)、isKnownRoomTypeCode(hotelId, code),使用单独短 TTL 缓存。 - TTL 建议 5 分钟;真实同步后可根据
catalog_version主动失效。 - 管理后台修改目录或同步 run 成功后,清理对应酒店和目录类型缓存。
- 多节点部署时,第一版可以依赖短 TTL;后续如目录变更频繁,再接 Redis 或事件广播失效。
响应应返回:
| 字段 | 中文说明 |
|---|---|
catalog_version |
当前目录版本,前端可用于调试和避免重复请求 |
catalog_source |
当前目录主要来源,例如 SYSTEM_MANAGED / PMS_SYNC |
stale |
当前是否为过期但可用的最后成功快照 |
warnings[] |
非阻塞警告,例如 PMS 同步失败但仍返回本地快照 |
11. 失败兜底
| 场景 | Lookup API 行为 | 确认 / 复核行为 |
|---|---|---|
| 目录有本地 Active 快照 | 返回 200 和可选项 | 按目录校验,通过后确认 |
| PMS 同步失败,但有上次成功快照 | 返回 200,stale=true,带 warning |
仍可按本地快照确认,并在审计或 payload 中保留目录版本 |
| PMS 同步失败且无本地快照 | 返回 200 空列表和 warning,或按后续实现返回明确错误 | 必填目录字段 fail closed,返回 V4_CATALOG_UNAVAILABLE 或 V4_FIELD_VALIDATION_FAILED |
| SuperAgent 输出未知非空 code | 任务卡进入 REVIEW_REQUIRED,fields[].validation_errors 指向该字段 |
用户必须选择已知 code;不能自由输入原值 |
| 目录 code 后续停用 | 已确认卡保持历史确认快照不回滚 | 新确认不能选择停用 code,除非后续设计允许历史兼容选择 |
| 前端提交未返回字段或自由 code | 后端忽略未开放字段;目录字段校验失败 | 不写入 confirmed_payload_json |
生产建议:
FIXED_SEED可用于 dev/test 和初始化导入。- 生产如果真实目录为空,不应静默接受固定种子;应让卡片进入复核或目录不可用错误,避免写入错误 PMS code。
12. 权限、酒店隔离和审计
12.1 Lookup 查询权限
第一版 lookup 查询建议:
| 接口 | 分类 | 权限 | 酒店隔离 | 审计 |
|---|---|---|---|---|
GET /api/reservation/lookups/accounts |
FRONTEND_USER |
RESERVATION_TASK_READ |
按用户可访问酒店校验 | 只读不写业务审计 |
GET /api/reservation/lookups/room-types |
FRONTEND_USER |
RESERVATION_TASK_READ |
按用户可访问酒店校验 | 只读不写业务审计 |
GET /api/reservation/lookups/rate-codes |
FRONTEND_USER |
RESERVATION_TASK_READ |
按用户可访问酒店校验 | 只读不写业务审计 |
复用 RESERVATION_TASK_READ 的原因:
- Lookup 是任务详情表单选项的辅助查询能力。
- 目录值本身不包含邮件正文、附件、AI payload 或 PMS Secret。
- 可以避免第一版为了表单下拉再新增一个普通用户权限码,降低前端角色配置复杂度。
12.2 目录维护权限
目录维护不在本 checkpoint 实现。后续如果做系统管理维护,建议新增:
RESERVATION_CATALOG_MANAGE
用于 Account、Market、Source、临时 Room Type、Rate Code 的系统管理维护页面。写操作必须记录管理审计或业务配置审计。
12.3 第三方接口边界
SuperAgent 当前不调用本 lookup API。SuperAgent 目录供给后续有两种方式:
- 线下或配置文件方式把目录版本给 SuperAgent。
- 单独设计机器接口,例如
GET /api/integrations/superagent/catalogs/...,使用 HMAC 鉴权和最小字段。
不得让 SuperAgent 使用前端 Bearer token 或前端 lookup API。
13. 前端使用方式
前端建议:
- 先读取 V4 订单任务详情。
- 遍历每张卡
fields[]。 - 只有字段
editable=true且control_type=select/lookup时才加载 lookup。 - 根据
options_source选择 lookup 接口。 - 搜索输入做 debounce,不一次性拉全量。
- 显示
stale=true或warnings[]时给用户非阻塞提醒。 - 用户提交确认或复核时只提交 code,不提交显示名、Market / Source 派生值或目录完整对象。
- 确认成功后以后端返回的
confirmed_payload_json/ 刷新详情为准更新页面。
前端禁止:
- 硬编码 PMS 房型或 Rate Code 全集。
- 把目录显示名当业务 code 提交。
- 绕过
fields[]自行补业务字段。 - 使用 lookup API 给 SuperAgent、AgentBus 或 Debug 链路拼接输入。
- 在浏览器保存目录中的外部 PMS ID、同步错误详情或任何 Secret。
14. 后续开发 checkpoint
| Checkpoint | 目标 | 主要交付 |
|---|---|---|
| M002-V4-CP11 | DB 管理目录与 Lookup API V1 | 新增 Account / Code 目录表、Repository、DirectoryService DB 实现、Account / Room Type / Rate Code lookup 查询接口、权限和测试 |
| M002-V4-CP12 | 前端 Lookup 接入 | V4 卡片字段渲染按 options_source 调用 lookup,替换固定种子硬编码选项,处理 stale / warning / 空目录 |
| M002-V4-CP13 | 目录管理后台 V1 | Account / Market / Source 管理,临时 Room Type / Rate Code 管理,RESERVATION_CATALOG_MANAGE 权限和管理审计 |
| M002-V4-CP14 | PMS / OPERA / OHIP 目录同步 | 同步 Adapter、同步 run 表、失败重试、最后成功快照、同步状态管理入口 |
| M002-V4-CP15 | SuperAgent 目录供给 | 明确目录版本如何给 SuperAgent,必要时新增机器目录接口或导出包 |
CP11 已作为后端第一步落地,因为它不依赖真实 PMS,也能让前端后续不再硬编码当前固定种子。
15. 仍需确认的问题
- Account 的第一版真实维护入口是否放在现有系统管理后台,还是先用导入 SQL / Excel 导入。
- Account code 是否继续使用本系统定义的稳定 code,例如
QBD_TRAVEL,还是必须对齐 PMS profile code。 - Market / Source 是否只允许随 Account 派生,还是未来允许用户在 Basic Information 中单独改选。
- Room Type 第一版真实目录是否先由系统管理维护,还是等 PMS / OHIP 同步后再替换。
- Rate Code 第一版是否只校验 code,还是需要按
booking_type、account_code、入住日期过滤。 - 生产是否允许
FIXED_SEED作为兜底,还是只允许 dev/test 使用。 - SuperAgent 是否需要读取目录;如果需要,是离线给目录包,还是新增 HMAC 机器接口。
在这些问题未确认前,CP11 仍可以先按 DB 管理目录 + 前端 lookup 查询实现,不接真实 PMS,也不替换 SuperAgent 输入契约。