Files
jcgl-dev/docs/公寓端/15-第二轮开发(IT-1)交付说明.md
zfjia 51356c69a3
IT-0 verify / verify (push) Waiting to run
第二次任务推进。
2026-11-10 16:44:01 +08:00

20 KiB
Raw Permalink Blame History

文档定位:IT-1 运行时基座 M0 第二轮开发的交付说明,与 docs/公寓端/13 表 13-11 / DV-1 一一对应。 版本:v1.0 | 2026-11-10 环境:MySQL apt_rev01 @ 127.0.0.1:3306(凭据由 dev/.env 注入)、Redis 本机 database=1、JDK 24 / Maven 3.8.1 / Spring Boot 4.1.0 上位依据:公寓端/07 表 7-2 / 7-3 / 7-6 / 7-8、公寓端/04 §1 / §2 表 4-4、公寓端/03 §4 表 3-12、公寓端/13 表 13-11 / 13-21 / 13-22 / 13-30 / 13-32、公寓端/14 表 14-23 权威关系:本文件是实现说明,不改变任何设计口径;阶段划分与验收仍以 07 为准,业务规则 / 状态 / 接口仍以 CR-02 §11~§15 为准;跨端仍 20 个编号、契约 v2-draft、平台零回调、公寓本地库 59 张表均不变。


1. 交付概览与验收对照

表 15-1 第二轮交付物清单(对应 DV-1)

编号 交付物 落点 状态
DV-1-1 AptContext 增强(gyid/traceId/pageSize) ruoyi-common/.../apt/common/AptContext.java 已交付
DV-1-2 四前缀拦截器与解析器 AptPrefixResolver.java、AptContextInterceptor.java、AptWebMvcConfig.java、SecurityConfig.java 已交付,本轮补 /open/v1/** 放行
DV-1-3 统一错误码与真实 HTTP 状态 AptErrorCode.java、AptInfraExceptionHandler.java、AptAuthenticationEntryPoint.java、AptAccessDeniedHandler.java 已交付,本轮补表 4-4 HTTP 列映射
DV-1-4 审计切面落库 AptAudit.java、AptAuditAspect.java、AptOperationLog.java、AptAuditMapper.java/.xml 已交付,落 duty_operation_log
DV-1-5 分页封装(上限 100) AptPageSupport.java、AptTableDataInfo.java、AptBaseController.java 已交付
DV-1-6 业务表只读查询骨架 AptRoute.java、AptRouteMapper.java/.xml、AptRouteController.java 已交付,不含 CRUD
DV-1-7 springdoc 分组 application.yml(apt/duty/open,扫 com.ruoyi.apt.**) 已交付
DV-1-8 权限点种子与 M0 验收账号 dev/sql/apt_rev01/09_it1_permissions.sql 已交付,二次执行幂等通过
DV-1-9 M0 用例脚本 dev/scripts/verify-it1-m0.ps1 已交付,本轮端到端 5/5 通过
DV-1-10 回归测试 ruoyi-admin/src/test/java/com/ruoyi/apt/** 41 用例全绿
DV-1-11 本文档 docs/公寓端/15 已交付

表 15-2 表 13-11 验收标准逐条对照

# 验收标准 依据 本轮结果
1 无令牌 /apt/route/list → 401 07 表 7-3 M0 通过:HTTP 401 + 40101/UNAUTHORIZED
2 有令牌缺权限点 → 40301 07 表 7-3 M0 通过:HTTP 403 + 40301/PERMISSION_DENIED(apt_guest 角色)
3 gyid=A 查 gyid=B → 40302 且无数据泄露 07 表 7-3 M0、03 表 3-14 通过:HTTP 403 + 40302/GY_ID_CROSS_SCOPE,响应无 rows
4 异常统一返回、无堆栈外泄 07 表 7-3 M0 通过:500 + {code,msg,data{reason,traceId,path}},无内部消息与堆栈
5 pageSize=1000 截为 100 13 表 13-11(07 表 7-3 归 M1,本轮提前落地) 通过:HTTP 200 + pageSize=100
6 架构测试断言所有业务 Mapper SQL 带 gyid 13 表 13-11 通过:AptMapperGyidArchTest 扫描 mapper/apt/**

表 15-3 前置条件与 Go-NoGo 状态

项 要求 状态
IT-0 契约冻结签字 13 表 13-10:未冻结不进 IT-1 未满足:14 表 14-22 ① 记「部分达成」,6 项 P0 与 IR-01 待冻结会签字;本轮按用户显式指令「继续下一轮开发」带条件开工,须补签
D5 一进程一 gyid 签字 13 表 13-24,拍板时点 IT-0 冻结会 未满足:代码已按 D5 实现(apt.gy-id 唯一来源),签字待补
数据库 / Redis apt_rev01 59 表、Redis database=1 已具备,09_it1_permissions.sql 已执行且幂等
技术基线 设计锁定 JDK 1.8 / Boot 2.5.15,dev 实测 JDK 17 / Boot 4.1.0 IR-01 仍为 P0,实编译与运行均通过,定稿待冻结会

2. 模块职责边界与相互依赖关系

表 15-4 模块清单

层 包 / 文件 职责 明确不做
公共 ruoyi-common com.ruoyi.apt.common gyid/traceId 上下文、错误码、异常、四前缀解析、分页封装、审计注解 不访问数据源、不碰若依 AjaxResult 语义
框架 ruoyi-framework com.ruoyi.apt.framework 拦截器注册、401/403 处理器、异常统一映射、审计切面、探针服务、AptProperties 不写业务逻辑、不改若依 GlobalExceptionHandler 本体
系统 ruoyi-system com.ruoyi.apt.master/ops 只读列表 Domain/Mapper/XML、审计写入对象 不提供新增/编辑/删除/状态命令
启动 ruoyi-admin com.ruoyi.apt.ops.controller 自检接口(IT-0)+ 只读列表骨架(IT-1) 不写入住/叫乘/账务业务 Controller
配置 SecurityConfig、application.yml、application-druid.yml 过滤器链、springdoc 分组、数据源与 Redis 凭据一律外置,不落明文
SQL 09_it1_permissions.sql 只写 sys_* 框架表的权限点种子 不触碰 59 张业务表

图 15-1 依赖方向

flowchart LR
    A["SecurityConfig / 过滤器链"] --> B["AptAuthenticationEntryPoint<br/>AptAccessDeniedHandler"]
    A --> C["AptContextInterceptor"]
    C --> D["AptPrefixResolver"]
    C --> E["AptContext"]
    C --> F["AptProperties (apt.gy-id)"]
    G["AptRouteController"] --> H["AptBaseController"]
    H --> I["AptPageSupport / AptTableDataInfo"]
    G --> J["AptRouteMapper (gyid 隔离)"]
    G --> K["@AptAudit → AptAuditAspect"]
    K --> L["AptAuditMapper → duty_operation_log"]
    M["AptInfraExceptionHandler"] --> E
    M --> N["AptErrorCode"]

拦截器在 preHandle 写入 gyid 与 traceId,afterCompletion 清理;业务 Controller 只从 AptContext 取值,绝不采信请求参数。


3. 四前缀治理与鉴权

表 15-5 四前缀策略矩阵(04 §1、13 表 13-11)

前缀 会话要求 附加校验 拒绝码 过滤器链
/apt/** 需登录(@Anonymous 例外) 参数/头 gyid 与配置一致性 40101 / 40302 anyRequest().authenticated()
/duty/** 需登录(@Anonymous 例外) 同上 40101 / 40302 anyRequest().authenticated()
/open/v1/** 匿名分区 必填 X-Device-Code;gyid 不一致 → 40303 40101 / 40303 本轮补 permitAll(),否则会被提前 401
/platform/** 本端不提供 有令牌也显式拒绝 40401 PREFIX_NOT_SERVED anyRequest().authenticated()

设备侧 HMAC / 时间窗 / nonce 完整校验在 IT-3 落地;本轮只做占位骨架,符合表 13-11「不含业务表 CRUD」。

表 15-6 权限点种子(09_it1_permissions.sql)

menu_id 权限点 本轮状态
3000 公寓端父目录 启用
3001 apt:route:list 启用,关联超管角色 1(留痕)
3002 apt:ops:connectivity 仅登记(自检接口为 @Anonymous)
3003~3006 apt:room:list、apt:jcxx:list、duty:checkin:list、apt:ledger:local 置灰不关联角色(13 表 13-29 预埋不上线)
角色 300 / 账号 300 apt_guest M0「有令牌缺权限点」验收账号,apt_permission_count=0;生产部署前必须删除

表 15-7 统一错误响应

场景 HTTP body
未登录(过滤器链) 401 {code:40101, msg, data:{reason:"UNAUTHORIZED", traceId, path}}
权限不足(过滤器链 / @PreAuthorize) 403 {code:40301, msg, data:{reason:"PERMISSION_DENIED", traceId, path}}
跨公寓 / 前缀拒绝 / 参数非法 按表 4-4 {code, msg, data:{reason, traceId, path}}
未知异常(公寓端四前缀) 500 msg 固定为「内部错误(已记录)」,不回传 e.getMessage() 与堆栈
非公寓端路径 保持若依原状 401 委托 AuthenticationEntryPointImpl;403 委托 AccessDeniedHandlerImpl;ServiceException 保留自定义 code

4. 接口与错误码约定

表 15-8 本轮接口清单

方法 路径 权限点 请求参数 返回结构 错误码
GET /apt/route/list apt:route:list cc、jlid、state、pageNum/pageSize、orderByColumn/isAsc {code,msg,rows,total,pageSize,traceId} 40101、40301、40302、500
GET /apt/ops/connectivity @Anonymous + 仅回环 无 {code,msg,data{overall,gyid,results[],traceId}} 40001、40301、50301/50304
POST /apt/ops/connectivity/probe @Anonymous + 仅回环 {target:"DB|REDIS|ALL", strict:bool} 同上 40001 INVALID_TARGET、50301、50304
GET /apt/ops/connectivity/error-probe @Anonymous + 仅回环 无 统一错误体 500 UNEXPECTED_ERROR
— springdoc /v3/api-docs?group=apt|duty|open 匿名 — 分组文档 —

/platform/** 不分组(公寓端不提供);/apt/route/list 为只读骨架,表 13-11 明确本轮不含 CRUD。

表 15-9 AptErrorCode 与表 4-4 HTTP 列映射(本轮补齐)

段 码 HTTP 典型场景
参数 40001 400 必填缺失、target 非法
认证 40101 401 无令牌、令牌失效、设备凭据缺失
授权 40301/40302/40303 403 缺权限点、跨公寓、设备跨公寓
不存在 40401 404 对象不存在、/platform/** 前缀拒绝
冲突 40901~40916、40940 409 重复键、状态非法、延后域预埋
其他 41001、50101/50102、50301/50302/50304、500 410/501/503/500 录音清理、协议未定、依赖不可用、数据异常、兜底

50304(数据异常)为 IT-0 在既有 503xx 段内新增,40940 为 CR-02 表 C-3 延后域预埋;二者须随 50304 一并纳入契约冻结登记,40940 本期不启用。

表 15-10 异常策略矩阵

异常 映射 对外可见信息
AptException 自身 AptErrorCode + reason 仅 msg / reason / traceId / path
AccessDeniedException(公寓端) 40301 同上
ServiceException(公寓端) 40001 SERVICE_EXCEPTION 不外泄原始 message
ServiceException(非公寓端) 若依原 code / message 保持上游行为
DuplicateKeyException / DataIntegrityViolationException 40901 / 50304 无堆栈
CannotGetJdbcConnectionException / QueryTimeoutException / Redis* 50301 无连接串、无凭据
兜底 Exception(四前缀内) 500 UNEXPECTED_ERROR 仅写日志,不回传 e.getMessage()

5. 审计与分页

表 15-11 审计落库字段(duty_operation_log)

字段 来源 说明
gyid AptContext.getGyIdOrNull(),缺失写 UNKNOWN 强制隔离列,AptAuditMapper.xml INSERT 必带
log_id UUID(去横线) 与 gyid 组成唯一键
operator_ref SecurityUtils.getLoginUser(),异常时 ANONYMOUS —
module / action @AptAudit 注解 如 ROUTE / LIST
detail JSON status、costMs、traceId、uri、httpMethod、params(敏感键过滤)
trace_id / occurred_at AptContext / 当前时间 与错误响应可关联

与若依 @Log/sys_oper_log 并行,不改上游表;写库失败只 WARN,不影响业务返回。审计写入当前与业务同事务,IT-2 引入写操作后需评估 REQUIRES_NEW,避免事务回滚时丢留痕。

表 15-12 分页规则

项 规则
硬上限 AptPageSupport.HARD_MAX_SIZE = 100,配置 apt.page.max-size 高于此值仍被压制
默认值 pageNum=1、pageSize=10;pageSize<=0 回落默认
生效链路 AptBaseController.startAptPage() → AptPageSupport.startPage() → PageHelper.startPage()
响应回显 AptTableDataInfo 追加 pageSize 与 traceId
排序 只读列表固定 ORDER BY state DESC, kcsj ASC, cc ASC,禁止默认按 id(04 §1.2)

6. 验证结果

表 15-13 本轮实际执行的验证

# 验证项 手段 结果
1 全量编译与打包 mvn -B -ntp package(JDK 24 / Maven 3.8.1) 7 模块 BUILD SUCCESS,ruoyi-admin.jar 重打包
2 全量单测 Surefire 3.5.2 + JUnit5 Tests run: 41, Failures: 0, Errors: 0
3 四前缀 / 鉴权 AptPrefixResolverTest、AptAuthInterceptorTest、AptAccessDeniedHandlerTest 通过
4 错误码 / 异常 AptErrorResponseTest、AptInfraExceptionHandlerTest、AptConnectivityControllerTest 通过(含真实 HTTP 状态 400/403/503)
5 审计落库 AptAuditAspectTest(成功/失败/写库降级/敏感过滤) 通过
6 分页 AptPageSupportTest(normalize + 真实 PageHelper 链路) 通过
7 Mapper 架构约束 AptMapperGyidArchTest(gyid + 非 id 排序) 通过
8 权限点种子 09_it1_permissions.sql 首次/二次执行 幂等通过,apt_permission_count=0;追加置灰/总数/账号状态校验 SELECT
9 静态检查 read_lints(com.ruoyi.apt.** 与 SQL) 0 错误
10 真实进程端到端 M0 dev/scripts/verify-it1-m0.ps1,启动 ruoyi-admin.jar + 真实 HTTP 5/5 通过(见表 15-14)

表 15-14 端到端 M0 实测(07 表 7-3 M0 四项 + 13 表 13-11 扩展两项)

用例 期望 实测
无令牌 /apt/route/list HTTP 401 / 40101 HTTP 401 / 40101
apt_guest 有令牌缺权限点 HTTP 403 / 40301 HTTP 403 / 40301
令牌 gyid=A 查 gyid=B HTTP 403 / 40302,无数据 HTTP 403 / 40302,响应无 rows
/apt/ops/connectivity/error-probe 统一错误体、无堆栈外泄 500 + data.traceId,无内部标记与堆栈
pageSize=1000 截为 100 HTTP 200 + pageSize=100

端到端脚本从 dev/.env 加载凭据,经 /captchaImage + Redis database=1 的 captcha_codes:<uuid> 读取验证码答案完成登录,未关闭验证码开关、未修改 sys_config;结束后自动停止应用进程。 环境发现:dev/.env 的 APT_TOKEN_SECRET 仍是占位文本,而 TokenService.signWith(HS512, secret) 要求 Base64 编码且解码后 ≥64 字节,否则登录抛 ArrayIndexOutOfBoundsException。脚本已内置「本次运行生成临时密钥」兜底,.env 未改动;本轮修正了 dev/.env.example 中误导性的 APT_TOKEN_SECRET 提示(原文引导填 hex 文本),改为 Base64 要求与生成示例,并补齐从 application*.yml 提取的变量;本机 .env 仍须按模板填写。


7. 口径偏离与待评审项

表 15-15 口径偏离登记(含任务 1 核对结果与本轮处置)

# 偏离 本轮处置 待办
1 契约冻结签字未完成即开工 按用户显式指令带条件开工,交付说明显式登记 补冻结会签字(P0)
2 gyid 注入:表 13-11 写「只从会话/设备凭据解析」、03 表 3-12 写「令牌声明 → AptContext」,实现按 D5 只从 apt.gy-id 配置注入 请求参数/头仅作一致性校验并拒绝跨域 随 D5 签字确认口径
3 M0「令牌 gyid=A 查 gyid=B」在 D5 下无令牌态 gyid 验收改为「参数/头 gyid 不一致 → 40302/40303」(03 表 3-14 用例 2 允许) 验收脚本已固化,冻结会确认
4 分页上限归 M1(07 表 7-3),表 13-11 提前并入 IT-1 已提前实现并验证 交付记录按 6 项
5 表 4-4 外的错误码 50304 / 40940 / 500 50304 沿用 503xx 段、40940 属 CR-02 预埋、500 仅兜底 50304 纳入冻结登记;40940 本期不启用
6 审计切面实现为独立 @AptAudit 而非「扩展 @Log」 落 duty_operation_log,与若依 @Log 并行、不改上游表 登记即可
7 AptAccessDeniedHandler / handleAccessDenied 曾越界改变若依后台 403 本轮已修:非公寓端分别委托 AccessDeniedHandlerImpl 与若依原 code 已完成
8 /open/v1/** 曾被 anyRequest().authenticated() 提前 401 本轮已修:SecurityConfig 放行,由拦截器校验 X-Device-Code IT-3 补 HMAC
9 AptException 曾一律 HTTP 200,与表 4-4 不符 本轮已修:applyHttpStatus 按码前三位映射,并同步更新 IT-0 自检用例断言 已完成
10 ServiceException 被 @Order(HIGHEST_PRECEDENCE) 吞掉自定义 code 本轮已修:新增专门 handler,非公寓端保留若依口径 IT-2 需补 BindException / MethodArgumentNotValidException 类型分派
11 只读骨架字段与 04 表 4-5 不同(state/route_name/... vs enabled/jch/qd/jcsj/...) apt_master_route 为 IT-0 [推断] 表,骨架按 DDL 实现 IT-2 交路 CRUD 前给出字段映射,不改 59 张表设计口径
12 只读骨架 Controller 暂落 com.ruoyi.apt.ops.controller 表 13-21 要求交路域落 com.ruoyi.apt.master.* IT-2 迁移
13 表 13-11/13-22 引用「03 §5 四级隔离」 实际四级隔离在 03 §4 表 3-12,§5 为逻辑删除约定 文档交叉引用待勘误
14 application.yml 的 token.secret 与 .env 占位文本不兼容 验收脚本内置临时 Base64 兜底 修正本机 .env;run-local.ps1 未内置兜底

8. 变更点与影响范围、后续衔接

表 15-16 变更点与影响范围

类别 变更 影响范围
新增 AptPrefixResolver、AptAudit+切面+Mapper、AptPageSupport/AptTableDataInfo、AptBaseController、401/403 处理器、只读列表骨架、09_it1_permissions.sql、verify-it1-m0.ps1、本文档 dev/RuoYi-Vue-master 后端、dev/sql/apt_rev01、dev/scripts、文档索引
修改 SecurityConfig(/open/v1/** 放行 + 401/403 处理器)、application.yml(springdoc 三组)、AptContext(pageSize)、AptErrorCode(表 4-4 全量)、AptInfraExceptionHandler(HTTP 状态 + ServiceException)、AptConnectivityController(error-probe)、dev/.env.example 若依启动链路与非公寓端路径行为已做前缀隔离,后台管理保持原行为
测试 32 → 41 用例;IT-0 自检用例断言改为真实 HTTP 400/403/503 ruoyi-admin 构建
不变 CR-02 §12~§15 权威表述、跨端 20 编号、v2-draft、平台零回调、公寓本地库 59 张表、apt.duty.state 单写入口、统计结果不回写、F-AF-Q、Q-01Q-50 无设计口径改动;未新增 M7 / 阶段六 / D-4 / Q-* / R-* / 施工单编号
提交纪律 本轮未执行 git commit / git push 变更清单待评审

表 15-17 后续衔接(IT-2 主数据与房间)

项 内容
前置 本轮 M0 六项全过;D8' / D3 / D7 签字;表 15-15 #11 / #12 的字段映射与包迁移
范围 交路 CRUD + 复算校验 + 启停原因、房间档案 + 房态 + state_version、#1~#4 主数据下行 Mock(source='LOCAL')
需补 BindException / MethodArgumentNotValidException 的非公寓端类型分派;审计写入独立事务;只读骨架 Controller 迁入 com.ruoyi.apt.master.*
回归 表 7-3 M1/M2、表 7-6 八类用例 M0~M2 部分;本文件表 15-14 的 M0 五项须持续全绿
延后 IT-9~IT-11 消费 / 充值 / 菜品,本期不开 /apt/ledger/**、不建 com.ruoyi.apt.ledger 包