feat: restore learning feedback and knowledge capabilities

This commit is contained in:
2026-07-18 00:50:11 +08:00
parent 876a23a123
commit 6bdc86e3fc
152 changed files with 30337 additions and 953 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,556 @@
# 多租户多知识空间统一问答平台需求与总体方案
> 版本:v1.0
>
> 日期:2026-07-16
>
> 需求来源:客户关于“多个独立知识库、多个调用端、数据安全与数据库查询”的讨论,以及《物业AI人力资源系统业务需求文档BRD》
>
> 项目归属:《银城员工端 APP 分阶段实施总纲》阶段二的平台化能力
>
> 实施边界:本方案不改变当前阶段一 AI 陪练验收口径,也不把方案评审或演示可用表述为正式试点验收完成。
## 1. 结论摘要
本次需求不是简单的“再建几个知识库”,而是把现有知识问答能力升级为一个可服务多个公司的多租户知识平台:
1. **公司是最高隔离边界。** 银城、美途分别作为独立租户,账号、知识、应用、检索、日志和数据工具默认互不可见。
2. **知识空间是租户内的内容与授权单元。** 同一租户可按业务或受众建立多个知识空间,例如公共制度、物业业务 SOP、管理运营、客户咨询。
3. **调用应用与知识空间是多对多关系。** 一个应用可使用多个空间,一个空间也可供员工端、主管端、管理端等多个应用使用。
4. **用户或角色与知识空间也是独立的多对多关系。** 对内部登录用户,最终可检索范围是“应用获授权空间”与“用户/角色获授权空间”的交集。
5. **所有端复用同一套问答能力和响应契约。** 内部端和外部端因认证边界不同保留两个入口,但共用授权解析、检索、生成、引用和审计服务。
6. **知识文件和实时业务数据分两条链路。** 文件进入 RAG 知识检索;员工训练记录等实时数据只能通过预定义、受控的数据工具读取,不允许模型生成或执行任意 SQL。
7. **第一版不做跨租户共享。** 即使银城与美途存在集团或合作关系,也默认互相不可见;未来共享必须经过明确授权、脱敏、复制或发布流程。
8. **同一原始文件可以属于多个知识空间。** OSS 原文件只保存一份,每个空间保留独立的成员关系、片段和检索权限;解绑某个空间不得影响其他空间。
## 2. 需求背景与讨论解读
客户原始表达包含四层诉求:
- “再加几个独立库”:希望按公司、业务和受众划分可见内容。
- “给别的系统提供接口”:希望名片小程序、员工端、主管端、管理端等多个入口复用问答能力。
- “限定调用哪个库”:希望每个入口只能查询被授权的知识范围。
- “不用担心数据安全、行业问题”:希望通过隔离、权限和受控数据访问降低泄露风险。
其中前三点已经形成明确产品模型,第四点需要更准确地表述:**多知识空间有助于安全,但空间拆分本身不等于安全完成。** 真正的安全控制需要同时覆盖租户、应用、用户/角色、空间、项目/组织范围、数据行列权限、接口认证和审计日志。
客户后续确认“知识空间跟可访问的接口是多对多关系”“好多端需要调用问答”,说明其已理解并确认多端复用和应用—空间多对多这一核心方向。以下细节属于本方案给出的工程化定案:双入口共享服务、授权取交集、外部应用密钥、数据工具白名单、日志最小化和同文件多空间成员模型。
### 2.1 当前确认状态
| 层级 | 已形成的结论 | 当前性质 |
|---|---|---|
| 租户 | 银城、美途分别作为独立租户 | 已确认 |
| 多端 | 名片小程序、员工端、主管端、管理端等多个端需要调用问答 | 已确认 |
| 应用授权 | 调用应用与知识空间建立多对多关系 | 已确认 |
| 跨公司 | 第一版不做跨租户共享 | 已确认 |
| 首批空间 | 银城 3 个、美途 1 个上线,其他空间有内容和负责人后再启用 | 本方案建议,纳入第一版基线 |
| 主体授权 | 内部范围取应用授权与用户/角色授权交集 | 为满足数据安全必须采用的工程规则 |
| 外部认证 | 外部端使用独立应用令牌、内部端沿用登录态,底层共用 query service | 本方案工程定案 |
| 数据查询 | 第一版只开放本人训练概况、团队训练概况两个固定工具 | 本方案建议,纳入第一版基线 |
客户已确认的是产品方向,不等于空间内容清单、具体角色 key、负责人、外部密钥保管和标准题已经完成业务验收;这些仍按第 17 节作为正式试点准入材料。
## 3. 目标与非目标
### 3.1 业务目标
1. 支持银城、美途等多个公司使用同一平台,但数据与权限相互隔离。
2. 支持每个租户按业务、受众和敏感级别建立多个知识空间。
3. 支持多个应用统一调用问答能力,并为每个应用配置可访问空间。
4. 支持内部员工按角色、人员、项目或组织范围取得不同知识权限。
5. 支持答案带来源引用、无依据时明确提示,避免跨空间引用和无依据生成。
6. 支持同一文件一次存储、授权到多个空间,降低重复上传和维护成本。
7. 首版复用银城现有组织、训练与主管数据,提供两个安全的结构化数据查询工具。
8. 提供空间、授权、应用和查询审计的管理能力。
### 3.2 第一版非目标
- 不做跨租户实时检索、集团账号天然读取子公司数据或跨租户联合统计。
- 不做员工个人知识空间;个人 AI 助理继续按独立专项 TechSpec 和计划实施。
- 不接工资、薪酬、银行账户、完整人事档案、财务明细等高敏数据。
- 不接美途订单、客户交易流水或任意业务数据库。
- 不允许自然语言生成 SQL、任意 SQL、任意表名或任意字段查询。
- 不做知识空间之间的自动去重、自动合并或自动同步。
- 不为每个租户单独部署一套应用、MySQL 或 Qdrant;首版采用共享基础设施上的逻辑隔离。
- 不开放浏览器或小程序前端直连平台密钥。
- 不把本方案的完成等同于生产发布或正式试点验收。
## 4. 概念模型
### 4.1 核心对象
| 对象 | 定义 | 第一版示例 |
|---|---|---|
| 租户 Tenant | 公司级最高安全、运营和审计边界 | 银城、美途 |
| 知识空间 Space | 租户内独立的内容集合和授权单元 | 公共制度、物业业务 SOP、美途客户咨询 |
| 调用应用 App | 调用统一问答能力的业务入口 | 员工端、主管端、管理端、名片小程序 |
| 访问主体 Principal | 被授予空间权限的人或角色 | employee、supervisor、finance、指定用户 |
| 文档成员 Attachment | 原始文档在某个空间中的成员关系 | 同一制度文件同时进入公共制度和管理运营 |
| 数据工具 Data Tool | 受控读取实时结构化数据的固定服务 | 我的训练概况、团队训练概况 |
| 查询日志 Query Log | 不保存敏感正文的调用审计记录 | 应用、用户、空间、耗时、结果状态 |
### 4.2 边界层级
```mermaid
flowchart TD
T["租户:公司级隔离"] --> A["调用应用授权"]
T --> P["用户/角色授权"]
T --> S["知识空间"]
A --> X["应用允许的空间集合"]
P --> Y["主体允许的空间集合"]
X --> I["内部最终范围:X 与 Y 的交集"]
Y --> I
S --> I
I --> R["按 tenant_id + knowledge_id 检索"]
R --> O["带引用答案"]
```
租户内的项目、部门、岗位不是新租户,而是组织或数据范围。知识空间负责内容边界,项目/部门范围负责回答“谁能看哪些项目数据”;两者不能互相替代。
### 4.3 授权计算规则
内部登录用户:
```text
effectiveSpaceIds
= tenantSpaceIds
∩ appGrantedSpaceIds
∩ principalGrantedSpaceIds
```
外部匿名应用:
```text
effectiveSpaceIds
= tenantSpaceIds
∩ appGrantedSpaceIds
```
补充规则:
1. 客户端传入 `spaceCodes` 只能缩小服务端算出的范围,不能扩大范围。
2. 明确请求了未授权空间时返回 403,不静默扩大或替换为其他空间。
3. 没有任何有效空间时不执行 MySQL、Qdrant 或 LLM 查询,直接返回无权限。
4. 所有 MySQL 和 Qdrant 查询必须同时带 `tenant_id` 与有效 `knowledge_id` 集合。
5. 管理员拥有“配置空间”的权限,不代表天然拥有“读取全部空间正文”的权限;读取仍按显式授权。
## 5. 租户方案与安全考虑
### 5.1 租户划分
| 租户 | 定位 | 默认策略 |
|---|---|---|
| 银城 | 物业员工、主管、HR、财务和管理层使用的企业内部知识与业务数据 | 只允许银城身份和银城应用访问 |
| 美途 | 客户咨询和后续内部业务知识 | 只允许美途身份和美途应用访问 |
银城、美途即使由同一集团管理,也保持独立租户,原因如下:
1. **法人和责任边界不同。** 两家公司对员工信息、客户信息和经营资料承担不同的数据管理责任。
2. **最小权限。** 集团管理关系不能自动推导出每个账号有权读取所有子公司原文。
3. **降低事故影响面。** 一个租户的密钥泄漏、错误授权或导入失误不能扩大到另一个租户。
4. **便于审计追责。** 每次访问可明确归属到哪个公司、哪个应用和哪个主体。
5. **便于独立运营。** 两家公司可分别配置知识负责人、密钥轮换、限流、下线和数据保留策略。
6. **适应组织变化。** 后续新增公司、独立交付、合同终止或组织调整时,不需要拆分已混合的数据。
第一版跨租户访问固定为默认拒绝。未来如果出现集团共享需求,推荐使用“发布脱敏副本到目标租户”的方式,并保留来源、审批人、版本和撤回记录;不推荐直接让一个租户在线检索另一个租户的原始空间。
## 6. 第一批知识空间建设建议
### 6.1 银城首批上线空间
| 空间名称 | 建议编码 | 内容范围 | 初始使用者/应用 | 第一批状态 |
|---|---|---|---|---|
| 公共制度 | `yc_public_policy` | 公司制度、员工应知、员工权益、行政通知、公开流程 | 员工、主管、HR;员工端和管理端 | 必建、上线 |
| 物业业务 SOP | `yc_property_sop` | 管家、客服、保洁、保安、工程、收费等岗位流程与标准 | 员工、主管、培训/品质;员工端、主管端、管理端 | 必建、上线 |
| 管理运营 | `yc_management_ops` | 项目管理、巡检、培训、品质、复盘、团队管理方法 | 主管、项目经理、HR/培训/品质;主管端和管理端 | 必建、上线 |
| 财务专业 | `yc_finance_professional` | 财务制度、预算规则、报销和结算规范 | 财务角色;管理端 | 有真实内容和负责人后启用 |
| 经营决策 | `yc_business_decision` | 经营分析口径、管理报告、决策参考 | 高管及明确授权人员;管理端 | 有脱敏规则和负责人后启用 |
首批业务验收以前三个上线空间为准。财务专业、经营决策不是把同一批普通制度换个名字重复入库;只有在内容清单、负责人、密级和角色授权同时明确后才启用。
### 6.2 美途首批上线空间
| 空间名称 | 建议编码 | 内容范围 | 初始使用者/应用 | 第一批状态 |
|---|---|---|---|---|
| 美途客户咨询 | `mt_customer_service` | 服务介绍、常见问题、业务流程、公开价格口径、客户沟通话术 | 名片小程序;后续客服工作台 | 必建、上线 |
| 美途内部工作 | `mt_internal_work` | 内部流程、员工工作指引 | 美途内部员工应用 | 第一版不建 |
| 美途管理 | `mt_management` | 经营和团队管理资料 | 主管/管理层 | 第一版不建 |
| 美途财务 | `mt_finance` | 财务制度和内部财务资料 | 财务角色 | 第一版不建 |
美途客户咨询空间只能放可对外回答的内容。内部制度、客户隐私、合同原件、交易明细不得通过“同一问题看起来相近”而混入该空间。
### 6.3 角色与空间建议
| 主体 | 默认可读空间 | 附加限制 |
|---|---|---|
| 银城普通员工 | 公共制度 + 与岗位相关的物业业务 SOP | 项目相关内容按本人项目范围过滤 |
| 银城主管/项目经理 | 公共制度 + 物业业务 SOP + 管理运营 | 团队数据限本人管理范围 |
| HR/培训/品质 | 公共制度 + 物业业务 SOP + 管理运营 | 仅限职能授权范围,不能天然读取财务或经营原文 |
| 财务 | 公共制度 + 财务专业 | 财务空间启用后显式授予 |
| 高管 | 公共制度 + 管理运营 + 经营决策 | 默认看汇总;原始明细仍需单独授权 |
| 美途名片小程序 | 美途客户咨询 | 外部匿名应用,无用户角色扩权能力 |
这些是默认授权模板,不代替业务负责人对具体人员、岗位和项目范围的确认。
### 6.4 内容治理要求
每个上线空间必须具备:
- 一名业务负责人和一名内容维护人;
- 明确的内容准入范围与禁止内容;
- 初始文件清单和版本日期;
- 密级:`PUBLIC`、`INTERNAL`、`CONFIDENTIAL` 三选一;
- 适用角色、应用和项目范围;
- 更新周期和失效内容处理规则;
- 至少 10 个标准问题及预期引用,用于上线前验证。
## 7. 统一问答能力
### 7.1 入口与复用方式
| 场景 | API | 认证 | 说明 |
|---|---|---|---|
| 内部员工端、主管端、管理端 | `POST /api/knowledge/query` | 现有 Sa-Token 登录态 | 解析租户、用户、角色、`clientKey` 和项目范围 |
| 美途名片小程序等外部应用 | `POST /api/open/knowledge/query` | Bearer 应用令牌 | 只使用应用授权空间,不接受用户或角色扩权 |
两个入口共用 `AihrKnowledgeQueryService`,因此“统一接口”的准确含义是:统一请求/响应契约和统一业务能力,而不是强行让内部用户登录令牌与外部应用密钥共用一个认证入口。
### 7.2 请求契约
```json
{
"queryText": "装修施工人员进入小区需要什么手续?",
"spaceCodes": ["yc_property_sop"],
"category": "sop",
"position": "生活顾问",
"source": "mobile_uni_sop",
"limit": 5,
"toolCode": null
}
```
约束:
- `queryText` 必填,去首尾空白后 1–1000 字。
- `spaceCodes` 可不传;不传表示在有效授权范围内检索,传入表示进一步收窄。
- `limit` 默认 5,范围 1–10。
- `toolCode` 为空时执行知识问答;传入时只允许第一版白名单工具。
- `category/position/source` 保留兼容和分析用途,不能决定或扩大授权空间。
### 7.3 响应契约
```json
{
"requestId": "01JZZ...",
"queryText": "装修施工人员进入小区需要什么手续?",
"answer": "根据《装修人员进场管理 SOP》……",
"citations": [
{
"spaceCode": "yc_property_sop",
"sourceType": "DOCUMENT",
"docId": "doc_123",
"title": "装修人员进场管理 SOP",
"snippet": "施工人员进场前应完成……",
"fragmentId": 456
}
],
"usedSpaceCodes": ["yc_property_sop"],
"noEvidence": false,
"promptVersion": "knowledge-query-v1",
"legacy": {
"reference": "装修人员进场管理 SOP",
"docs": [],
"snippets": []
}
}
```
响应要求:
1. 每条文档结论必须能定位到被授权空间的引用。
2. 没有足够依据时返回 `noEvidence=true` 和明确提示,不用其他租户、其他空间或模型常识补齐公司规则。
3. 数据工具结果的 `sourceType` 为 `DATA_TOOL`,引用工具编码和统计窗口,不伪装成文档片段。
4. `requestId` 贯穿认证、授权、检索、LLM 和审计日志。
### 7.4 查询处理流程
```text
认证内部会话或外部应用令牌
→ 锁定 tenantId 与 appId
→ 内部用户解析角色、组织、项目范围
→ 计算有效知识空间集合
→ 校验请求是否仅收窄范围
→ 知识问答:MySQL Fulltext + Qdrant 混合召回
→ 数据工具:调用固定 service,并执行本人/团队范围检查
→ Rerank(可用时)
→ LLM 仅使用已授权证据生成答案
→ 返回引用与无依据标记
→ 写入最小化查询日志
```
### 7.5 现有接口兼容
现有 `POST /api/knowledge/search` 暂保留,作为兼容包装器转发到新查询服务。必须修正现有 `category=sop` 可能变成租户内全库检索的行为:兼容请求只能映射到当前主体已获授权的银城物业业务 SOP 等空间,不能将空分类当作“搜索全部空间”。
## 8. 实时数据库查询方案
### 8.1 为什么不能把数据库直接当知识库
文档知识适合切片、向量检索和引用;训练记录、人员状态等实时结构化数据具有强身份、行权限和时效要求。如果让模型直接访问数据库或生成 SQL,空间授权无法阻止它读取错误的表、行或字段,也无法稳定审计查询目的。
因此第一版采用“数据工具”模式:每个工具有固定编码、固定参数、固定 service、固定权限和固定返回字段。
### 8.2 第一版数据工具
| 工具编码 | 用途 | 数据来源 | 权限 |
|---|---|---|---|
| `MY_PRACTICE_SUMMARY` | 查询本人指定窗口内的训练次数、最近训练和能力摘要 | 复用 `AihrMobileSeedService.practiceHistory(extPartyId)` | 仅本人;服务端从登录态取身份 |
| `TEAM_PRACTICE_SUMMARY` | 查询本人管理团队的完训、待复盘和汇总 | 复用 `AihrMobileSeedService.practiceTeam(supervisorExtPartyId)` | 仅主管;服务端解析主管范围 |
第一版由客户端快捷入口显式传 `toolCode`。不从任意自然语言自动决定并执行数据库查询,不接工资、财务、美途订单或其他任意表。
### 8.3 工具安全规则
1. 请求体不接受 `tenantId`、`userId`、`extPartyId`、`supervisorExtPartyId`。
2. 身份和数据范围只从服务端登录态与组织快照取得。
3. 工具返回 DTO,不返回数据库字段全集、SQL、堆栈或内部主键集合。
4. 外部 API_TOKEN 应用第一版不得调用任何数据工具。
5. 工具失败不回退到模型猜测或 seed 假数据。
6. 审计日志记录工具编码、窗口和结果状态,不记录个人训练原文。
## 9. 数据模型
### 9.1 复用 `aihr_knowledge_info` 作为知识空间
在现有表上新增:
| 字段 | 类型 | 说明 |
|---|---|---|
| `code` | varchar(100) | 租户内稳定编码,`UNIQUE(tenant_id, code)` |
| `space_type` | varchar(30) | `BUSINESS` / `MANAGEMENT` / `PUBLIC` / `EXTERNAL` |
| `sensitivity_level` | varchar(30) | `PUBLIC` / `INTERNAL` / `CONFIDENTIAL` |
| `status` | varchar(20) | `DRAFT` / `ACTIVE` / `DISABLED` |
继续复用原有 `tenant_id`、`name`、设置与片段关系。客户端和授权表使用稳定 `code`,不再以可修改的中文名称作为接口主键。
### 9.2 `aihr_knowledge_space_grant`
| 字段 | 说明 |
|---|---|
| `id/tenant_id/knowledge_id` | 主键、租户和空间 |
| `principal_type` | `ROLE` 或 `USER` |
| `principal_value` | 角色 key 或用户 ID 字符串 |
| `permission` | `READ` 或 `MANAGE` |
| `status` | `ACTIVE` / `DISABLED` |
| `create_by/create_time/update_by/update_time` | 审计字段 |
唯一约束:`(tenant_id, knowledge_id, principal_type, principal_value, permission)`。
### 9.3 `aihr_knowledge_app`
| 字段 | 说明 |
|---|---|
| `id/tenant_id` | 应用主键和所属租户 |
| `app_code` | 全局唯一、稳定编码 |
| `app_name` | 应用名称 |
| `auth_type` | `SESSION` 或 `API_TOKEN` |
| `internal_client_key` | 内部端对应现有 `LoginUser.clientKey`,外部端为空 |
| `token_hash` | 外部应用完整令牌的 SHA-256,仅保存摘要 |
| `status` | `ACTIVE` / `DISABLED` |
| `rate_limit_per_minute` | 应用级动态限流 |
| `expires_time` | 令牌到期时间,可空 |
| 审计字段 | 创建、更新、轮换人员和时间 |
应用令牌建议格式为 `ak_<appCode>_<32字节随机值>`。明文仅在创建或轮换成功后显示一次,服务端只保存完整令牌 SHA-256,并使用常量时间比较。令牌只能保存在美途小程序云函数或业务后端,不能写进小程序包或浏览器 JavaScript。
### 9.4 `aihr_knowledge_app_space`
字段:`id/tenant_id/app_id/knowledge_id/create_by/create_time`。唯一约束:`(tenant_id, app_id, knowledge_id)`。应用和空间必须属于同一租户,服务端在写入时双重校验。
### 9.5 `aihr_knowledge_query_log`
保存:`request_id`、`tenant_id`、`app_id`、内部用户 ID(可空)、问题摘要哈希、使用空间编码、来源类型、结果状态、耗时、模型和 prompt 版本、创建时间。
默认不保存完整问题、完整答案、训练明细和文档正文。业务若以后要求质检原文,必须另行确定脱敏、权限和保存期限,不能直接扩大本表。
### 9.6 同一文件属于多个空间
第一版不新增抽象的文档—空间关系表,直接复用 `aihr_knowledge_attach` 作为空间成员关系:
- 同一 OSS 原文件可以对应多条 attach 记录;每条记录属于一个 `knowledge_id`。
- 同一空间内同名约束继续由 `(knowledge_id, name)` 保证。
- 不同空间的 attach 可复用相同 `oss_id`,但使用各自 `doc_id`/片段/权限。
- 解除某空间成员关系时,仅删除该空间的 attach、fragment 和 Qdrant points。
- 只有不存在其他 attach 引用同一 `oss_id` 时,才允许删除原始 OSS 对象。
- 脱敏、改写或裁剪后的版本视为新文件、新 hash 和新版本,不能假装与原文件完全相同。
异步上传队列增加 `space_codes_json`,支持一次上传选择多个目标空间。解析和 embedding 只调用一次,生成结果再分别持久化到各空间,避免重复付费调用模型。
## 10. 应用、角色与身份解析
### 10.1 内部应用
现有 `sys_client` 和 `LoginUser.clientKey` 用于识别内部调用端。新增 `aihr_knowledge_app` 保存与知识平台有关的应用策略,例如:
| app_code | auth_type | internal_client_key | 场景 |
|---|---|---|---|
| `yc_admin` | SESSION | `pc` | 银城管理端 |
| `yc_mobile` | SESSION | `app` | 银城员工/主管端 |
| `mt_card_miniapp` | API_TOKEN | 空 | 美途名片小程序后端 |
同一 `clientKey` 若在不同租户使用,按 `tenant_id + internal_client_key` 解析,不能跨租户命中应用。
### 10.2 内部主体
- `SYS_USER`:从 `LoginUser.rolePermission` 解析角色授权。
- `APP_USER`:从组织快照和岗位级别解析业务角色;普通人员至少映射 `employee`,主管/项目负责人映射 `supervisor`。
- 用户级授权:按服务端登录用户 ID 叠加,但仍受应用授权限制。
- 项目范围:继续复用组织同步数据,不接受客户端自报项目编码扩权。
## 11. 检索与向量隔离
### 11.1 MySQL Fulltext
所有召回 SQL 必须包含:
```sql
WHERE f.tenant_id = :tenantId
AND f.knowledge_id IN (:effectiveKnowledgeIds)
```
禁止继续只用知识库中文名称或空分类控制范围。
### 11.2 Qdrant
第一版继续使用共享 collection `aihr_knowledge`,payload 已包含 `tenant_id` 和 `knowledge_id`。查询过滤固定为:
```text
must:
tenant_id == currentTenantId
knowledge_id match any effectiveKnowledgeIds
```
如果 Qdrant 客户端尚不支持 `match.any`,先实现该过滤结构;不得为了省事去掉 `knowledge_id` 条件。应用请求不触发跨 collection 或跨租户合并。
### 11.3 生成约束
- LLM 输入仅包含已授权、重排后的证据。
- system prompt 明确公司制度类问题不得依靠模型常识补齐。
- 引用结果在返回前再次核对 `tenant_id + knowledge_id`。
- 外部应用使用专用 prompt,禁止输出内部操作说明、内部人员信息或“可能存在”的内部内容。
## 12. 管理端方案
新增管理页面 `/knowledge/spaces`,菜单名“知识空间”,包含三个页签:
1. **知识空间**:查看、创建、编辑、启停;显示租户、编码、密级、文档数、片段数、负责人和状态。
2. **空间授权**:按角色或指定用户配置 READ/MANAGE,展示实际生效范围。
3. **调用应用**:创建内部/外部应用、绑定空间、配置限流、轮换或停用令牌;明文令牌只显示一次。
现有 SOP 知识库页和资料处理页改为以空间为目标:
- 搜索时使用服务端授权范围,可选择授权内空间做收窄。
- 同步单文件上传可选择一个或多个空间。
- 异步批量上传记录保存目标空间集合。
- 管理端不得仅靠隐藏下拉选项实现权限;服务端必须重新校验 MANAGE 权限。
移动端不暴露任意空间选择器,避免用户误认为“看见空间名称就有权限”。页面继续以“问师傅”等业务语言呈现,空间选择由服务端按应用、角色和岗位自动计算。
## 13. 外部应用安全
1. 外部接口必须使用 HTTPS。
2. Bearer 令牌只能由服务端、云函数或可信后端持有。
3. 每个应用独立令牌、独立授权空间、独立限流和独立停用开关。
4. 使用现有 Redis 限流能力按 `appId` 控制每分钟请求数;超限返回 429。
5. 认证失败统一返回 401,不泄露 appCode 是否存在、令牌是否过期等内部细节。
6. 停用或到期应用不得检索、调用 LLM 或数据工具。
7. 轮换令牌生成新摘要并使旧令牌立即失效;第一版不保留双令牌宽限期。
8. 外部响应不返回 OSS 原始地址、内部用户 ID、数据库主键或管理字段。
9. 对外客户咨询设置长度限制、超时、并发、敏感词和输出脱敏。
## 14. 审计、监控与运维
### 14.1 必备指标
- 按租户、应用统计请求量、成功率、无依据率、P50/P95 延迟。
- 按知识空间统计命中量、零命中问题和引用分布。
- 按错误类型统计认证失败、无权限、限流、检索失败、模型失败。
- 跟踪外部应用令牌到期时间和最近使用时间。
- 跟踪同一文件多空间成员数和孤立 OSS 数量。
### 14.2 安全审计事件
- 应用创建、令牌创建/轮换/停用;
- 空间创建、启停、密级变化;
- 应用—空间和主体—空间授权变化;
- 明确请求未授权空间;
- 数据工具调用和拒绝;
- 跨租户 ID 组合、无有效空间仍尝试查询等异常。
## 15. 验收标准
### 15.1 功能验收
1. 银城、美途各自登录或调用时,只能列出本租户空间和应用。
2. 银城首批三个空间、美途客户咨询空间均有唯一编码、负责人、授权和验证题单。
3. 一个内部应用可绑定多个空间;一个空间可同时绑定多个内部应用。
4. 内部用户的最终范围严格等于应用授权与主体授权交集。
5. 美途名片小程序只能命中 `mt_customer_service`,不能访问银城或美途内部预留空间。
6. 显式传未授权 `spaceCodes` 返回 403;不传时只在有效空间内查询。
7. 回答包含空间编码和文档引用;无证据时返回 `noEvidence=true`。
8. 同一文件加入两个空间后,两边均能独立检索;从一个空间解绑不影响另一个空间和 OSS 原文件。
9. 本人训练工具不能查询他人;主管工具只能返回本人管理范围;外部应用调用工具被拒绝。
10. 原 `/api/knowledge/search` 兼容现有员工端,但不再因 `category=sop` 搜索租户全部空间。
### 15.2 安全验收
至少覆盖以下自动化和真实 API 反例:
| 测试 | 预期 |
|---|---|
| 银城 token + 美途 spaceCode | 403,MySQL/Qdrant/LLM 均未执行 |
| 美途 app token + 银城 spaceCode | 403 |
| 员工端 app 已授权、用户角色未授权 | 403 或空有效范围 |
| 用户已授权、当前 app 未授权 | 403 或空有效范围 |
| 禁用/过期/错误 app token | 401 |
| 超过应用限流 | 429 |
| APP_USER 请求其他 extPartyId | 服务端忽略请求值并按本人身份处理 |
| 普通员工调用团队训练工具 | 403 |
| 外部应用调用任一数据工具 | 403 |
| 删除一个空间的文件成员关系 | 其他空间仍可检索,OSS 不被删除 |
### 15.3 交付成熟度
验收结论必须分开记录:
- **开发完成**:代码、迁移、自动化测试和构建通过。
- **联调可用**:银城内部端与美途测试应用完成真实 HTTP 联调。
- **线上生效**:生产迁移、配置、部署、健康检查和回归完成。
- **正式试点验收**:业务负责人确认内容清单、授权矩阵、标准题命中、日志和运营指标。
任一前置层完成都不能替代后续层。
## 16. 发布与迁移策略
1. 先上线 schema 与后端兼容层,默认不开启任何外部应用。
2. 为现有细粒度 SOP 知识库补齐 `legacy_*` 稳定编码,先保留为回滚基线,不直接把“投诉处理 SOP”等旧库改名冒充新的“物业业务 SOP”空间。
3. 创建银城三个空间和美途客户咨询空间,按业务确认后的源文件清单重新导入或复用 OSS 成员关系;迁移前后核对 attach、fragment 和 Qdrant payload 数量。新空间验证通过前保持调用应用禁用,验证通过后再停用不再使用的 legacy 空间。
4. 配置内部应用、角色授权并做反向越权测试。
5. 切换管理端和移动端到新 `/query`,原 `/search` 保持兼容。
6. 为美途创建测试 API_TOKEN,在云函数/后端保存,完成限流和错误令牌测试。
7. 观察无依据率、跨空间拒绝、模型错误和 P95 延迟后,再启用生产外部应用。
8. 发布失败时先停用对应 `aihr_knowledge_app`,内部兼容接口可继续服务;数据库迁移只做前向修复,不破坏已有文档和片段。
## 17. 业务上线前必须提交的材料
以下不是系统设计缺口,而是正式试点必须由业务侧提交的准入材料:
1. 四个首批上线空间的负责人、维护人和审批人名单。
2. 每个空间的初始文件清单、版本日期、密级和禁止内容清单。
3. 银城角色—空间—应用授权矩阵,并确认主管、HR/培训/品质、高管的具体角色 key。
4. 美途名片小程序的可信服务端或云函数部署位置、密钥保管人和轮换责任人。
5. 每个空间至少 10 个标准问题、预期答案要点和预期引用。
6. 查询日志保留周期、外部接口日调用量预估和每分钟限流值。
在这些材料缺失时,可以完成开发和联调,但不能宣布正式试点验收完成。