Skip to content

feat(acl): 增加资源 ACL、用户组授权与向量权限过滤#3213

Draft
qin-ctx wants to merge 11 commits into
mainfrom
feat/resource-acl
Draft

feat(acl): 增加资源 ACL、用户组授权与向量权限过滤#3213
qin-ctx wants to merge 11 commits into
mainfrom
feat/resource-acl

Conversation

@qin-ctx

@qin-ctx qin-ctx commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Description

为 OpenViking 的 viking://resources/... 共享区增加协作文档式 ACL,并让文件操作、维护操作和向量检索使用同一套权限语义。

个人区 viking://user/{user_id}/resources/... 保持 owner 私有;需要共享时将资源移动到共享区。共享区支持用户、用户组和 user:*,目录授权向所有后代累加继承,子节点只能增加授权,不覆盖祖先授权。

ACL 不创建独立 collection,也不写入 JSON/tags。direct 和 inherited 权限保存在 context collection 的原生 list<string> 标量字段中,find/search 可直接在向量查询阶段过滤。

本轮同时把历史上的 write、delete 和新加入的 reindex 特判收敛到 VikingFS 的统一能力检查,避免继续维护多套近似但不一致的 access 逻辑。

Human Involvement

  • A human participated in the implementation or review loop
  • This PR was generated entirely by AI agents without human participation in the loop

Related Issue

无。

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test update

Changes Made

1. ACL 模型与存储

  • Principal:user:{user_id}group:{group_id}user:*
  • Level:viewer -> readeditor -> read + writemanager -> read + write + manage
  • 内部固定值使用 AclLevelAclAction 两个 str + Enum;HTTP/CLI 与 context 标量仍使用相同字符串值,协议和存储格式不变。
  • 当前 account 的 ADMIN 是共享区隐式 manager;个人区不接受 ACL。
  • 有效权限为当前节点和所有祖先 direct ACL 的并集,不支持 deny 或子节点收窄祖先授权。
  • context 记录保存 acl_direct_{read,write,manage}_principal_idsacl_inherited_{read,write,manage}_principal_ids 和派生字段 acl_enabled
  • 修改目录 ACL 或移动共享子树时批量重算 inherited 字段;direct ACL 仍是权限真相。
  • 旧记录缺少 ACL 字段时等价于 acl_enabled=false,继续使用升级前 URI 规则,不要求全量回填。

2. 统一鉴权入口

单节点强制鉴权统一为 _ensure_access(uri, ctx, *, action=AclAction.READ),批量操作统一为 _ensure_access_many(uris, ctx, *, action)_can_access/_can_access_many 只负责过滤和布尔判断。write/manage 调用必须显式传枚举,运行时拒绝裸字符串 action,避免拼写错误或错误分支。

每次强制鉴权按固定顺序执行:

canonicalize URI
  -> account / owner / actor-peer / system namespace 硬边界
  -> 隐式 manager、有效 ACL 或 acl_enabled=false 的 legacy fallback
  -> write/manage namespace 防护

_ensure_mutable_access_ensure_delete_access 和 reindex 路由 _authorize_reindex_uri 已删除。原 URI access 规则只保留为不可绕过的 namespace 边界,以及未启用 ACL 时的兼容回退,不再维护第二套操作权限。

操作映射:

操作 能力
read、stat、list/tree、find/search/grep/glob、relations read
write/create、mkdir、set tags、reindex write
delete、move 源节点 manage
move 目标 write
set/grant/revoke/delete ACL manage

首次在共享节点建立 ACL 是唯一 bootstrap:ACL 尚未启用时仅共享区隐式 manager 可设置;启用后按有效 manage 判断。

3. 写入、删除、移动与 reindex

  • 普通写入和递归 set tags 走统一 write;递归操作先批量校验,避免部分成功。
  • 删除走 manage;递归删除完整扫描并校验子树后才产生副作用。
  • move 要求来源子树 manage、目标 write。共享区内部保留 direct ACL 并按新祖先重算 inherited;个人区与共享区之间移动时按目标 scope 清理或继承 ACL。
  • reindex 路由只做认证和请求格式校验;service canonicalize URI;executor 校验 target 类型和 mode 后,在创建任务或执行工作前调用统一 write 鉴权。USER、ADMIN、ROOT 不再各自维护 reindex scope 特判。
  • user config 的 add target 校验改为真正 await 统一 write 鉴权,修复原同步包装调用 async helper、实际未执行权限检查的问题。
  • viking:// account 根只允许管理员执行 write 类维护;删除仍由 namespace 防护禁止。

4. 检索与用户组

检索身份由服务端从请求上下文生成:

[user:{ctx.user_id}, user:*] + [group:{id} for id in ctx.group_ids]

共享区向量查询对 direct/inherited read principal 字段执行原生 contains-any 过滤。target URI 只限制检索范围,不要求中间目录可读,因此深层文件被直接授权后仍可召回。

用户组按 account 持久化稳定 group_id。增删成员只改变后续请求的 RequestContext.group_ids,不展开用户列表,也不重写资源 context;退出组后下一次请求立即失去对应授权。

5. 最小 CLI 示例

直接授权并验证读取、检索和 reindex:

ov acl grant viking://resources/project-a --principal user:bob --level editor
ov acl get viking://resources/project-a

# 使用 Bob 的 user API key
ov find "deployment guide" -u viking://resources/project-a
ov reindex viking://resources/project-a --mode vectors_only --wait true

组授权无需逐个维护资源 ACL:

ov --sudo admin create-group acme Engineering
ov --sudo admin add-group-member acme grp_0123 bob
ov acl grant viking://resources/project-a --principal group:grp_0123 --level viewer

# 移出组后,下一次请求立即撤权,不重写资源记录
ov --sudo admin remove-group-member acme grp_0123 bob

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have tested this on the following platforms:
    • Linux
    • macOS
    • Windows

本轮合并与鉴权重构验证:

  • ACL、URI guard、watch task、move rollback、add target、reindex 和 content write 定向回归:60 passed
  • Python 变更:ruff checkcompileallgit diff --check 通过,旧鉴权 helper 引用为 0。
  • 测试变更保持克制:用一个端到端 wiring 测试替换 reindex 路由特判矩阵,仅新增一个 account 根写保护回归;其余只更新已有 fake。
  • 本 PR 此前验证:Rust CLI cargo test -p ov_cli390 passed;Go SDK go test ./... 通过。
  • GitHub Actions 已通过 Build Docsplugin-testscheck-deps 及 Rust 多平台构建。

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Screenshots (if applicable)

不适用,改动为服务端、存储、SDK 和 CLI 能力。

Additional Notes

  • 已合并最新 maina0e822a0)并处理冲突:保留 main 的 canonical URI 行为,同时保留 ACL 分支的批量向量 URI 更新与失败回滚;冲突测试只保留两个可发现真实回归的用例。
  • 本地存量 context collection 启动时自动增加 ACL 字段和标量索引,旧记录不回填;远端 VikingDB collection 由部署方添加字段和索引,服务启动时校验。
  • 设计与使用文档:docs/zh/concepts/15-acl.mddocs/zh/api/12-acl.mddocs/zh/api/07-system.md,并同步维护英文版本。

Persist direct and inherited ACL fields in context records so filesystem operations and vector retrieval enforce the same permissions.
@qin-ctx qin-ctx changed the title feat(acl): 增加资源 ACL 与向量检索权限过滤 feat(acl): 增加资源 ACL、用户组授权与向量权限过滤 Jul 13, 2026
qin-ctx added 8 commits July 13, 2026 17:29
确保 ACL 更新结果与锁内状态一致,移动失败可恢复向量 URI,并让后台解析沿用发起请求的用户组身份。精简重复实现和低价值测试。
个人资源保持 owner 私有,分享通过移动到共享区完成;跨区移动按目标 scope 继承或清空 ACL,并将向量权限过滤限制在共享区。
恢复 telemetry 空上下文和 import 的基线写法,仅保留 ACL 用户组身份传递。
ACL 元数据读取失败时终止权限判断,并确保 grep 的 node_limit 作用于权限过滤后的可见结果。
删除重复、时序绑定和实现细节测试,并撤销非必要的 grep 循环扩容。保留用例只覆盖独立的安全、一致性和兼容性故障。
# Conflicts:
#	openviking/storage/viking_fs.py
#	tests/storage/test_semantic_processor_mv_vector_store.py
将 write、delete 和 reindex 收敛到 read/write/manage 能力检查,并修复 add target 权限校验未等待的问题。
用 AclAction 和 AclLevel 约束内部权限分支,拒绝裸字符串 action,并保持 API 与存储字符串格式兼容。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant