feat(backend): implement Tri-Domain Knowledge Architecture
This commit is contained in:
parent
a71f4051d2
commit
2a1c33539f
@ -15,7 +15,8 @@ async def process_uploaded_material_oss(
|
|||||||
original_filename: str,
|
original_filename: str,
|
||||||
context_id: str,
|
context_id: str,
|
||||||
push_event_fn,
|
push_event_fn,
|
||||||
user_id: str
|
user_id: str,
|
||||||
|
org_id: str = "org_001"
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
1. Downloads native PDF from OSS
|
1. Downloads native PDF from OSS
|
||||||
@ -53,7 +54,11 @@ async def process_uploaded_material_oss(
|
|||||||
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
||||||
storage_root = Path(storageDir)
|
storage_root = Path(storageDir)
|
||||||
user_id_safe = user_id if user_id else "unknown"
|
user_id_safe = user_id if user_id else "unknown"
|
||||||
|
org_id_safe = org_id if org_id else "org_001"
|
||||||
|
|
||||||
user_dir = storage_root / "users" / user_id_safe
|
user_dir = storage_root / "users" / user_id_safe
|
||||||
|
org_dir = storage_root / "orgs" / org_id_safe
|
||||||
|
platform_dir = storage_root / "platform"
|
||||||
|
|
||||||
ext = os.path.splitext(original_filename)[1].lower()
|
ext = os.path.splitext(original_filename)[1].lower()
|
||||||
|
|
||||||
@ -86,7 +91,13 @@ async def process_uploaded_material_oss(
|
|||||||
raw_path = base_dir / f"{file_hash}_raw{ext}"
|
raw_path = base_dir / f"{file_hash}_raw{ext}"
|
||||||
md_path = base_dir / f"{file_hash}.md"
|
md_path = base_dir / f"{file_hash}.md"
|
||||||
elif context_id.startswith("wiki:") or context_id == "deepview":
|
elif context_id.startswith("wiki:") or context_id == "deepview":
|
||||||
base_dir = storage_root / "wiki"
|
# 存入本机构域的 wiki 库
|
||||||
|
base_dir = org_dir / "wiki"
|
||||||
|
raw_path = base_dir / f"{file_hash}_raw{ext}"
|
||||||
|
md_path = base_dir / f"{file_hash}.md"
|
||||||
|
elif context_id.startswith("platform:"):
|
||||||
|
# 预留平台运维口
|
||||||
|
base_dir = platform_dir / "wiki"
|
||||||
raw_path = base_dir / f"{file_hash}_raw{ext}"
|
raw_path = base_dir / f"{file_hash}_raw{ext}"
|
||||||
md_path = base_dir / f"{file_hash}.md"
|
md_path = base_dir / f"{file_hash}.md"
|
||||||
elif context_id.startswith("doctor:"):
|
elif context_id.startswith("doctor:"):
|
||||||
|
|||||||
@ -180,6 +180,13 @@ class DeepviewSSEServer:
|
|||||||
os.makedirs(userDir, exist_ok=True)
|
os.makedirs(userDir, exist_ok=True)
|
||||||
return userDir
|
return userDir
|
||||||
|
|
||||||
|
def _getOrgStorageDir(self, orgId: str) -> str:
|
||||||
|
"""返回机构的存储沙箱根路径,不存在时自动创建。"""
|
||||||
|
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
||||||
|
orgDir = os.path.join(storageDir, "orgs", orgId)
|
||||||
|
os.makedirs(orgDir, exist_ok=True)
|
||||||
|
return orgDir
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
# ──────────────────────────────────────────────
|
||||||
# ──────────────────────────────────────────────
|
# ──────────────────────────────────────────────
|
||||||
|
|
||||||
@ -525,10 +532,15 @@ class DeepviewSSEServer:
|
|||||||
userObj = await self._extractUser(request)
|
userObj = await self._extractUser(request)
|
||||||
userId = userObj.get("sub", "unknown") if userObj else "unknown"
|
userId = userObj.get("sub", "unknown") if userObj else "unknown"
|
||||||
|
|
||||||
# 从环境变量获取存储根目录,并获取用户专属沙箱
|
# 从环境变量获取存储根目录,并获取用户专属沙箱与机构知识域
|
||||||
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
||||||
userDir = self._getUserStorageDir(userId)
|
userDir = self._getUserStorageDir(userId)
|
||||||
|
|
||||||
|
# 解析 orgId
|
||||||
|
orgId = userObj.get("org", "org_001") if userObj else "org_001"
|
||||||
|
orgDir = self._getOrgStorageDir(orgId)
|
||||||
|
platformDir = os.path.join(storageDir, "platform")
|
||||||
|
|
||||||
# 1. 加载唯一的 SKILL.md (上下文无关版)
|
# 1. 加载唯一的 SKILL.md (上下文无关版)
|
||||||
skillPath = os.path.join(
|
skillPath = os.path.join(
|
||||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
|
||||||
@ -557,7 +569,8 @@ class DeepviewSSEServer:
|
|||||||
## 🎙️ 当前上下文模式:单次面诊录音复盘
|
## 🎙️ 当前上下文模式:单次面诊录音复盘
|
||||||
- 录音 ASR 文件:{asrPath}
|
- 录音 ASR 文件:{asrPath}
|
||||||
- 医生风格档案:{userDir}/doctor_profile.md
|
- 医生风格档案:{userDir}/doctor_profile.md
|
||||||
- 企业知识库目录:{storageDir}/wiki/
|
- 企业知识库目录:{orgDir}/wiki/
|
||||||
|
- 平台规则参考:{platformDir}/wiki/
|
||||||
|
|
||||||
### 你的工作重心
|
### 你的工作重心
|
||||||
基于这一次面诊录音,分析信任断点、沟通体征、改进建议。
|
基于这一次面诊录音,分析信任断点、沟通体征、改进建议。
|
||||||
@ -572,14 +585,15 @@ class DeepviewSSEServer:
|
|||||||
- 核心档案:{userDir}/clients/{clientId}/profile.md
|
- 核心档案:{userDir}/clients/{clientId}/profile.md
|
||||||
- 历史录音目录:{userDir}/clients/{clientId}/history/
|
- 历史录音目录:{userDir}/clients/{clientId}/history/
|
||||||
- 医生风格档案:{userDir}/doctor_profile.md
|
- 医生风格档案:{userDir}/doctor_profile.md
|
||||||
- 企业知识库目录:{storageDir}/wiki/
|
- 企业知识库目录:{orgDir}/wiki/
|
||||||
|
- 平台规则参考:{platformDir}/wiki/
|
||||||
|
|
||||||
### 你的工作重心
|
### 你的工作重心
|
||||||
基于该客户的全生命周期数据,提供诊前策略、社交杠杆分析、跨品类破冰方案。
|
基于该客户的全生命周期数据,提供诊前策略、社交杠杆分析、跨品类破冰方案。
|
||||||
优先读取 profile.md 获取全景概览,必要时深入 history/ 追溯原始录音细节。
|
优先读取 profile.md 获取全景概览,必要时深入 history/ 追溯原始录音细节。
|
||||||
"""
|
"""
|
||||||
else:
|
else:
|
||||||
systemPrompt += f"\n\n## 通用模式\n企业知识库目录:{storageDir}/wiki/\n"
|
systemPrompt += f"\n\n## 通用模式\n企业知识库目录:{orgDir}/wiki/\n平台规则参考:{platformDir}/wiki/\n"
|
||||||
|
|
||||||
# 3. 加载上下文履历,实现真正的 Stateful Context
|
# 3. 加载上下文履历,实现真正的 Stateful Context
|
||||||
history = db.get_messages_as_conversation(chatId)
|
history = db.get_messages_as_conversation(chatId)
|
||||||
@ -649,7 +663,13 @@ class DeepviewSSEServer:
|
|||||||
userObj = await self._extractUser(request)
|
userObj = await self._extractUser(request)
|
||||||
userId = userObj.get("sub", "unknown") if userObj else "unknown"
|
userId = userObj.get("sub", "unknown") if userObj else "unknown"
|
||||||
userDir = self._getUserStorageDir(userId)
|
userDir = self._getUserStorageDir(userId)
|
||||||
|
|
||||||
|
# 解析 orgId
|
||||||
|
orgId = userObj.get("org", "org_001") if userObj else "org_001"
|
||||||
|
orgDir = self._getOrgStorageDir(orgId)
|
||||||
|
|
||||||
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
storageDir = os.getenv("DEEPVIEW_STORAGE_DIR", os.path.expanduser("~/Downloads/Coding/医生助理智能体/backend/storage"))
|
||||||
|
platformDir = os.path.join(storageDir, "platform")
|
||||||
|
|
||||||
# 构建基础 Prompt
|
# 构建基础 Prompt
|
||||||
systemPrompt = "你是深维面诊智能军师。\n"
|
systemPrompt = "你是深维面诊智能军师。\n"
|
||||||
@ -662,6 +682,10 @@ class DeepviewSSEServer:
|
|||||||
systemPrompt = f.read()
|
systemPrompt = f.read()
|
||||||
|
|
||||||
systemPrompt = systemPrompt.replace("{{STORAGE_DIR}}", storageDir)
|
systemPrompt = systemPrompt.replace("{{STORAGE_DIR}}", storageDir)
|
||||||
|
# 兼容一下如果 prompt 里有企业知识库占位
|
||||||
|
# (因为 V3 里移除了,如果有人加回来,这里替换)
|
||||||
|
systemPrompt = systemPrompt.replace(f"{storageDir}/wiki/", f"{orgDir}/wiki/")
|
||||||
|
systemPrompt += f"\n\n## 规则遵循\n企业知识库:{orgDir}/wiki/\n平台规则:{platformDir}/wiki/\n"
|
||||||
|
|
||||||
if contextId.startswith("recording:"):
|
if contextId.startswith("recording:"):
|
||||||
recordingId = contextId.split(":", 1)[1]
|
recordingId = contextId.split(":", 1)[1]
|
||||||
@ -1103,7 +1127,8 @@ xray.module5: track1(数组,每项含node/action/strategy/purpose), track2(数
|
|||||||
original_filename=filename,
|
original_filename=filename,
|
||||||
context_id=context_id,
|
context_id=context_id,
|
||||||
push_event_fn=self._pushEvent,
|
push_event_fn=self._pushEvent,
|
||||||
user_id=user["userId"]
|
user_id=user["userId"],
|
||||||
|
org_id=user.get("org", "org_001")
|
||||||
)
|
)
|
||||||
# 2. X-ray stage (Auto orchestrate)
|
# 2. X-ray stage (Auto orchestrate)
|
||||||
if context_id.startswith("recording:"):
|
if context_id.startswith("recording:"):
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
## ⚙️ 先决上下文 (Required Context)
|
## ⚙️ 先决上下文 (Required Context)
|
||||||
- `<CLIENT_PROFILE>`: `storage/users/{userId}/clients/{client_id}/profile.md`
|
- `<CLIENT_PROFILE>`: `storage/users/{userId}/clients/{client_id}/profile.md`
|
||||||
- `<WIKI>`: `storage/wiki/`
|
- `<WIKI>`: 机构知识库 `storage/orgs/{orgId}/wiki/`,以及平台规则 `storage/platform/wiki/`
|
||||||
- `<NEW_ASR_INPUT>`: `storage/users/{userId}/clients/{client_id}/history/{date}.md`或者 `inbox` 裸推演
|
- `<NEW_ASR_INPUT>`: `storage/users/{userId}/clients/{client_id}/history/{date}.md`或者 `inbox` 裸推演
|
||||||
|
|
||||||
## 🧠 运行指令 (Execution Instructions)
|
## 🧠 运行指令 (Execution Instructions)
|
||||||
|
|||||||
193
docs/SPEC_tri_domain_knowledge_architecture.md
Normal file
193
docs/SPEC_tri_domain_knowledge_architecture.md
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
# SPEC: 三元知识域架构 (Tri-Domain Knowledge Architecture)
|
||||||
|
|
||||||
|
> **版本**: v1.0
|
||||||
|
> **前置依赖**: [SPEC_deepview_metadata_scoping_v3.md](./SPEC_deepview_metadata_scoping_v3.md) (Prosumer-First 沙箱隔离)
|
||||||
|
> **设计哲学**: [DESIGN_PHILOSOPHY_AI_NATIVE.md](./DESIGN_PHILOSOPHY_AI_NATIVE.md) (AI-Native 产品心法)
|
||||||
|
> **状态**: 草案 (Proposal)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 问题陈述
|
||||||
|
|
||||||
|
V3 SPEC 成功地将用户数据(客户档案、录音、个人风格)锁死在 `storage/users/{userId}/` 的物理沙箱内。但当前的 `storage/wiki/` 仍然是一个**无主的全局公域**——任何经过认证的用户上传的知识库文件,都会落入这个公有池,并被所有用户的 Agent 无差别读取。
|
||||||
|
|
||||||
|
在单机构运营阶段,这不构成安全问题。但本产品作为一款轻量级 SaaS 工具,**将很快遇到多家医疗机构同时使用的场景**。届时:
|
||||||
|
|
||||||
|
| 风险 | 场景 |
|
||||||
|
|------|------|
|
||||||
|
| **知识污染** | A 机构的"报价策略.md"被 B 机构医生的 Agent 读取,导致 AI 输出了竞争对手的定价策略 |
|
||||||
|
| **方法论冲突** | A 机构上传的"保守型话术规范"与 B 机构的"激进型破冰话术"同在一个池中,Agent 无法判断听谁的 |
|
||||||
|
| **逆向泄密** | 医生在对话中追问"知识库里有什么内容",Agent 如实汇报,变相暴露了其他机构的核心商业资产 |
|
||||||
|
|
||||||
|
**结论**:`wiki/` 需要从"一个桶"裂变为"三元域",否则沙箱隔离只做了一半。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 三元域模型 (Tri-Domain Model)
|
||||||
|
|
||||||
|
### 2.1 架构总览
|
||||||
|
|
||||||
|
```
|
||||||
|
storage/
|
||||||
|
├── platform/ ← 🌐 Domain 1: 平台域 (Platform)
|
||||||
|
│ └── wiki/
|
||||||
|
│ ├── system_instructions.md # 系统级行为约束
|
||||||
|
│ └── medical_ethics_baseline.md # 医疗合规底线
|
||||||
|
│
|
||||||
|
├── orgs/ ← 🏢 Domain 2: 机构域 (Organization)
|
||||||
|
│ ├── {orgId_A}/
|
||||||
|
│ │ └── wiki/
|
||||||
|
│ │ ├── rfm_rules.md # A机构的 RFM 客群规则
|
||||||
|
│ │ ├── pricing_2026.md # A机构的报价表
|
||||||
|
│ │ └── talk_track_v3.md # A机构的话术规范
|
||||||
|
│ │
|
||||||
|
│ └── {orgId_B}/
|
||||||
|
│ └── wiki/
|
||||||
|
│ └── ... # B机构的独立知识库
|
||||||
|
│
|
||||||
|
└── users/ ← 👤 Domain 3: 个人域 (User)
|
||||||
|
└── {userId}/
|
||||||
|
├── clients/ # 私有客户档案 (V3 已实现)
|
||||||
|
├── inbox/ # 未归档录音 (V3 已实现)
|
||||||
|
└── doctor_profile.md # 个人风格画像 (V3 已实现)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 三元域的职责定义
|
||||||
|
|
||||||
|
| 域 | 物理路径 | 写入权限 | 读取权限 | 内容特征 |
|
||||||
|
|----|---------|---------|---------|---------|
|
||||||
|
| **平台域** `platform/wiki/` | 仅运维/开发者 | 所有用户(只读) | 通用底线:医疗合规、AI 行为红线、系统级兜底 Prompt |
|
||||||
|
| **机构域** `orgs/{orgId}/wiki/` | 机构管理员 | 该机构下所有用户 | 企业差异化资产:RFM 规则、定价表、话术方法论、培训心法 |
|
||||||
|
| **个人域** `users/{userId}/` | 用户本人 | 仅用户本人 | 私有工作数据:客户、录音、个人风格、Inbox |
|
||||||
|
|
||||||
|
### 2.3 上下文注入优先级
|
||||||
|
|
||||||
|
当 Agent 构建 System Prompt 时,三元域按**由近及远**的优先级叠加注入:
|
||||||
|
|
||||||
|
```
|
||||||
|
[优先级 1] 个人域 → doctor_profile.md, 当前客户 profile.md
|
||||||
|
[优先级 2] 机构域 → orgs/{orgId}/wiki/*
|
||||||
|
[优先级 3] 平台域 → platform/wiki/*
|
||||||
|
```
|
||||||
|
|
||||||
|
**冲突解决原则**:近域覆盖远域。如果个人域的 `doctor_profile.md` 声明了"我不使用激进话术",即使机构域的 `talk_track_v3.md` 中含有激进话术范例,Agent 应优先遵从个人偏好。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 用户与机构的关系模型
|
||||||
|
|
||||||
|
### 3.1 Prosumer 生命周期
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
|
│ Phase 1: 自由人 (Freelancer) │
|
||||||
|
│ ─ 注册即可用,无需任何机构归属 │
|
||||||
|
│ ─ Agent 读取: platform/wiki/* + users/{userId}/* │
|
||||||
|
│ ─ orgs 层级对该用户透明(不存在) │
|
||||||
|
├──────────────────────────────────────────────────────────────┤
|
||||||
|
│ Phase 2: 受邀加入机构 (Org Member) │
|
||||||
|
│ ─ 机构管理员发出邀请码,用户确认加入后绑定 orgId │
|
||||||
|
│ ─ Agent 读取: platform/* + orgs/{orgId}/* + users/{userId}/* │
|
||||||
|
│ ─ 个人域数据对机构管理员不可见(除非显式授权移交) │
|
||||||
|
├──────────────────────────────────────────────────────────────┤
|
||||||
|
│ Phase 3: 授权联邦 (Federation) [远期预留] │
|
||||||
|
│ ─ 医生主动授权特定客户档案向机构汇报系统开放 │
|
||||||
|
│ ─ 机构管理层获得聚合视图(只读),不触碰个人原始录音 │
|
||||||
|
└──────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 数据流向的不可逆栅栏
|
||||||
|
|
||||||
|
- **上行不可逆**:个人域数据只有经用户显式确认后,才可拷贝(非移动)至机构域的聚合报告。机构管理员永远不可直接遍历 `users/{userId}/` 目录。
|
||||||
|
- **下行只读注入**:机构域和平台域对个人域的影响仅限于"知识注入"(Agent Prompt 中追加上下文)。任何域都不能向个人域写入文件。
|
||||||
|
- **跨机构绝对隔离**:`orgs/{orgId_A}/` 与 `orgs/{orgId_B}/` 之间零交集。一个用户同时隶属两家机构时,Agent 只加载当前活跃会话所选的机构上下文。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 现有 `wiki/` 的迁移路径
|
||||||
|
|
||||||
|
当前 `storage/wiki/gemini_rfm_rules.md` 实质上是某一家机构的商业方法论,不应继续驻留在全局公域。
|
||||||
|
|
||||||
|
### 4.1 迁移策略(渐进式)
|
||||||
|
|
||||||
|
| 阶段 | 动作 | 影响 |
|
||||||
|
|------|------|------|
|
||||||
|
| **Phase 0 (当前)** | `storage/wiki/` 保持原址不动 | 继续服务单机构运营,无破坏性 |
|
||||||
|
| **Phase 1 (首次多机构)** | 引入 `storage/platform/wiki/` 存放通用底线;将 `storage/wiki/` 整体 rename 为 `storage/orgs/{首个orgId}/wiki/` | 一次性 rename,后端路径切换 |
|
||||||
|
| **Phase 2 (稳态)** | 新机构入驻时,由运维在 `storage/orgs/{newOrgId}/wiki/` 下初始化空目录 | 零干扰,增量部署 |
|
||||||
|
|
||||||
|
### 4.2 后端改动影响面预估
|
||||||
|
|
||||||
|
需改动的位置与 V3 沙箱重构完全同构,核心变量仅从 `storageDir + "/wiki"` 变为 `storageDir + "/orgs/" + orgId + "/wiki"`:
|
||||||
|
|
||||||
|
| 文件 | 函数 | 变更内容 |
|
||||||
|
|------|------|---------|
|
||||||
|
| `deepview_sse.py` | `_handleChat` | Prompt 中 wiki 路径追加 orgId |
|
||||||
|
| `deepview_sse.py` | `_handleReportGenerate` | 同上 |
|
||||||
|
| `deepview_materials.py` | `process_uploaded_material_oss` | `wiki:` 上下文路由至 `orgs/{orgId}/wiki/` |
|
||||||
|
| `deepview_sse.py` | `_handleMaterialsList` | 列表查询时过滤至当前用户 orgId |
|
||||||
|
|
||||||
|
### 4.3 前端改动
|
||||||
|
|
||||||
|
- 零改动(与 V3 一致)。orgId 通过 JWT Token 中的 claim(如 `org` 字段)透传,前端感知不到域的存在。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 安全边界与防御策略
|
||||||
|
|
||||||
|
### 5.1 物理隔离防线
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 防路径穿越攻击:所有用户可控的 path 片段必须经过白名单校验
|
||||||
|
def _sanitizePath(segment: str) -> str:
|
||||||
|
"""只允许字母数字下划线连字符,严禁 .. / \\ 等"""
|
||||||
|
import re
|
||||||
|
if not re.match(r'^[a-zA-Z0-9_\-]+$', segment):
|
||||||
|
raise ValueError(f"Invalid path segment: {segment}")
|
||||||
|
return segment
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Agent 工具权限矩阵
|
||||||
|
|
||||||
|
| Agent 工具 | 平台域 | 机构域 (本org) | 机构域 (他org) | 个人域 (本人) | 个人域 (他人) |
|
||||||
|
|-----------|--------|--------------|--------------|-------------|-------------|
|
||||||
|
| `file_read` | ✅ | ✅ | ❌ | ✅ | ❌ |
|
||||||
|
| `file_write` | ❌ | ❌ | ❌ | ✅ | ❌ |
|
||||||
|
| `file_list` | ✅ | ✅ | ❌ | ✅ | ❌ |
|
||||||
|
|
||||||
|
### 5.3 审计日志(远期)
|
||||||
|
|
||||||
|
对 `orgs/{orgId}/wiki/` 目录的任何写入操作,应记录 `(timestamp, userId, action, filePath)` 至审计表,支持机构管理员追溯"谁在什么时候传了什么"。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 与 V3 SPEC 的关系
|
||||||
|
|
||||||
|
本 SPEC 是 V3 的**正统延伸**,不是替代。二者的关系为:
|
||||||
|
|
||||||
|
- **V3 SPEC** 解决了"个人域"的物理隔离问题(`users/{userId}/`)
|
||||||
|
- **本 SPEC** 在 V3 之上,向外延伸了"机构域"(`orgs/{orgId}/`)和"平台域"(`platform/`),形成完整的三元安全边界
|
||||||
|
|
||||||
|
三者合并后的**完整隔离模型**:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Platform Domain (只读注入, 运维独占写) │
|
||||||
|
│ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ Org Domain (机构管理员写, 成员只读) │ │
|
||||||
|
│ │ ┌─────────────────────────────────────┐ │ │
|
||||||
|
│ │ │ User Domain (用户独占读写) │ │ │
|
||||||
|
│ │ │ ┌──────────────────────┐ │ │ │
|
||||||
|
│ │ │ │ Client Data (归档后) │ │ │ │
|
||||||
|
│ │ │ └──────────────────────┘ │ │ │
|
||||||
|
│ │ │ ┌──────────────────────┐ │ │ │
|
||||||
|
│ │ │ │ Inbox (裸推演态) │ │ │ │
|
||||||
|
│ │ │ └──────────────────────┘ │ │ │
|
||||||
|
│ │ └─────────────────────────────────────┘ │ │
|
||||||
|
│ └─────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> *本规范为深维医生助理三元知识域架构草案,经审阅确认后,将指导后续的机构域隔离实现。*
|
||||||
Loading…
Reference in New Issue
Block a user