19 KiB
19 KiB
14 DMS 门禁集成审计与设计决策一页纸总结 (Decision Summary)
面向对象:项目负责人、架构指导老师、业务决策评审委员会 核心宗旨:以最短篇幅、最清晰视角,讲透“现状、能力、接入边界、推荐架构与实施规划”。
1. 当前系统有什么?(Current RailwaySystem Assets)
- 业务与数据基线:
- 当前生产分支基于
adcf930e,已完成 V2 数据库结构迁移。 - 物理表层:
train_dormitory_info(宿舍楼栋/房间台账)、train_accommodation(学员参训住宿分配事实表)、train_dorm_auth(门禁授权表,外键绑定accommodation_id)已在 Kingbase 物理库建表。 - 业务逻辑层:已具备完整的培训计划编排、学员报到核验、宿舍入住分配与床位容量实时统计能力。
- 当前生产分支基于
- 本地模型漂移与前置对齐要求 (
LOCAL_DOMAIN_ALIGNMENT_REQUIRED = YES):train_accommodation:DB 物理表已建,但 Java 层尚无对应的实体类、Mapper 与业务 Service,未形成完整业务层。train_dorm_auth:DB 已升级为以accommodation_id为外键的 V2 结构,但 Java 实体类与 XML Mapper 仍残留 V1 字段(student_id,plan_id,dorm_id)。- 决策红线:在真正编写外部 DMS Adapter 之前,必须在 Wave 0 优先完成本地住宿与门禁授权领域模型对齐,严禁将外部适配器直接架设在漂移模型上。
2. DMS 平台能提供什么?(DMS IoT Platform Capabilities)
外部 DMS 智能门锁平台(https://dms.dmsiot.com)具备完整的 RESTful 接口体系:
- 楼栋-楼层-房间-门锁全层级资产查询(可精确匹配房间获取
placeId,支持一房多锁)。 - 多模态电子钥匙下发能力:
- 在线限时密码 (Online Password):系统可生成 4~8 位纯数字密码(Pilot 建议采用 6 位限时密码),指定起止有效时间,支持远程主动注销。
- 在线实体芯片卡 (Online Card):支持将学员 IC/M1 卡按小端十六进制编码下发至锁具,支持远程主动注销。
- 二维码/手机钥匙 (QR Key):端点已定义 (
POST /rest/doorlock/qrcode/create与POST /rest/qrcode/delete),分类为DOCUMENTED,但返回体存在数据污染且无具体二维码载荷,适用性归为NEEDS_BUSINESS_CONFIRMATION。
- 低功耗异步执行与对账体系:门锁基于电池无线通信,下发指令后返回
operationId,要求 10 秒后通过接口查询终态。 - 设备运行指标:提供门锁电池电量、信号强度及门锁开门记录流水拉取。
3. 一期建议先接什么?暂时不接什么?(Scope Boundary)
+-------------------------------------------------------------------------------+
| 一期重点纳入 (P0 / P1) |
| 1. 认证鉴权: Token 内存单飞排他锁缓存 + 滑动刷新 + 401 单次重试自愈 |
| 2. 房源映射: 本地宿舍与 DMS placeId / lockId 的预绑定持久化 (支持一房多锁) |
| 3. 首选凭据: 【在线限时密码】(零硬件与发卡器依赖, 支持4~8位/推荐6位, 随时主动撤销) |
| 4. 异步对账: 后台调度器 10 秒后异步轮询 operationId,消除 HTTP 线程阻塞 |
| 5. 换房补偿: 严格遵循"先发新房权限、确认生效后再撤旧房"原则,避免学员无处可住 |
| 6. 结训撤权: 培训结束主动派发 Revoke 指令,同时以 validUntil 作为有效期边界兜底 |
| 7. 设备巡检: 门锁电量与信号查询 (P1),辅助宿管员发现低电量设备 |
+-------------------------------------------------------------------------------+
▲
【严格划清边界】
▼
+-------------------------------------------------------------------------------+
| 一期明确排除 (P2 / Out of Scope / Needs Confirmation) |
| 1. 取电开关全套接口 (P2): 涉及强电改造,与学员核心学籍住宿无关,暂缓接入 |
| 2. 远程网络开锁 (P2): 属于高危主动开门操作,一期严格封存,仅设计受控两票制应急方案 |
| 3. 二维码钥匙 (Needs Biz Confirm): 接口已文档化但载荷污染,一期不作首选方案 |
| 4. 离线密码与离线发卡 (Out of Scope): 缺乏可靠远程主动撤销机制,增加现场运维负担 |
+-------------------------------------------------------------------------------+
4. 需要向甲方与业务负责人确认的核心问题 (Blocking Decisions)
- 下发触发时机 (Q-BLK-03):
- 推荐意见:学员在现场完成《报到核验》后自动触发门禁下发。确保人已到校才给钥匙,杜绝未报到人员提前进房。
- 首期钥匙类型 (Q-BLK-02):
- 推荐意见:首选采用系统派发 6 位在线限时密码(学员移动端个人中心受控查看);若后续统一下发实体卡,可平滑启用在线卡片模式。
- 主数据权威归属 (Q-NON-01):
- 推荐意见:坚决以 RailwaySystem 作为住宿与房间主数据,DMS 仅作为外部执行端,严禁让 DMS 状态覆盖本地系统。
- 现场网络连通性与沙箱 (Q-BLK-01 & Q-BLK-05):
- 生产环境机房是否允许访问公网
dms.dmsiot.com?供应商必须提供包含测试网关与实验台门锁的独立联调测试沙箱。
- 生产环境机房是否允许访问公网
- 设备离线时
validUntil过期语义 (Q-BLK-06):- 门锁离线断网时,到达
validUntil是否由锁端本地时钟强制失效?需供应商提供硬件保证级别说明。
- 门锁离线断网时,到达
5. 推荐技术架构设计
[前端 Accommodation / 个人中心]
│
▼
[业务领域层: 住宿分配 / 换房补偿 / 报到联动] <--- 绝对 Source of Truth
│
▼ (通过强类型 DTO,完全屏蔽外部厂商细节)
[中立网关接口: DoorAccessGateway (grant / revoke / query)]
│
▼ (SPI 模式)
[DMS 集成适配器: DmsDoorAccessGateway]
├── DmsTokenManager: 进程级单飞排他锁 (防并发覆盖踩踏)
├── 细分 HTTP 客户端: PlaceClient / DoorLockClient / KeyClient / OpClient
└── DmsOperationPoller: 后台 10 秒对账调度器 (解除 HTTP 线程阻塞)
│
▼ (HTTPS / Cookie 传递 token)
[外部 DMS 物联网平台: https://dms.dmsiot.com]
6. 后续 R.3B 四阶段推进路线图 (Four Waves, 约 15~16 人天)
- Wave 0: Local Domain Alignment (本地领域模型对齐,3天):
- 实现
TrainAccommodationJava 实体/Mapper/Service;升级并清洗TrainDormAuth对齐 V2 数据库;确立住宿事实与门禁授权的清晰边界。
- 实现
- Wave 1: External Mapping & Operation Persistence (外部映射与持久化,2天):
- 创建
train_external_resource_mapping与train_external_operation物理表及 Migration 脚本;落地双层状态机模型。
- 创建
- Wave 2: DMS Adapter & Mock Tests (DMS 适配器与离线仿真,5天):
- 配置与环境变量绑定;
DmsTokenManager单飞排他锁并发控制;细分 HTTP 客户端;在线密码/卡片适配器;10 秒轮询调度器;WireMock 22 项单测全覆盖。
- 配置与环境变量绑定;
- Wave 3: Business Orchestration & UI & Sandbox (业务编排、界面与现场验收,5~6天):
- 报到联动授权下发;“先发新房后撤旧房”换房补偿;退训/结训撤权;管理端门禁综合视图;学员端 30 秒倒计时密码受控查看;现场实验台沙箱 E2E 闭环验收。
6.1 Wave 0 Implementation Result (本地领域模型闭环)
- 基线与状态:
- 成功消除数据库 V2 模型与 Java 代码之间的全部结构漂移。
- 严格保持 0 DMS 耦合:无 DmsClient、无 TokenManager、无外部调用、无假设备成功。
- 保持 Kingbase 生产库只读,零 Migration(
MIGRATION_REQUIRED = NO)。 - 交付本地领域模型:
TrainAccommodation与升级后的TrainDormAuth。
6.2 Wave 0.1 Accommodation History & Final Checkpoint Decision (基数模型升级与终态)
- 核心基数关系冻结:
Enrollment 1:N Accommodation History:允许学员产生多次历史住宿记录(调房/换房留痕)。Enrollment 1:0..1 Active Accommodation:同一时刻最多一条有效住宿(accommodation_status IN (0, 1))。Accommodation 1:0..1 DoorAuthorization:门禁授权强引用住宿实体。TIME_RANGE_SUPPORT = LIMITED:当前 Kingbase 物理表仅有assigned_time,无start_time/end_time列,时间窗口支持为有限支持。
- 006 Migration 方案设计:
- 脚本路径:
RuoYi-Vue/sql/system/kingbase/006_accommodation_history_constraint.sql。 - 安全序号:
006(001-003 为基线,004-005 已被 R.2 分支占用)。 - 迁移安全护栏:前置重复 active 检查抛异常、仅在定义匹配时安全 DROP
uq_accommodation_enroll、创建uq_accommodation_enroll_active局部唯一索引(WHERE accommodation_status IN (0, 1))、全流程幂等。 - 生产执行纪律:禁止在生产库执行 006 迁移脚本,本 Wave 仅作资产与契约验证储备。
- 脚本路径:
- 质量与构建验收:
- 单元与契约测试总数:174 项,全部 PASS(0 failures, 0 errors)。
- Maven
clean test与clean package均顺利构建成功。
6.3 Wave 1 External Resource Mapping & Operation Persistence (Wave 1 implemented)
- 阶段状态:Wave 1 implemented。
- 架构决策与模型基线:
- 资源映射模型:
RESOURCE_MAPPING_REFERENCE_MODEL = DORM_ID_FK,以dorm_id外键强关联train_dormitory_info。 - 房间映射基数:
ROOM_MAPPING_CARDINALITY = Dormitory 1:0..1 Active Room (Dormitory 1:N History)。 - 门锁映射基数:
LOCK_MAPPING_CARDINALITY = Dormitory 1:0..N DoorLocks(支持一房多锁)。 - 外部资源防冲突:
EXTERNAL_RESOURCE_ACTIVE_UNIQUENESS = Vendor + External Resource ID + Active Unique。 - 操作流水模型:
OPERATION_REFERENCE_MODEL = DOOR_AUTH_ID_FK,以door_auth_id外键强关联train_dorm_auth。 - 授权操作基数:
DOOR_AUTH_OPERATION_CARDINALITY = DoorAuthorization 1:N ExternalOperation。 - 操作类型与状态分离:
OPERATION_TYPE_MODEL = GRANT, REVOKE;EXTERNAL_OPERATION_STATUS_MODEL = CREATED, REQUESTED, ACCEPTED, PENDING, RETRY_WAIT, SUCCESS, FAILED, TIMEOUT(REVOKED属于DoorAuthorization业务凭据状态,不属于单次操作执行结果,注销操作的执行结果为operation_type=REVOKE达成SUCCESS)。 - 本地幂等模型:
IDEMPOTENCY_MODEL基于idempotency_key唯一索引防重。 - 轮询检索支持:
PENDING_OPERATION_QUERY准备就绪,本 Wave 保持 0 调度器运行。
- 资源映射模型:
- 安全红线保持:
- 敏感字段:
SENSITIVE_OPERATION_FIELD_COUNT = 0。 - 外部耦合:
DMS_HTTP_CLIENT_COUNT = 0,DMS_TOKEN_MANAGER_COUNT = 0。 - 生产数据库:只读保护,
PRODUCTION_DB_MODIFIED? NO。
- 敏感字段:
- Migration 证据与准入准则:
008_RUNTIME_FIRST_RUN = NOT_EXECUTED,008_RUNTIME_SECOND_RUN = NOT_EXECUTED(生产与非隔离库绝不盲跑 DDL)。008_CONTRACT_TEST = PASS,008_IDEMPOTENCY_STATIC_VERIFICATION = PASS。RUNTIME_MIGRATION_GATE_BEFORE_PRODUCTION = REQUIRED(在正式生产投产前必须在隔离 Kingbase 完成双跑验证)。
- 测试与验证指标:
- 测试套件全部通过:
TOTAL_TEST_COUNT = 203(ruoyi-train: 175, ruoyi-admin: 28),Failures = 0, Errors = 0, Skipped = 0。 - Maven 构建:
clean test与clean package均SUCCESS。 - 代码格式校验:
git diff --check = PASS。 - 阶段评审状态:
R3_WAVE1_REVIEW = PASS。 - 提交状态:
R3_WAVE1_COMMIT = COMMITTED(SHA: 22bcd1bacb66826e8e911454e9c01b54c8b64b32)。
- 测试套件全部通过:
6.4 Wave 2 DMS Adapter, Token, Poller & Mock Integration (Wave 2 implemented against Mock DMS only)
- 阶段状态:
R3_WAVE2_STATUS = PASS。 - 配置与安全默认:
DMS_DEFAULT_ENABLED = FALSE:默认不开启 DMS 通信与轮询。DMS_PROPERTIES:完整实现受控配置,零硬编码密钥,参数化超时与刷新窗口。
- 令牌与通信架构:
TOKEN_TRANSPORT_MODEL=Cookie: token={token}(严禁使用未核实的Authorization: Bearer)。TOKEN_CACHE_MODEL=SINGLE_PROCESS_IN_MEMORY(全应用单一集中缓存)。TOKEN_SINGLE_FLIGHT_MODEL=REENTRANT_LOCK_DCL(高并发过期单飞防击穿,实测 20 线程并发登录仅 1 次)。TOKEN_TTL_MODEL=7200S_WITH_REFRESH_SKEW(滑动窗口提前 120 秒平滑单飞刷新)。SUCCESSFUL_API_EXTENDS_LOCAL_TTL=YES(成功调用 DMS API 顺延本地失效时间戳)。AUTH_FAILURE_REFRESH_MODEL=INVALIDATE_THEN_SINGLE_FLIGHT(401 集中失效并在下一次请求单飞获取新 Token,无 login storm)。AMBIGUOUS_MUTATION_AUTO_RETRY=NO(写操作读取超时坚决抑制自动重发,防止重复生成门锁凭据)。DMS_HTTP_CLIENT=DmsHttpClient统一底层通信与全局脱敏日志(零明文密码/Token/Secret 泄露)。
- 设备与凭据适配能力:
LOCATION_ADAPTER=DmsLocationClient/ExternalLocationGateway(Building, Floor, Room 空间定位与 placeId 解析)。DOORLOCK_ADAPTER=DmsDoorLockClient/ExternalDoorLockGateway(支持 0 把锁空列表与多把锁完整返回)。ONLINE_PASSWORD_CREATE=DmsPasswordClient/ExternalCredentialGateway(支持 4~8 位数字限时密码下发,密码零落库)。ONLINE_PASSWORD_DELETE=DmsPasswordClient/ExternalCredentialGateway(注销并返回 operationId)。OPERATION_STATUS_QUERY=DmsOperationStatusClient。VENDOR_STATUS_MAPPING=DmsOperationStatusMapper(集中统一映射,未知状态判定为 UNKNOWN,绝非 SUCCESS)。
- 异步轮询与测试模拟:
POLLER_IMPLEMENTED=DmsOperationPoller(条件化启动,单进程并发防重,终态不可篡改保护,指数退避重试)。POLLER_INITIAL_DELAY= 10s。MULTI_INSTANCE_POLLER_LOCK=FUTURE_GATE。MOCK_DMS_IMPLEMENTED=MockDmsServer(纯轻量 JDK 原生模拟,登录互斥、短 TTL、多锁/零锁与状态流转)。
- 测试与质量指标:
OLD_TEST_COUNT = 203NEW_TEST_COUNT = 26TOTAL_TEST_COUNT = 229(ruoyi-train: 201, ruoyi-admin: 28),Failures = 0, Errors = 0, Skipped = 0。MAVEN_TEST = SUCCESS,MAVEN_PACKAGE = SUCCESS。git diff --check = PASS。
- 环境纪律与迁移标记:
LIVE_DMS_REQUEST_COUNT = 0(全生命周期未对公网真实 DMS 发起任何请求)。FRONTEND_MODIFIED = 0,CONTROLLER_COUNT = 0。008_RUNTIME_FIRST_RUN = NOT_EXECUTED,008_RUNTIME_SECOND_RUN = NOT_EXECUTED。RUNTIME_MIGRATION_GATE_BEFORE_PRODUCTION = REQUIRED。COMMIT? NO,PUSH? NO,DEPLOY? NO(严格 HOLD 等待审查)。
6.5 Wave 3A Access Authorization Orchestration Dry-Run (Wave 3A implemented against Mock DMS only)
- 阶段状态:
R3_WAVE3A_STATUS = PASS。 - 架构与模型扩展:
AUTH_SCHEMA_SUFFICIENT = NO(基线train_dorm_auth缺失凭据类型、细粒度状态、关联操作流水ID及版本号)。009_MIGRATION_REQUIRED = YES。009_MIGRATION_FILE=RuoYi-Vue/sql/system/kingbase/009_dorm_authorization_orchestration.sql(安全编号 009,幂等增量,纯非破坏性,零明文密钥)。AUTHORIZATION_STATUS_MODEL=PENDING_GRANT / GRANTING / ACTIVE / PENDING_REVOKE / REVOKING / REVOKED / ERROR(厂商中立领域授权生命周期)。CREDENTIAL_TYPE_MODEL=ONLINE_PASSWORD(未来可扩展 QR, CARD, MOBILE_KEY)。VALIDITY_WINDOW_SOURCE=BUSINESS_POLICY_REQUIRED(一期从培训计划与住宿业务时间推导,未决策略显式记录)。
- 统一编排与驱动机制:
RECONCILIATION_MODEL=AccessAuthorizationOrchestrator.reconcile(enrollmentId)(状态驱动对账,解耦业务事件发生顺序)。GRANT_PRECONDITIONS=Enrollment status=1 (已报到) + Active Accommodation (status 0/1) + Active Room Mapping + Exactly 1 Primary DoorLock Mapping + 有效期可推导。REPORT_CONFIRM_TRIGGER=reconcile(enrollmentId)(报到核验通过后驱动,异步对账)。ACCOMMODATION_TRIGGER=reconcile(enrollmentId)(分配或激活住宿后驱动)。REPORT_CONFIRM_EXTERNAL_FAILURE_ROLLBACK=NO(外部网络/DMS 失败绝不回滚报到主事务)。LOCK_SELECTION_POLICY=PRIMARY_LOCK_ONLY(Least Privilege 原则,严格锁定唯一定义的主门锁发码,0主锁与多主锁阻断)。RECONCILE_IDEMPOTENT=YES(多事件/重复报到触发多次 reconcile 结果幂等,无重复授权、无重复发码)。
- 状态流转与时序保护:
GRANT_HTTP_SUCCESS_MARKS_ACTIVE=NO(HTTP 受理仅标记为 GRANTING/ACCEPTED,Poller 确认后方推进 ACTIVE)。GRANT_SUCCESS_RESULT=ExternalOperation=SUCCESS, DoorAuthorization=ACTIVE。GRANT_FAILED_RESULT=ExternalOperation=FAILED, DoorAuthorization=ERROR (保留上下文待重试)。GRANT_TIMEOUT_RESULT=ExternalOperation=TIMEOUT, DoorAuthorization=ERROR (保留上下文待重试)。REVOKE_SUCCESS_RESULT=ExternalOperation=SUCCESS, DoorAuthorization=REVOKED。REVOKE_FAILED_RESULT=ExternalOperation=FAILED, DoorAuthorization=ERROR/REVOKING。STALE_OPERATION_RESULT_GUARD=LATEST_OPERATION_OWNERSHIP_AND_VERSION_CHECK(防迟到旧操作结果覆盖已推进的新状态)。LONG_DB_TRANSACTION_AROUND_HTTP=NO(本地短事务写库 -> 外部调用 -> 本地短事务更新,绝不用长事务包裹网络 IO)。
- 换房调宿与高可用:
TRANSFER_POLICY=GRANT_NEW_THEN_REVOKE_OLD(先下发新宿舍门禁,对账确认 ACTIVE 后才撤销旧宿舍)。TRANSFER_FAILURE_PRESERVES_OLD_ACCESS=YES(新宿舍发码失败严格保留旧宿舍门禁,保障学员可用性)。TRANSFER_DUAL_ACCESS_WINDOW=ACKNOWLEDGED_FOR_AVAILABILITY(可用性优先,审计留痕)。
- 凭据安全与零泄露:
PASSWORD_GENERATOR=SecurePasswordGenerator(SecureRandom强随机、6 位纯数字、杜绝弱密码)。PLAINTEXT_PASSWORD_PERSISTENCE_COUNT=0(数据库、流水表、日志、异常栈、toString 全链路零明文留存)。
- 未决业务与环境门禁:
CREDENTIAL_DELIVERY_POLICY=OPEN_QUESTION。LEAVE_AUTO_REVOKE_POLICY=OPEN_QUESTION。TOKEN_COOKIE_NAME=VENDOR_CONFIRMATION_REQUIRED。LIVE_DMS_REQUEST_COUNT=0(100% Mock DMS 验证)。FRONTEND_MODIFIED=0。
- 全量测试指标:
OLD_TEST_COUNT = 233NEW_TEST_COUNT = 18TOTAL_TEST_COUNT = 251(ruoyi-train: 219, ruoyi-admin: 32)FAILURES = 0,ERRORS = 0,SKIPPED = 0。MAVEN_TEST = SUCCESS,MAVEN_PACKAGE = SUCCESS。git diff --check = PASS。
- 环境纪律与迁移标记:
008_RUNTIME_FIRST_RUN = NOT_EXECUTED,008_RUNTIME_SECOND_RUN = NOT_EXECUTED。009_RUNTIME_FIRST_RUN = NOT_EXECUTED,009_RUNTIME_SECOND_RUN = NOT_EXECUTED。RUNTIME_MIGRATION_GATE_BEFORE_PRODUCTION = REQUIRED。COMMIT? NO,PUSH? NO,DEPLOY? NO(严格 HOLD 等待审查)。