-
Notifications
You must be signed in to change notification settings - Fork 155
Description
背景
Phase 1(#158)已完成 API 层多租户能力定义:身份类型、API Key 管理、认证中间件、RBAC、Admin API、Router 依赖注入迁移。
当前 RequestContext 已在 Router 层可用,但未向下传递到 Service / VikingFS / VectorDB。所有请求仍然共享同一存储空间,数据无隔离。
Phase 2 的目标是将 RequestContext 贯穿到存储层,实现 account 级路径隔离、user/agent 级权限过滤、VectorDB 租户过滤。
设计文档:docs/design/multi-tenant-design.md
RFC 讨论:#157
设计方案
AGFS 文件系统隔离(设计文档 5.3 节)
VikingFS 保持单例,不持有租户状态。多租户通过参数传递实现:
- 公开方法(
ls、read、write等)接收ctx: RequestContext - 从
ctx.account_id提取 account_id,传给内部方法 _uri_to_path加 account_id 前缀:viking://resources/doc.md+account_id="acme"→/local/acme/resources/doc.md_path_to_uri去前缀还原,对用户透明
单租户模式(multi_tenant=false)下 VikingFS 忽略 account_id,保持旧扁平路径(见设计文档第 8 节)。
逐层权限过滤(设计文档 5.4 节)
user/agent 级隔离通过 _is_accessible(uri, ctx) 实现:
- ROOT / ACCOUNT_ADMIN:可见所有条目
- USER:只能看到自己的
user_space和agent_space目录 - 列举操作(ls、tree、glob):AGFS 返回全量结果后过滤
- 读写操作(read、write、mkdir 等):执行前校验,无权限则拒绝
VectorDB 租户过滤(设计文档 5.5 节)
单 context collection,schema 新增 account_id 和 owner_space 字段。
查询过滤策略:
| 角色 | 过滤条件 |
|---|---|
| ROOT | 无 |
| ACCOUNT_ADMIN | account_id = ctx.account_id |
| USER | account_id = ctx.account_id AND owner_space IN (user_space, agent_space) |
写入时 Context 对象携带 account_id 和 owner_space,通过 EmbeddingMsgConverter 透传到 VectorDB。
Service 层适配(设计文档 T9)
- 去除
OpenVikingService的单例_user - 所有 sub-service 方法新增
ctx: RequestContext参数 - Router 层将 Phase 1 已注入的 ctx 传递给 service 方法
目录初始化(设计文档 5.6 节)
- 创建新 account 时:初始化公共根目录(
viking://user、viking://agent、viking://resources等) - 用户首次访问时:懒初始化
viking://user/{user_space}/memories/preferences等 - Agent 首次使用时:懒初始化
viking://agent/{agent_space}/memories/cases等
任务拆解
实施顺序:T6/T7 并行 → T8 → T9 → T10-P2(ctx 传递)→ T12-P2(嵌入模式)→ T13 → T14-P2
T6: VikingFS 多租户改造
修改 openviking/storage/viking_fs.py:
- 新增
_multi_tenant: bool标志 - 所有公开方法新增
ctx: RequestContext参数 _uri_to_path/_path_to_uri:多租户模式加 account_id 前缀,单租户模式保持旧路径- 新增
_is_accessible(uri, ctx)方法,列举操作过滤、读写操作校验 - 内部方法统一加
account_id: str参数
T7: VectorDB schema 扩展
修改 openviking/storage/collection_schemas.py:
context_collection()Fields 新增account_id(string)字段
T8: 检索层与数据写入的租户过滤
修改 openviking/retrieve/hierarchical_retriever.py、openviking/core/context.py:
Context类新增account_id和owner_space字段HierarchicalRetriever.retrieve()新增ctx参数,按角色注入 account_id + owner_space 过滤条件
T9: Service 层适配
修改 openviking/service/core.py 及所有 sub-service:
- 去除
_user单例 - 各 service 方法新增
ctx参数,传递给 VikingFS / Retriever - 涉及:FSService、SearchService、SessionService、ResourceService、RelationService、PackService、DebugService
T10-P2: Router ctx 传递
修改所有 router:
- Phase 1 已完成依赖注入(
Depends(get_request_context)),Phase 2 将 ctx 传给 service 方法 await service.fs.ls(uri)→await service.fs.ls(uri, ctx=ctx)
T12-P2: 嵌入模式适配
修改 openviking/client/local.py:
- 嵌入模式不做多租户,构造固定默认
RequestContext(user=default, role=ROOT)传给 service
T13: 目录初始化适配
修改 openviking/core/directories.py:
- 拆分为
initialize_account_directories/initialize_user_directories/initialize_agent_directories - 方法签名接受
ctx: RequestContext - 构造
Context时填入account_id和owner_space
T14-P2: 隔离与可见性测试
- 存储隔离测试:
_uri_to_path前缀正确性、_is_accessible行为、VectorDB 多级过滤 - 端到端集成测试:Root 创建 account → Account 注册 user → User 写数据 → 跨 account 不可见、同 account 跨 user 不可见
- 单租户模式测试(若采用设计文档第 8 节方案 A):
multi_tenant=false时扁平路径、Admin API 返回 404
关联
Metadata
Metadata
Assignees
Labels
Type
Projects
Status