fix(release): enforce AIHR tenant collation contract

This commit is contained in:
2026-07-15 13:33:56 +08:00
parent bd19cdd255
commit ab406e616a
19 changed files with 243 additions and 67 deletions
+16 -3
View File
@@ -11,12 +11,13 @@
- 对练五维、每日三题评分模式、SOP 提问主体/版本、组织入职日期字段尚未全部迁移;
- `aihr_prompt_template` 表存在,但内置模板数量为 `0`;
- `aihr_candidate_material` 缺少 `reviewer/reviewed_time`,`aihr_interview_result` 缺少人工复核字段和 `questions_json`,`aihr_candidate_employee_link` 尚不存在;这些候选人/HR 复核链路不能依赖首次请求触发懒迁移;
- AIHR 表的 `tenant_id` 曾使用 `utf8mb4_0900_ai_ci`,框架 `sys_oss.tenant_id` 使用 `utf8mb4_general_ci`;跨模块等值连接会报 `Illegal mix of collations`,不能靠查询吞错或单次 `binary` 兼容长期掩盖;
- 这些事实不能由应用启动时的懒迁移或页面 fallback 代替。
## 发布前置条件
1. 确认发布窗口、DB 备份和回滚负责人;迁移脚本包含 `ALTER TABLE`,不能在无备份状态执行。
2. 先执行 `scripts/release-preflight.sh` 的只读检查;生产静态资源、后端包和当前提交必须一致。若要同时核对线上结构,追加 `RELEASE_VERIFY_REMOTE_SCHEMA=true`,该开关只读检查必需表,不执行迁移。
2. 先执行 `scripts/release-preflight.sh` 的本地产物检查。生产迁移后、后端发布完成后,必须追加 `RELEASE_VERIFY_REMOTE_SCHEMA=true RELEASE_VERIFY_REMOTE_BACKEND=true` 再做线上核验;该门禁会检查必需表、所有 AIHR `tenant_id` 与 `sys_oss.tenant_id` 的排序规则,以及资料处理实际连接 SQL。
3. 确认迁移目标库、租户和字符集为 MySQL 8 / `utf8mb4`;脚本只允许在目标业务库执行。
4. 生产组织同步凭据、AI 供应商留存/费用口径和正式试点窗口仍未闭合时,不要把迁移完成宣称为 BRD 验收完成。
@@ -40,9 +41,10 @@ mysql --default-character-set=utf8mb4 "$DB_NAME" < backend/script/sql/update/aih
mysql --default-character-set=utf8mb4 "$DB_NAME" < backend/script/sql/update/aihr_20260715_knowledge_feedback_mysql8.sql
mysql --default-character-set=utf8mb4 "$DB_NAME" < backend/script/sql/update/aihr_20260714_org_hire_date_mysql8.sql
mysql --default-character-set=utf8mb4 "$DB_NAME" < backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql
mysql --default-character-set=utf8mb4 "$DB_NAME" < backend/script/sql/update/aihr_20260715_tenant_collation_mysql8.sql
```
顺序原因:场景补充依赖三张场景/Rubric 基础表;五维迁移依赖场景和 Rubric;岗位/SOP/任务/资格迁移只补正式数据契约,不写业务行,也不代表岗位适用范围、任务规则或资格标准已经获得 HR 确认。住宅 SOP 和 Prompt 迁移只补内置内容,不代表内容已完成业务复核。
顺序原因:场景补充依赖三张场景/Rubric 基础表;五维迁移依赖场景和 Rubric;租户排序规则迁移必须最后执行,以覆盖本批次新建的所有 AIHR 表。岗位/SOP/任务/资格迁移只补正式数据契约,不写业务行,也不代表岗位适用范围、任务规则或资格标准已经获得 HR 确认。住宅 SOP 和 Prompt 迁移只补内置内容,不代表内容已完成业务复核。
## 迁移后只读核验
@@ -84,9 +86,20 @@ SELECT COUNT(*) AS built_in_prompt_templates
FROM aihr_prompt_template
WHERE tenant_id = '000000'
AND code IN ('summary_card', 'sop_answer', 'mentor_rewrite', 'review_annotation', 'prep_card', 'supervision_image_analysis_maintenance');
SELECT aihr.table_name, aihr.collation_name, core.collation_name AS expected_collation
FROM information_schema.columns aihr
JOIN information_schema.columns core
ON core.table_schema = aihr.table_schema
AND core.table_name = 'sys_oss'
AND core.column_name = 'tenant_id'
WHERE aihr.table_schema = DATABASE()
AND LEFT(aihr.table_name, 5) = 'aihr_'
AND aihr.column_name = 'tenant_id'
AND aihr.collation_name <> core.collation_name;
```
预期是三张场景/Rubric 表、三张证据表、两张知识治理表、三张候选人/面试表和四张岗位/SOP/任务/资格契约表均存在,会话证据字段为 `8/8`,候选资料审核字段为 `2/2`,面试复核字段为 `6/6`,字段查询覆盖所有列,内置 Prompt 数量为 `6`。岗位/SOP/任务/资格表为空是允许的;这只证明 schema/seed 迁移完成,不证明正式岗位规则、资格 gating 或试点完成。
预期是三张场景/Rubric 表、三张证据表、两张知识治理表、三张候选人/面试表和四张岗位/SOP/任务/资格契约表均存在,会话证据字段为 `8/8`,候选资料审核字段为 `2/2`,面试复核字段为 `6/6`,字段查询覆盖所有列,内置 Prompt 数量为 `6`,排序规则差异查询返回 `0` 行。岗位/SOP/任务/资格表为空是允许的;这只证明 schema/seed 迁移完成,不证明正式岗位规则、资格 gating 或试点完成。
## 迁移后应用回归
+3 -3
View File
@@ -169,11 +169,11 @@ curl -k -s https://peilian.njzhmj.top/h5/ | sed -n '1,20p'
RELEASE_REMOTE_URL=https://peilian.njzhmj.top ./scripts/release-preflight.sh
# 发布后核验线上主资源是否与当前本地产物一致
RELEASE_REMOTE_URL=https://peilian.njzhmj.top RELEASE_VERIFY_REMOTE_MATCH=true ./scripts/release-preflight.sh
# 同时通过 SSH 校验线上后端 jar;默认使用本机 SSH alias YCWY;比较 ruoyi-aihr 模块内容,避免 ZIP 打包时间戳造成误报
RELEASE_REMOTE_URL=https://peilian.njzhmj.top RELEASE_VERIFY_REMOTE_MATCH=true RELEASE_VERIFY_REMOTE_BACKEND=true ./scripts/release-preflight.sh
# 同时校验线上 schema、资料处理连接 SQL 与后端 jar;后端发布验收不得省略 schema 门禁
RELEASE_REMOTE_URL=https://peilian.njzhmj.top RELEASE_VERIFY_REMOTE_MATCH=true RELEASE_VERIFY_REMOTE_SCHEMA=true RELEASE_VERIFY_REMOTE_BACKEND=true ./scripts/release-preflight.sh
```
`RELEASE_VERIFY_REMOTE_BACKEND=true` 必须与 `RELEASE_VERIFY_REMOTE_MATCH=true` 同时使用;预检会同时打印整包 jar SHA-256 和 `ruoyi-aihr` 模块内容 SHA-256,实际匹配以模块内容 hash 为准。远端后端默认核对 `/opt/wygj/app/ruoyi-admin.jar`,如发布路径不同可通过 `RELEASE_REMOTE_BACKEND_PATH` 覆盖;路径必须是安全的绝对路径。
`RELEASE_VERIFY_REMOTE_BACKEND=true` 必须与 `RELEASE_VERIFY_REMOTE_MATCH=true`、`RELEASE_VERIFY_REMOTE_SCHEMA=true` 同时使用;预检会同时打印整包 jar SHA-256 和 `ruoyi-aihr` 模块内容 SHA-256,实际匹配以模块内容 hash 为准。schema 门禁会拒绝 AIHR 与框架租户字段排序规则不一致,并执行资料处理页依赖的 `aihr_knowledge_attach`/`sys_oss` 连接检查。远端后端默认核对 `/opt/wygj/app/ruoyi-admin.jar`,如发布路径不同可通过 `RELEASE_REMOTE_BACKEND_PATH` 覆盖;路径必须是安全的绝对路径。
带 `RELEASE_REMOTE_URL` 时,预检同时校验租户接口 JSON 的业务 `code=200`;HTTP 200 但业务返回 401/405 会判定失败。