Files
prop-ai-hr/docs/KNOWLEDGE_PLATFORM_RUNBOOK.md
T

8.7 KiB

多租户知识空间平台运行手册

1. 适用范围与安全边界

本手册用于银城与美途作为两个独立 SaaS 租户的知识空间初始化、内容迁移、授权、外部应用联调和回滚。租户、调用应用和知识空间是三层独立边界:内部用户的有效查询范围取“当前租户 + 当前调用应用绑定空间 + 用户/角色授权空间”的交集;外部应用只能访问其所属租户内显式绑定的空间。

禁止把集团账号、公司名称、客户端传入的 tenantId/userId/extPartyId 当作授权依据。禁止在浏览器、小程序包、日志、工单或文档中保存 API_TOKEN。回滚优先停用应用或解绑空间,不删除知识数据、附件或 OSS 对象。

2. 初始化前确认

2.1 确认生产租户 ID

先只读查询生产库,不凭公司简称猜租户 ID:

select tenant_id, company_name, status, del_flag
from sys_tenant
where del_flag = '0'
order by tenant_id;

由业务负责人确认银城、美途分别对应的 tenant_id 和公司全称,并确认二者不同。执行脚本还会再次查询并打印 tenant_id:company_name,操作者必须核对后才继续。

2.2 备份与迁移

先备份数据库,再执行 backend/script/sql/update/aihr_20260716_knowledge_space_platform_mysql8.sql。迁移可重复执行,但生产仍应先在结构副本验证。执行后至少核对:

show tables like 'aihr_knowledge_%';
show create table aihr_knowledge_info;
show create table aihr_knowledge_app;
show create table aihr_knowledge_space_grant;

3. 幂等初始化

先 dry-run,不连接数据库、不输出密码或令牌:

./scripts/provision-knowledge-platform.sh \
  --silver-tenant-id '<银城租户ID>' \
  --meitu-tenant-id '<美途租户ID>' \
  --dry-run

确认输出恰好包含银城 3 个空间、美途 1 个空间、3 个应用及预期绑定后,再实际执行:

AIHR_DB_HOST='<数据库地址>' \
AIHR_DB_PORT='3306' \
AIHR_DB_NAME='ry-vue' \
AIHR_DB_USER='<账号>' \
AIHR_DB_PASSWORD='<从安全环境注入>' \
./scripts/provision-knowledge-platform.sh \
  --silver-tenant-id '<银城租户ID>' \
  --meitu-tenant-id '<美途租户ID>' \
  --confirm

不设置 AIHR_DB_HOST 时,脚本使用本地 wygj-mysql 容器。脚本是幂等 upsert,可重复执行;它不会生成 API_TOKEN,也不会把现有细粒度知识库改名、搬迁或删除。

执行后核对:

select tenant_id, code, name, space_type, sensitivity_level, status
from aihr_knowledge_info
where code in ('yc_public_policy','yc_property_sop','yc_management_ops','mt_customer_service')
order by tenant_id, code;

select tenant_id, app_code, auth_type, internal_client_key, status, rate_limit_per_minute
from aihr_knowledge_app
where app_code in ('yc_admin','yc_mobile','mt_card_miniapp')
order by tenant_id, app_code;

mt_card_miniapp 初始化后必须是 DISABLED 且 token_hash 为空;银城与美途之间不得存在应用—空间绑定。

4. 空间、授权与应用管理

管理端“知识空间”页面提供空间、主体授权和调用应用管理。空间编码创建后不可修改;停用空间会让检索立即失去该空间,但不删除资料。MANAGE 授权可以给用户或角色,READ 只决定主体能否读;SESSION 应用与主体授权取交集。

外部美途应用的启用顺序固定为:

  1. 核对只绑定 mt_customer_service。
  2. 核对空间只含批准对外发布的内容。
  3. 设置合理的每分钟限流和过期时间。
  4. 在管理端轮换令牌;明文只显示一次。
  5. 立即写入小程序云函数、API 网关或可信后端的密钥系统。
  6. 确认后端联调通过,再把应用状态改为 ACTIVE。

轮换令牌后旧令牌立即失效。发生泄露或暂停联调时,先把应用改为 DISABLED;需要恢复时重新轮换,不复用曾暴露的明文。前端、小程序源码和用户设备绝不能直接持有令牌。

5. 内容导入与 legacy 空间迁移

5.1 新内容导入

在 SOP 或资料处理页显式选择一个或多个可管理空间。多空间上传只解析一次、复用同一个 OSS 对象,但为每个空间建立独立附件成员关系和检索片段。解绑或停用一个空间不得影响另一个空间的内容。

导入后核对:

select a.tenant_id, k.code, a.doc_id, a.name, a.oss_id, a.status,
       count(f.id) fragment_count
from aihr_knowledge_attach a
join aihr_knowledge_info k
  on k.tenant_id = a.tenant_id and k.id = a.knowledge_id
left join aihr_knowledge_fragment f
  on f.tenant_id = a.tenant_id and f.knowledge_id = a.knowledge_id and f.doc_id = a.doc_id
group by a.tenant_id, k.code, a.doc_id, a.name, a.oss_id, a.status
order by a.id desc;

空间解绑会先删除当前成员、片段和向量点;只有跨租户附件引用计数为零时才尝试删除 OSS。对象存储删除失败不会恢复已解绑成员,而是留下可审计的孤立对象,按下列查询确认后由独立清理流程处理:

select o.oss_id, o.tenant_id, o.original_name
from sys_oss o
left join aihr_knowledge_attach a
  on a.tenant_id = o.tenant_id and a.oss_id = o.oss_id
where a.id is null and o.ext1 in ('aihr-knowledge','aihr-knowledge-staging');

5.2 细粒度 SOP 迁入 yc_property_sop

现有“投诉处理 SOP、催缴沟通 SOP、报修跟进 SOP”等 legacy_* 空间不直接改名。按以下顺序执行:

  1. 业务负责人导出现有空间的文件清单,逐项标记目标空间、密级、版本日期、维护人和是否允许复用。
  2. 通过多空间导入或 OSS 成员复用把批准内容加入 yc_property_sop,保留原 legacy 成员关系。
  3. 对新空间至少运行 10 个标准问题,逐题核对答案、文件标题、引用片段和空间编码。
  4. 核对新应用只绑定新空间,legacy 空间不向新应用授权。
  5. 业务确认后把不再使用的 legacy 空间改为 DISABLED,观察查询日志一个完整业务周期。
  6. 若出现缺失,重新启用 legacy 空间或恢复应用绑定;不要搬回附件、删除片段或清理 OSS。

6. 查询、日志与限流观察

内部统一入口为 POST /api/knowledge/query,外部入口为 POST /api/open/knowledge/query。外部请求使用 Authorization: Bearer <API_TOKEN>。查询日志只保存问题哈希、有效空间、来源类型、状态、耗时和提示版本,不保存完整问题或令牌。

select tenant_id, app_id, status, source_types, count(*) calls,
       round(avg(latency_ms)) avg_latency_ms, max(create_time) last_time
from aihr_knowledge_query_log
group by tenant_id, app_id, status, source_types
order by last_time desc;

重点观察 REJECTED、FAILED、NO_EVIDENCE、连续 429 和异常高耗时。外部应用的限流依赖 Redis;Redis 不可用时外部查询应失败关闭并返回服务不可用,不能绕过限流继续调用。

7. 验证与发布闸门

自动合同测试:

bash scripts/tests/provision-knowledge-platform.test.sh
node --test scripts/tests/knowledge-platform-security.test.mjs

真实环境验证器从环境变量读取令牌,绝不写入命令脚本或仓库:

AIHR_BASE_URL='https://wygj-api.localhost' \
AIHR_SILVER_ADMIN_TOKEN='<管理端登录令牌>' \
AIHR_SILVER_EMPLOYEE_TOKEN='<员工登录令牌>' \
AIHR_SILVER_SUPERVISOR_TOKEN='<主管登录令牌>' \
AIHR_MEITU_APP_TOKEN='<美途应用令牌>' \
AIHR_MEITU_QUERY='<已确认能命中公开内容的美途标准题>' \
node scripts/verify-knowledge-platform.mjs

在预先导入了同一测试文件到 yc_public_policy 与 yc_property_sop 的非生产环境,可额外执行破坏性解绑验证;它会删除公共制度空间中的测试成员,因此必须使用专用测试文件:

AIHR_VERIFY_UNBIND=true \
AIHR_SHARED_DOC_NAME='<专用测试文件名>' \
AIHR_SHARED_DOC_QUERY='<测试文件唯一标记>' \
node scripts/verify-knowledge-platform.mjs

只有工程回归、真实 HTTP 正反例、数据库租户归属、Qdrant tenant+knowledge 过滤和每空间标准题都通过,才可标记“联调可用”。生产发布、真实内容负责人/授权矩阵签字和试点样本未完成时,不得标记“线上生效”或“正式试点验收”。

8. 回滚

按影响最小顺序处理:

  1. 停用 mt_card_miniapp 或对应 SESSION 应用。
  2. 解绑错误空间或把有问题的新空间置为 DISABLED。
  3. 客户端临时回到兼容 /api/knowledge/search,该入口仍经过统一授权服务。
  4. 恢复旧应用绑定或重新启用 legacy 空间。

不要删除新表,不删除查询审计,不把附件移动回旧空间,不清理 OSS,不回滚已经写入的稳定空间编码。数据库和静态资源发布仍遵循项目既有备份与发布口径。