Skip to content

[Feature]: Multi-Tenant Phase 1 - API 层多租户能力定义 #158

@qin-ptr

Description

@qin-ptr

背景

OpenViking 当前为单租户架构:

  • 认证:单一全局 api_key,HMAC 比对
  • 无 RBAC:所有认证用户拥有完全访问权限
  • 无存储隔离:所有数据共享同一命名空间
  • 服务层OpenVikingService 持有单例 _user,不支持请求级用户上下文

需要实现多租户支持。Phase 1 聚焦 API 层能力定义,建立身份、认证、授权的基础框架,为 Phase 2 存储隔离做准备。

设计方案

设计文档:docs/design/multi-tenant-design.md
RFC 讨论:#157

两层 API Key 体系

类型 格式 解析方式 存储位置
Root Key 纯随机 token(secrets.token_hex(32) HMAC 比对 ov.conf server 段 root_api_key
User Key 纯随机 token(secrets.token_hex(32) 查内存索引 /{account_id}/_system/users.json
  • Key 无前缀,不携带身份信息
  • 认证时顺序匹配:先 HMAC 比对 root key,再查 user key 索引,均不匹配则 401

三层 RBAC

角色 枚举值 能力
ROOT root 一切:创建/删除工作区、提升用户角色、跨租户访问
ADMIN admin 用户属性(非 Key 类型),管理本工作区用户、下发 User Key、工作区内全量数据访问
USER user 访问自己的 user/agent/session/resources scope

认证流程

  1. X-API-KeyAuthorization: Bearer 提取 Key
  2. 获取 app.state.api_key_manager;若为 None(未配置 root_api_key)→ dev 模式,返回固定 ROOT 身份(account_id="default", user_id="default")
  3. HMAC 比对 root key → 匹配则返回 role=ROOT
  4. 查 user key 内存索引 → 匹配则返回 (account_id, user_id, role=ADMIN/USER)
  5. 均不匹配 → 401
  6. X-OpenViking-Agent header 读取 agent_id(默认 "default")
  7. 构造 RequestContext(UserIdentifier, Role) 注入到 Router

存储结构

/_system/accounts.json              # 全局工作区列表
/{account_id}/_system/users.json    # Per-account 用户注册表(含 key 和 role)

Phase 1 边界

  • RequestContext 在 Router 层注入,不向 Service/VikingFS 层传递(Phase 2 完成)
  • 存储路径不变,VectorDB schema 不变
  • 嵌入模式原生支持多租户(调用方直接声明身份,无 API Key 认证)

任务拆解

T1: 身份与角色类型定义

新建 openviking/server/identity.py

  • Role(str, Enum): ROOT / ADMIN / USER
  • ResolvedIdentity: 认证中间件输出(role, account_id?, user_id?, agent_id?),字段均为 Optional
  • RequestContext: 请求级上下文(UserIdentifier + Role),贯穿 Router → Service → VikingFS

T2: ServerConfig 更新

修改 openviking/server/config.py

  • api_keyroot_api_key(ROOT 身份认证)
  • root_api_keyNone 时进入 dev 模式,不区分 multi_tenant 开关

T3: API Key Manager

新建 openviking/server/api_keys.py

  • 内存索引:_user_keys: Dict[str, UserKeyEntry] 实现 O(1) 查找
  • 持久化:per-account /{account_id}/_system/users.json + 全局 /_system/accounts.json
  • resolve(api_key): HMAC 比对 root key → 查 user key 索引 → 401
  • create_account / delete_account / register_user / remove_user / regenerate_key / set_role 等管理方法

T4: 认证中间件重写

重写 openviking/server/auth.py

  • resolve_identity(): 提取 Key → APIKeyManager 解析 → 返回 ResolvedIdentity;无 api_key_manager 时返回 dev 模式默认身份
  • get_request_context(): ResolvedIdentityRequestContext(Optional 字段填入 "default")
  • require_role(*roles): 角色守卫工厂,用于 Admin API 权限检查

T5: App 初始化集成

修改 openviking/server/app.py

  • root_api_key 存在时:创建 APIKeyManager → load() → 赋值 app.state.api_key_manager
  • root_api_key 为 None 时:app.state.api_key_manager = None(dev 模式)
  • Admin Router 始终注册

T6: Router 依赖注入迁移

修改所有 router(filesystem, content, search, resources, sessions, relations, pack, system, debug, observer):

  • Depends(verify_api_key)Depends(get_request_context)
  • Phase 1 仅替换依赖注入,_ctx 接收但不向 service 层传递

T7: Admin Router

新建 openviking/server/routers/admin.py

端点 方法 权限 功能
/api/v1/admin/accounts POST ROOT 创建工作区 + 首个 admin 用户
/api/v1/admin/accounts GET ROOT 列出所有工作区
/api/v1/admin/accounts/{account_id} DELETE ROOT 删除工作区
/api/v1/admin/accounts/{account_id}/users POST ROOT, ADMIN 注册用户
/api/v1/admin/accounts/{account_id}/users GET ROOT, ADMIN 列出工作区内用户
/api/v1/admin/accounts/{account_id}/users/{user_id} DELETE ROOT, ADMIN 移除用户
/api/v1/admin/accounts/{account_id}/users/{user_id}/role PUT ROOT 修改用户角色
/api/v1/admin/accounts/{account_id}/users/{user_id}/key POST ROOT, ADMIN 重新生成 user key

ADMIN 仅能操作自己所属的 account。

T8: 客户端 SDK 更新

  • HTTP 客户端移除 account_id/user_id 参数,身份由服务端从 API Key 解析
  • 新增 agent_id 参数,通过 X-OpenViking-Agent header 发送
  • CLI 新增 admin 命令组
  • Rust CLI 新增 admin 子命令

T9: 文档更新

  • 新增中英文 Admin API 文档
  • 更新认证指南、配置指南、部署指南
  • 新增多租户示例 (examples/multi_tenant/)

T10: 测试

  • APIKeyManager 单元测试(key 生成/解析/注册检查)
  • 认证中间件测试(root key、user key、dev 模式、require_role 守卫)
  • Admin API 集成测试
  • 身份模块单元测试
  • 回归测试(现有测试适配 dev mode)

关联

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

Status

In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions