feat(personal): authorize enterprise knowledge from org ACL

This commit is contained in:
2026-07-12 15:45:46 +08:00
parent 3a3562abb4
commit 2161353247
8 changed files with 471 additions and 6 deletions
+1 -1
View File
@@ -174,7 +174,7 @@ curl -fsS -X POST "$API_BASE/api/knowledge/doc/rebuild-vector-index" -H "Authori
个人知识接口统一位于 `/api/aihr/personal-assistant`,包括空间、资料列表与详情、文字/文件/URL 收藏、重试、删除、下载链接、检索、问答和会话。所有接口必须使用移动端短信登录返回的 `Authorization: Bearer <access_token>` 与 `clientid`,服务端从登录态注入 `tenant_id + owner_user_id`;请求体和查询参数不接受调用方指定 owner。
`POST /search` 与 `POST /ask` 的 `scope` 可选 `PERSONAL`、`ENTERPRISE` 或二者组合。返回引用的 `domain` 必须明确为个人或企业域;企业域只有在服务端企业知识授权策略返回显式 fragment allowlist 后才会参与 mixed 检索,未配置授权时 fail-closed。个人资料详情、下载、重试、删除、`itemIds` 检索均按 owner 过滤,不存在与越权统一返回 `PERSONAL_ITEM_NOT_FOUND`。
`POST /search` 与 `POST /ask` 的 `scope` 可选 `PERSONAL`、`ENTERPRISE` 或二者组合。返回引用的 `domain` 必须明确为个人或企业域。企业域授权只读取登录用户的 `sys_user` 手机号、同租户在职 `aihr_org_snapshot` 和启用的 `aihr_knowledge_acl`,按 `TENANT / PROJECT / POSITION` 规则在 SQL 层生成 fragment allowlist;无组织身份或 ACL 时 fail-closed。客户端不能提交岗位、项目或 fragmentId 扩权。当前是阶段二组织快照消费,不表示阶段三北森实时对接完成。个人资料详情、下载、重试、删除、`itemIds` 检索均按 owner 过滤,不存在与越权统一返回 `PERSONAL_ITEM_NOT_FOUND`。
URL 收藏在任何网络请求前执行 SSRF 校验,私网、环回、链路本地和云元数据地址返回 `PERSONAL_URL_BLOCKED`。删除先进入 `DELETING` 并立即对详情和检索隐藏,再异步清理 Qdrant、片段和 OSS;重复删除返回同一个 `cleanupJobId`。
+2
View File
@@ -198,6 +198,8 @@ curl -k -s https://peilian.njzhmj.top/h5/ | sed -n '1,20p'
个人知识使用独立 Qdrant collection,默认 `aihr_personal_knowledge`,payload 强制包含 `tenant_id`、`owner_user_id`、`item_id` 与 `captured_at`。对象存储固定使用 `personal-minio` 配置和私有 bucket `ruoyi-personal`,不修改企业资料使用的默认 `minio/ruoyi`。MySQL 表和专用 OSS 配置由 `backend/script/sql/aihr_personal_knowledge_mysql8.sql` 初始化;旧开发库先运行 `COMPOSE_PROJECT_NAME=wygj ./scripts/reset-dev-db.sh`。
企业范围问答另外依赖 `aihr_org_snapshot` 与 `aihr_knowledge_acl`。reset 会给企业 SOP `1001/1002/1003` 写入“一线生活顾问”POSITION ACL;手机号 `13900000103` 的组织快照岗位为物业管家,服务端按固定别名映射到生活顾问后获得 allowlist。普通新注册手机号没有组织快照,企业范围必须返回无权限。不要用手工手机号、客户端岗位参数或 TENANT ACL 绕过该默认拒绝;开放组织系统只负责刷新阶段二快照,北森实时组织/任职仍属阶段三。
空间与处理配额通过 `aihr.personal.*` 配置覆盖,包括空间字节配额、资料数量、单文件大小、抓取字节/超时、worker 与 cleanup 批量大小。不要把个人 collection 改回企业 `aihr_knowledge`。
启动依赖与后端后运行真实隔离 smoke:
+12 -1
View File
@@ -124,10 +124,21 @@ org.dromara.aihr.knowledge.parse
5. 个人资料转企业知识必须复制经审核后的脱敏版本,不能把个人 item 直接改成企业 scope。
6. 自动化测试必须使用两个用户交叉访问,验证列表、详情、检索、向量和删除均返回不可见。
企业知识授权由唯一生产策略 `OrgSnapshotEnterpriseKnowledgeAccessPolicy` 负责:只用登录态
`tenant_id + user_id` 查询本人 `sys_user.phonenumber`,再匹配同租户、在职的 `aihr_org_snapshot`,
最后按 `aihr_knowledge_acl` 的 `TENANT / PROJECT / POSITION` 规则生成 fragment allowlist。岗位别名
`生活顾问 / 物业管家 / 客服管家` 只在服务端归一化;无组织快照、离职、无启用 ACL、表缺失或数据库故障均默认拒绝。
这里消费的是阶段二本地/定时同步快照,不代表阶段三北森实时对接已经完成。
## 4. 数据模型
初始化 SQL:`backend/script/sql/aihr_personal_knowledge_mysql8.sql`。
企业 ACL 独立位于 `backend/script/sql/aihr_knowledge_mysql8.sql` 的 `aihr_knowledge_acl`,不向个人表添加
企业 scope。ACL 以租户和 knowledge 为边界,可按租户、项目或岗位授权,并保留 `INTERNAL / RESTRICTED`
密级字段;没有启用 ACL 的企业知识默认不可见。当前 seed 仅将 SOP `1001/1002/1003` 明确授权给一线
生活顾问岗位,没有全租户放开。
### 4.1 `aihr_personal_space`
每个租户内每名员工一条。
@@ -518,7 +529,7 @@ src/services/personal-assistant.ts API 客户端
### M3:企业知识授权融合
- 企业知识权限过滤。
- 企业知识权限过滤:组织快照 + 独立 ACL + SQL fragment allowlist 下推,默认拒绝。
- 个人/企业/mixed 三范围切换和引用域标记。
### M4:移动端闭环与试点