Files
th-hotel-simple/docs/project/requirements/M003-identity-access-hotel-menu-v1.md
2026-07-09 19:31:20 +08:00

26 KiB
Raw Blame History

M003 Identity Access Hotel Menu 登录权限与酒店菜单底座 V1

文档信息

项目 内容
文档版本 0.2
日期 2026-07-09
状态 CP1 后端第一版已实现,管理后台和前端登录页待做
适用范围 本系统用户登录、角色权限、菜单、酒店授权和当前用户上下文底座
主要读者 产品、后端、前端、测试、后续协作 agent

1. 文档定位

本文记录 M003 登录权限与酒店菜单底座的第一版设计。该模块是平台通用能力,不属于 workflows.reservation,后续 Reservation、SourceMessage、审计、OPERA 执行等业务能力 都应通过该底座获取当前用户、权限和酒店上下文。

第一期目标是先让系统具备登录态、当前用户上下文、权限码、可访问酒店和可见菜单能力; 管理后台 CRUD 暂不实现,但必须在数据模型和接口边界上为后续扩展留好位置。

2. 已确认决策

  • 第一版采用用户名密码登录,本系统自己管理用户、角色、权限、菜单和酒店。
  • 登录态采用数据库 session token不使用 JWT。
  • 登录成功后后端生成随机 access_token,数据库只保存 token_hash
  • 前端请求使用 Authorization: Bearer <access_token>
  • 前端第一版将 access_token 保存在 sessionStorage,刷新同一浏览器会话可恢复,关闭浏览器后需要重新登录;不得放入 localStorage、URL 或普通日志。
  • session 默认有效期第一版为 12 小时,即 AUTH_SESSION_TTL_MINUTES=720,可按环境覆盖。
  • 用户和酒店关系采用第三种模型:
    • 管理员可访问全部酒店。
    • 普通用户绑定一个或多个酒店。
    • 普通用户有默认酒店,可在授权酒店之间切换。
  • 当前前端已有菜单入口为订单列表、任务队列和 Debug EML订单详情、任务详情和邮件会话属于隐藏详情路由不作为菜单返回。
  • 初始超级管理员通过环境变量初始化:
    • AUTH_BOOTSTRAP_ADMIN_USERNAME
    • AUTH_BOOTSTRAP_ADMIN_PASSWORD
    • AUTH_BOOTSTRAP_ADMIN_DISPLAY_NAME
  • 系统中已存在超级管理员后,不再使用环境变量覆盖管理员账号或密码。
  • 第一期开启登录和权限底座,但不强制拦截现有业务接口。
  • 管理后台还没有做,必须明确后置。

3. 核心目标

第一期要解决以下问题:

  • 前端可以登录、登出,并获取当前用户信息。
  • 前端可以拿到当前用户可访问酒店、默认酒店和可见菜单。
  • 后端可以从 token 解析当前用户上下文。
  • 后端可以判断当前用户是否拥有某个权限码。
  • 后端可以判断当前用户是否可访问某个 hotel_id
  • 审计 actor 后续可以从当前用户上下文读取,不再依赖本地占位值。
  • SourceMessage 原文读取等高敏能力后续可以从临时 access-key 逐步迁移到权限码。

4. 非目标范围

第一期不做以下能力:

  • 用户新增、编辑、禁用、重置密码接口。
  • 角色新增、编辑、删除接口。
  • 权限分配接口。
  • 菜单新增、编辑、排序接口。
  • 酒店新增、编辑、停用接口。
  • 用户绑定酒店管理接口。
  • 管理后台页面。
  • 强制要求现有 Reservation / SourceMessage 业务接口必须带 token。
  • 外部 SSO、OIDC、企业微信、LDAP 或网关注入用户。
  • JWT refresh token 体系。
  • 密码找回、短信验证码、MFA、多端设备管理。

这些能力后续作为管理后台和安全增强 checkpoint 独立设计。

5. 模块边界

后端建议拆成平台模块:

platform.identity
// 用户、登录、session、当前用户上下文

platform.access
// 角色、权限、用户角色、权限判断

platform.navigation
// 菜单树、菜单权限、当前用户可见菜单

platform.hotel
// 酒店基础信息、用户可访问酒店、默认酒店

platform.security
// 请求过滤器、Bearer token 解析、可选鉴权上下文

中文说明:

模块 职责 不负责
platform.identity 用户账号、登录、登出、session token、当前用户 不维护业务订单和任务
platform.access 角色、权限码、用户角色、权限判断 不直接决定菜单 UI 样式
platform.navigation 菜单树、菜单权限、用户可见菜单 不做业务接口权限校验
platform.hotel 酒店基础资料、用户酒店授权、默认酒店 不保存订单、任务或邮件正文
platform.security 请求级 token 解析、当前用户上下文注入 不替代 SuperAgent / AgentBus 服务间鉴权

目录仍遵守当前后端规范:

<module>
├── control
├── service
│   └── impl
├── domain
├── mapper
├── repository
└── common
    ├── dto
    ├── request
    ├── result
    └── enums

6. 数据模型建议

6.1 用户表 platform_user

字段 中文说明
id 用户内部 ID
username 登录用户名,全局唯一
password_hash 密码哈希,禁止保存明文密码
display_name 用户展示名称
email 邮箱,可为空
phone 手机号,可为空
user_status 用户状态,例如 ACTIVEDISABLED
super_admin 是否超级管理员
password_changed_at 最近密码变更时间
last_login_at 最近登录时间
created_at / updated_at 创建和更新时间

密码哈希建议使用 BCrypt 或同等级单向哈希算法。日志、错误响应和审计不得输出密码、密码哈希或 token。

6.2 Session 表 platform_user_session

字段 中文说明
id session 内部 ID
user_id 所属用户 ID
token_hash access token 哈希,数据库不保存明文 token
session_status session 状态,例如 ACTIVEREVOKEDEXPIRED
issued_at 签发时间
expires_at 过期时间
revoked_at 注销或撤销时间
last_seen_at 最近使用时间
client_ip 登录或最近请求 IP第一版可为空
user_agent_summary User-Agent 摘要,第一版可为空

第一版 session 过期时间通过配置控制,例如 AUTH_SESSION_TTL_MINUTES,默认使用 720 分钟。

6.3 角色表 platform_role

字段 中文说明
id 角色内部 ID
role_code 稳定角色代码,例如 SYSTEM_ADMINRESERVATION_OPERATOR
role_name 角色展示名称
role_status 角色状态
system_builtin 是否系统内置角色
created_at / updated_at 创建和更新时间

6.4 权限表 platform_permission

字段 中文说明
id 权限内部 ID
permission_code 稳定权限代码
permission_name 权限展示名称
permission_group 权限分组,例如 RESERVATIONSOURCE_MESSAGESYSTEM
permission_status 权限状态
system_builtin 是否系统内置权限

权限码只能使用稳定英文代码,不使用中文或菜单文案做业务判断。

6.5 用户角色表 platform_user_role

字段 中文说明
id 关系内部 ID
user_id 用户 ID
role_id 角色 ID
created_at 创建时间

6.6 角色权限表 platform_role_permission

字段 中文说明
id 关系内部 ID
role_id 角色 ID
permission_id 权限 ID
created_at 创建时间

6.7 酒店表 platform_hotel

字段 中文说明
id 酒店内部 ID
hotel_id 业务酒店 ID例如 HOTEL-TEST
hotel_name 酒店展示名称
hotel_status 酒店状态,例如 ACTIVEDISABLED
time_zone 酒店本地时区,用于入住日期、离店日期等酒店本地业务日期
sort_order 排序号
created_at / updated_at 创建和更新时间

现有业务表中的 hotel_id 继续作为业务上下文 ID。用户酒店权限必须围绕该字段校验。

6.8 用户酒店授权表 platform_user_hotel

字段 中文说明
id 关系内部 ID
user_id 用户 ID
hotel_id 酒店业务 ID
default_hotel 是否该用户默认酒店
created_at 创建时间

规则:

  • 普通用户至少应有一个可访问酒店。
  • 普通用户最多只能有一个默认酒店。
  • 超级管理员不需要为每个酒店插授权关系,默认可访问全部启用酒店。
  • 业务接口收到 hotel_id 时,后续强制鉴权阶段必须校验当前用户是否可访问该酒店。

6.9 菜单表 platform_menu

字段 中文说明
id 菜单内部 ID
parent_id 父菜单 ID根菜单为空
menu_code 稳定菜单代码
menu_name 菜单展示名称
menu_type 菜单类型,例如 GROUPPAGEACTION
route_path 前端路由路径
component_key 前端组件标识,第一版可为空
icon_key 前端图标标识
permission_code 访问该菜单需要的权限码,可为空
sort_order 菜单排序
visible 是否可见
menu_status 菜单状态

菜单权限只决定入口是否可见,不替代后端接口权限校验。

7. 初始内置数据

第一期可内置以下角色:

角色代码 中文说明
SYSTEM_ADMIN 系统管理员,可访问全部酒店和系统能力
RESERVATION_OPERATOR 预订处理员,可处理 Reservation 任务
RESERVATION_VIEWER 预订只读查看员,只能查看任务、订单和邮件摘要

第一期建议内置以下权限码:

权限码 中文说明
SOURCE_MESSAGE_READ 查看来源消息安全摘要
SOURCE_MESSAGE_ORIGINAL_READ 查看来源消息原文和媒体 URL
RESERVATION_ORDER_READ 查看订单
RESERVATION_TASK_READ 查看任务
RESERVATION_TASK_EDIT 保存任务草稿
RESERVATION_TASK_CONFIRM 最终确认任务
RESERVATION_OPERA_SIM_EXECUTE 执行或重试 OPERA 模拟
RESERVATION_AUDIT_READ 查看任务审计
HOTEL_SWITCH 在授权酒店之间切换
SYSTEM_AUTH_READ 读取当前用户、菜单和权限信息
SYSTEM_USER_MANAGE 用户管理,第一期不开放管理接口
SYSTEM_ROLE_MANAGE 角色权限管理,第一期不开放管理接口
SYSTEM_MENU_MANAGE 菜单管理,第一期不开放管理接口
HOTEL_MANAGE 酒店管理,第一期不开放管理接口
SYSTEM_DEBUG_EML_RUN 访问 Debug EML 上传到 SuperAgent 调试页面

第一期内置角色权限矩阵:

角色代码 默认权限
SYSTEM_ADMIN 全部权限,包括当前第一期权限和后续管理类占位权限
RESERVATION_OPERATOR SYSTEM_AUTH_READHOTEL_SWITCHRESERVATION_ORDER_READRESERVATION_TASK_READRESERVATION_TASK_EDITRESERVATION_TASK_CONFIRMRESERVATION_OPERA_SIM_EXECUTERESERVATION_AUDIT_READSOURCE_MESSAGE_READSOURCE_MESSAGE_ORIGINAL_READ
RESERVATION_VIEWER SYSTEM_AUTH_READHOTEL_SWITCHRESERVATION_ORDER_READRESERVATION_TASK_READRESERVATION_AUDIT_READSOURCE_MESSAGE_READ

中文说明:

  • SYSTEM_ADMIN 用于系统初始化和调试能力,第一版可访问所有启用酒店。
  • RESERVATION_OPERATOR 需要查看邮件原文和附件外链来处理任务,因此第一版包含 SOURCE_MESSAGE_ORIGINAL_READ
  • RESERVATION_VIEWER 只读查看订单、任务、审计和来源消息安全摘要;不允许保存、确认、执行 OPERA 模拟,也不允许访问 Debug EML。
  • SYSTEM_DEBUG_EML_RUN 第一版只授予 SYSTEM_ADMIN,避免普通业务用户触发 SuperAgent 调试链路。

第一期可内置菜单,需和当前前端路由保持一致:

菜单代码 路由 权限码 图标 Key 可见性 中文说明
RESERVATION_ORDERS /reservation/orders RESERVATION_ORDER_READ pi pi-list 可见 订单列表
RESERVATION_TASKS /reservation/tasks RESERVATION_TASK_READ pi pi-check-square 可见 任务队列
DEBUG_EML_SUPERAGENT /debug/eml-superagent SYSTEM_DEBUG_EML_RUN pi pi-upload 有权限时可见 Debug EML 上传到 SuperAgent
SOURCE_MESSAGES /source-messages SOURCE_MESSAGE_READ pi pi-envelope 第一版隐藏 来源消息独立页面,前端尚未实现
SYSTEM_SETTINGS /system SYSTEM_USER_MANAGE pi pi-cog 第一版隐藏 系统设置入口,占位为后续管理后台使用

当前前端隐藏详情路由不作为菜单返回:

路由 中文说明
/reservation/orders/{orderId} 订单详情,通过订单列表或任务入口进入
/reservation/tasks/{taskId} 任务详情,通过任务列表或订单时间线进入
/reservation/source-messages/{sourceMessageId}/conversation 邮件会话详情,通过任务或订单详情来源入口进入

菜单数据应允许后续通过管理后台维护。第一版 icon_key 先兼容当前 PrimeIcons class如果后续换成后端稳定图标代码前端再统一做映射。

8. 接口契约第一版

8.1 登录

POST /api/auth/login

请求体:

{
  "username": "admin",
  "password": "password"
}

成功响应:

{
  "access_token": "plain-token-only-return-once",
  "token_type": "Bearer",
  "expires_at": "2026-07-09T12:00:00Z",
  "user": {
    "id": "1900000000000000001",
    "username": "admin",
    "display_name": "系统管理员",
    "super_admin": true
  },
  "default_hotel_id": "HOTEL-TEST",
  "hotels": [
    {
      "hotel_id": "HOTEL-TEST",
      "hotel_name": "测试酒店",
      "time_zone": "Asia/Bangkok",
      "default_hotel": true
    }
  ],
  "permissions": [
    "SYSTEM_AUTH_READ",
    "RESERVATION_ORDER_READ",
    "RESERVATION_TASK_READ"
  ],
  "menus": [
    {
      "menu_code": "RESERVATION_ORDERS",
      "menu_name": "订单列表",
      "route_path": "/reservation/orders",
      "component_key": "ReservationOrders",
      "icon_key": "pi pi-list",
      "permission_code": "RESERVATION_ORDER_READ",
      "sort_order": 10
    },
    {
      "menu_code": "RESERVATION_TASKS",
      "menu_name": "任务队列",
      "route_path": "/reservation/tasks",
      "component_key": "ReservationTasks",
      "icon_key": "pi pi-check-square",
      "permission_code": "RESERVATION_TASK_READ",
      "sort_order": 20
    },
    {
      "menu_code": "DEBUG_EML_SUPERAGENT",
      "menu_name": "Debug EML",
      "route_path": "/debug/eml-superagent",
      "component_key": "DebugEmlSuperAgent",
      "icon_key": "pi pi-upload",
      "permission_code": "SYSTEM_DEBUG_EML_RUN",
      "sort_order": 30
    }
  ]
}

说明:

  • 登录失败统一返回用户名或密码错误,不暴露账号是否存在。
  • 禁用用户不能登录。
  • token 明文只在登录成功响应中返回一次。
  • 数据库只保存 token hash。
  • 前端第一版使用 sessionStorage 保存 token退出登录时必须清理本地 token。
  • 超级管理员如果拥有 SYSTEM_DEBUG_EML_RUNmenus[] 可包含 /debug/eml-superagent;普通预订角色不返回该菜单。

8.2 登出

POST /api/auth/logout
Authorization: Bearer <access_token>

行为:

  • 将当前 session 标记为 REVOKED
  • 重复登出可以幂等返回成功。

8.3 当前用户

GET /api/auth/me
Authorization: Bearer <access_token>

返回:

{
  "user": {
    "id": "1900000000000000001",
    "username": "admin",
    "display_name": "系统管理员",
    "super_admin": true
  },
  "default_hotel_id": "HOTEL-TEST",
  "hotels": [
    {
      "hotel_id": "HOTEL-TEST",
      "hotel_name": "测试酒店",
      "time_zone": "Asia/Bangkok",
      "default_hotel": true
    }
  ],
  "permissions": [
    "RESERVATION_TASK_READ"
  ],
  "menus": [
    {
      "menu_code": "RESERVATION_TASKS",
      "menu_name": "任务列表",
      "route_path": "/reservation/tasks",
      "component_key": "ReservationTasks",
      "icon_key": "pi pi-check-square",
      "permission_code": "RESERVATION_TASK_READ",
      "sort_order": 20
    }
  ]
}

说明:

  • GET /api/auth/me 是前端启动后恢复登录态、菜单和酒店上下文的核心接口。
  • 超级管理员的 hotels 可返回全部启用酒店。
  • 普通用户只返回授权酒店。

9. 现有业务接口接入策略

第一期不强制拦截现有业务接口。

行为规则:

  • /api/auth/login 不需要 token。
  • /api/auth/logout/api/auth/me 需要 token。
  • 现有 Reservation / SourceMessage 查询和操作接口第一期继续保持未登录可访问,避免打断当前前后端联调。
  • 如果现有业务接口请求带合法 token后端可解析当前用户上下文。
  • 如果现有业务接口未带 token后端按匿名上下文处理行为保持现状。
  • 如果现有业务接口带了无效 token第一期可对非强制鉴权接口忽略该 token避免旧前端因为缓存脏 token 被整体打断。
  • Debug EML 上传接口当前仍使用 X-TH-Hotel-Debug-Upload-Key 受控访问M003 第一版只决定菜单是否可见,不把 debug access key 下发给前端。
  • 后续强制鉴权 checkpoint 再逐步将业务接口改为必须登录和权限校验。

后续强制鉴权时应按接口分批启用:

  1. 查询类接口先要求登录和酒店权限。
  2. 写操作再要求具体操作权限。
  3. 邮件原文读取迁移到 SOURCE_MESSAGE_ORIGINAL_READ
  4. OPERA 模拟迁移到 RESERVATION_OPERA_SIM_EXECUTE
  5. 审计查询迁移到 RESERVATION_AUDIT_READ

10. 酒店上下文规则

第一期登录态接入后,后端应提供统一的酒店上下文解析能力。

规则:

  • 请求显式传 hotel_id 时,后续强制鉴权阶段必须校验用户是否可访问该酒店。
  • 请求未传 hotel_id 时,普通用户使用默认酒店。
  • 超级管理员不传 hotel_id 时:
    • 管理后台可查询全部酒店。
    • 业务页面建议仍使用默认酒店或要求前端选择酒店,避免误查全部数据。
  • SuperAgent / AgentBus 服务间接口仍使用 HMAC / token 等服务间鉴权,不走人工用户登录态。
  • SuperAgent / AgentBus 请求中的 hotel_id 后续应校验酒店是否存在并处于启用状态。

11. 安全要求

  • 密码不能明文保存。
  • token 不能明文入库。
  • token、密码和密码哈希不能出现在日志、错误响应、审计详情或前端配置。
  • 登录失败不暴露账号是否存在。
  • session 需要过期时间。
  • 登出后 token 必须失效。
  • 管理员初始化密码只能来自环境变量或部署 Secret。
  • 前端不能保存任何服务端 Secret。
  • 菜单隐藏不能替代后端权限校验。

12. 审计和 actor 迁移

当前部分业务审计仍使用本地占位 actor。M003 第一期开启当前用户上下文后,后续业务模块应逐步迁移:

场景 第一版迁移策略
用户保存任务草稿 有 token 时记录当前用户;无 token 时继续兼容本地占位
用户最终确认任务 有 token 时记录当前用户;无 token 时继续兼容本地占位
Fallback 转换 有 token 时记录当前用户
OPERA 模拟执行 / 重试 有 token 时记录当前用户
邮件原文读取 后续从 access-key 迁移到 SOURCE_MESSAGE_ORIGINAL_READ 权限

第一期不强制改完所有业务审计 actor但需要提供可复用的当前用户上下文接口。

13. 配置项建议

配置项 是否 Secret 中文说明
AUTH_BOOTSTRAP_ADMIN_USERNAME 初始超级管理员用户名
AUTH_BOOTSTRAP_ADMIN_PASSWORD 初始超级管理员密码,只用于首次初始化
AUTH_BOOTSTRAP_ADMIN_DISPLAY_NAME 初始超级管理员展示名
AUTH_SESSION_TTL_MINUTES session 有效期,第一版默认 720 分钟
AUTH_BOOTSTRAP_DEFAULT_HOTEL_ID 初始默认酒店 IDdev/test 可使用 HOTEL-TEST 或当前环境约定值
AUTH_BOOTSTRAP_DEFAULT_HOTEL_NAME 初始默认酒店名称
AUTH_BOOTSTRAP_DEFAULT_HOTEL_TIME_ZONE 初始默认酒店时区

生产环境必须通过部署 Secret 或环境变量注入管理员初始密码,不得写入仓库、镜像或普通文档。

当前后端已按环境拆分配置:

环境 推荐变量前缀 默认酒店
dev AUTH_DEV_*,并兼容 AUTH_* 通用变量 HOTEL-DEV / 开发酒店
test AUTH_TEST_*,并兼容 AUTH_* 通用变量 HOTEL-TEST / 测试酒店
prod AUTH_PROD_*,并兼容 AUTH_* 通用变量 必须由生产 Secret 显式配置

例如 test 环境可配置:

AUTH_TEST_BOOTSTRAP_ADMIN_USERNAME=admin
AUTH_TEST_BOOTSTRAP_ADMIN_PASSWORD=<测试环境初始密码>
AUTH_TEST_BOOTSTRAP_ADMIN_DISPLAY_NAME=系统管理员
AUTH_TEST_BOOTSTRAP_DEFAULT_HOTEL_ID=HOTEL-TEST
AUTH_TEST_BOOTSTRAP_DEFAULT_HOTEL_NAME=测试酒店
AUTH_TEST_BOOTSTRAP_DEFAULT_HOTEL_TIME_ZONE=Asia/Bangkok
AUTH_TEST_SESSION_TTL_MINUTES=720

说明:

  • 启动初始化发现系统中已经存在超级管理员后,不会继续用环境变量覆盖管理员用户名或密码。
  • 数据库 platform_user_session 只保存 token_hash,不保存明文 token。
  • 当前后端提供可选 Bearer token 解析,现有 Reservation / SourceMessage 业务接口第一版仍不强制登录。

14. Checkpoint 建议

CP1登录和权限底座

状态:后端第一版已实现。

范围:

  • Flyway 创建用户、角色、权限、菜单、酒店和 session 表。
  • 内置角色、权限、菜单基础数据。
  • 支持环境变量初始化超级管理员和默认酒店。
  • 实现登录、登出、当前用户接口。
  • 实现数据库 session token。
  • 实现可选 token 解析,不强制拦截现有业务接口。
  • 提供当前用户上下文、权限判断和酒店授权判断服务。

不做:

  • 管理后台 CRUD。
  • 强制拦截现有业务接口。
  • 前端登录页面。
  • 外部 SSO。

CP2前端登录和菜单接入

范围:

  • 前端登录页。
  • 使用 sessionStorage 保存 access token登出或 token 失效时清理。
  • 启动时调用 /api/auth/me
  • 根据 menus[] 渲染菜单,替换当前 ReservationAppShell 中订单列表、任务队列、Debug EML 的硬编码菜单。
  • 根据 hotels[] 支持酒店选择或展示默认酒店。

CP3业务接口逐步强制鉴权

范围:

  • Reservation 查询接口校验登录和酒店权限。
  • Reservation 写接口校验具体权限。
  • SourceMessage 原文读取迁移到 SOURCE_MESSAGE_ORIGINAL_READ
  • 审计 actor 全面迁移到当前用户。

CP4管理后台接口

范围:

  • 用户管理。
  • 角色管理。
  • 权限分配。
  • 菜单管理。
  • 酒店管理。
  • 用户酒店授权。

该 checkpoint 还没有做,后续流程梳理或目标模式时必须提醒。

15. 待确认问题

问题 建议 状态
session 默认有效期是多少? 第一版使用 12 小时,即 AUTH_SESSION_TTL_MINUTES=720,可配置 已确认
初始默认酒店在 dev/test/prod 的具体 ID 和名称是什么? dev/test 先沿用现有 HOTEL-DEV / HOTEL-TEST 习惯,生产必须配置真实酒店 待确认
前端菜单图标使用什么 icon key 第一版兼容当前 PrimeIcons class例如 pi pi-listpi pi-check-squarepi pi-upload 已确认
前端 token 保存在哪里? 第一版使用 sessionStorage,不使用 localStorage 已确认
Debug EML 菜单谁能看到? 第一版仅 SYSTEM_ADMIN 通过 SYSTEM_DEBUG_EML_RUN 看到 已确认
现有业务接口强制鉴权从哪一批开始? M003 CP3 单独确认 后置
管理后台什么时候做? M003 CP4 单独确认 后置

16. 目标模式提示词建议

如果要进入目标模式开发 CP1可以这样说

进入目标模式,目标:实现 M003 CP1 登录和权限底座。

范围:
1. 新增用户、角色、权限、菜单、酒店、用户酒店授权、session 的 Flyway 表结构。
2. 初始化内置权限、角色权限矩阵、菜单、默认酒店和超级管理员。
3. 实现用户名密码登录、登出、当前用户接口。
4. 登录态使用数据库 session token数据库只保存 token_hash。
5. session 默认有效期 12 小时,支持 `AUTH_SESSION_TTL_MINUTES` 覆盖。
6. 初始化菜单需和当前前端路由对齐:
   - `RESERVATION_ORDERS` -> `/reservation/orders`
   - `RESERVATION_TASKS` -> `/reservation/tasks`
   - `DEBUG_EML_SUPERAGENT` -> `/debug/eml-superagent`
   - 订单详情、任务详情、邮件会话是隐藏路由,不作为菜单返回。
7. `SYSTEM_DEBUG_EML_RUN` 第一版只授予 `SYSTEM_ADMIN`。
8. 实现当前用户上下文、权限判断和酒店授权判断服务。
9. 第一版不强制拦截现有 Reservation / SourceMessage 业务接口;请求带合法 token 时可识别当前用户,未带 token 时保持现有行为。
10. Debug EML 上传接口仍使用 `X-TH-Hotel-Debug-Upload-Key`M003 CP1 只控制菜单可见性,不下发 debug key。
11. 保持当前后端代码规范control、service、service.impl、domain、mapper、repository、common.request、common.result、common.dto、common.enums。
12. Controller、Service、ServiceImpl 方法加中文注释Entity 字段加中文注释。
13. 补充测试。

不做:
1. 用户 / 角色 / 权限 / 菜单 / 酒店管理后台 CRUD。
2. 前端登录页面。
3. 强制拦截现有业务接口。
4. 外部 SSO / JWT / MFA。
5. 真实 OPERA / OHIP。

完成后:
更新文档code review运行测试中文提交。