Skip to content

[2/3] feat(memory): 角色感知授权与 Agent 代操作 - #59

Open
openjiuwen-sync-bot[bot] wants to merge 42 commits into
openJiuwen-ai:mem2.0from
openjiuwenai:sync/pr-166
Open

[2/3] feat(memory): 角色感知授权与 Agent 代操作#59
openjiuwen-sync-bot[bot] wants to merge 42 commits into
openJiuwen-ai:mem2.0from
openjiuwenai:sync/pr-166

Conversation

@openjiuwen-sync-bot

@openjiuwen-sync-bot openjiuwen-sync-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

Paired: GitHub #59GitCode !166

/kind feature

变更概述

这是安全模块三阶段交付的第 2 个 PR,建立在 PR① 的认证上下文之上。

主要增加:

  • 授权层接入 AuthContext
  • ROOT 权限按照认证角色判定,不再根据空 Scope 形状推断。
  • 增加 acting_user 委托语义,支持 Agent 代表同组织、同空间用户执行受限操作。
  • Agent 代操作仅覆盖 READ、WRITE、UPDATE、DELETE,不授予 SHARE。
  • 管理面操作必须由认证上下文中的 ROOT 角色发起。
  • 更新路由权限管理器和 SQLite 权限管理器的角色感知逻辑。
  • 增加身份伪造、越权委托和向后兼容测试。

安全属性

  • auth.actor 与请求 actor 不一致时 fail closed。
  • acting_user 不能跨组织或跨空间扩权。
  • Agent 委托不能扩展到其他 Agent。
  • payload 中的角色或身份字段不能提升权限。

验证

  • PR 独有历史仅包含功能、测试、文档和格式化提交,无冗余 merge。
  • PR 变更范围 ruff check 通过。
  • PR 变更范围 ruff format --check 通过。
  • git diff --check 及冲突标记扫描通过。
  • PR② 变更测试:64 passed。
  • 最终安全相关集成测试:292 passed。

Self-checklist

  • 设计:角色感知授权方案已归档,并完成多轮内部安全审查。
  • 测试:新增 UT/集成测试已随 PR 提交。
  • 验证:预期目标与实际验证结果已在本描述中列明。
  • 接口:相关公共接口、注释、spec 与 AGENTS.md 已同步。
  • 文档:相关 feature/spec 文档已随 PR 提交。

合并信息

Merge-Order: 2/3
Depends-On: #​165(#58
Do-Not-Merge-Before: #​165
Merge-Method: merge commit(禁止 Squash)

本 PR 保持 Draft/WIP。PR① 合入后需刷新 diff,确认只剩角色感知授权与 Agent 代操作增量,再取消 Draft。

HankDUMPLINGZhong and others added 6 commits July 30, 2026 15:29
身份此前由请求体的 actor_* 字段提供(handler._actor_scope 的 docstring 自称
"Claimed"),调用方填什么就是什么,13 个动词全部可冒充任意主体。授权层本身是
对的——诚实身份读别人的 scope 正确返回 403——洞在于认证层根本不存在。

新增 src/security/:
- Authenticator 三实现(DEV / TRUSTED / API_KEY),模式在装配期选定而非每请求
  分流;错误消息一律笼统,避免主体枚举侧信道
- PrincipalKeyStore(Argon2id,OWASP 2024+ 参数),三条 resolve 路径各恰好一次
  verify 以消除 timing 侧信道;缺 argon2-cffi 时装配期抛错,不回退明文
- RateLimiter 令牌桶,挂在认证之前——Argon2 的 128MiB×4 单次成本在无限制调用下
  是放大器;桶按 peer 分并 LRU 有界,否则这个防耗尽的组件自己成为耗尽入口
- check_dev_binding 纯函数,DEV 模式绑非 loopback 时由进程入口 exit(1)

common/type_def/auth.py 提供 AuthContext(frozen,actor 与 role 均无默认值——
漏传会得到空 Scope() 即 platform-admin 全局权限)与 ContextVar 传播。

handler 改从认证上下文取身份,payload 里的 actor_* 一律 400 而非静默忽略:
静默忽略会让运维以为"我加了 actor_scope 限制"仍然生效。audit verb 的
actor_agent/actor_session 是查询谓词,语义不同,对该 verb 放行。

storage/fs_impl/encrypted_fs_store.py 补齐静态加密的 FS 侧(KV 侧上游已有):
与 EncryptedKVStore 逐条同构,不自带任何密码学,AAD 绑满五维 scope + ref。
明文兼容开关只在 provider 的 allow_plaintext 上,装饰器不重复提供。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test_identity_forgery_rejected.py 按 CLAUDE.md §5 先写后修:在改动前的 HEAD 上
跑一遍看它全红(证明漏洞真实存在),再做改动看它全绿。其中
test_identity_comes_from_context_not_payload 比"伪造被拒"更重要——前者证明堵上
之后认证与授权确实串起来了,后者只证明洞堵上了。

关键断言:
- 限流跑在认证之前(认证器一次都没被调到),429 与 401 可分
- 审计 detail 恰好只有 mode 与 peer 两个键,用 set(detail) == {...} 精确断言:
  桶余量能用来反推限流参数,然后贴着阈值发请求
- resolve 的 timing pad 取 5 次中位数,比值须在 [0.5, 2.0]。这条实测抓到过真实
  缺陷:初版"前缀有候选但 key 错"跑两次 verify、"前缀无候选"跑一次,ratio=0.49;
  修的是实现(加 verified_any 标志)不是断言
- AuthContext 的 ContextVar 线程隔离与 reset 保证
- FS 加密:AAD 绑满五维 scope + ref;换 scope 搬密文解不开;明文兼容开着时写
  路径仍然加密

两个既有测试随实现改写:身份改由上下文提供后,每条用例都必须显式声明"谁在发这个
请求"——这正是要的效果,签名上就不给"不指定身份也能调"留位置。原先断言
actor_space 能覆盖 identity 的那条用例被删除,它断言的正是要堵的洞。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
新增 docs/features/security/F01-authentication-kernel.md:认证内核的 11 条决策、
8 条拒绝方案与 13 条已知遗留。速率限制写在同一份而不单开——它唯一的存在目的是
保护认证,且这个可用性风险是引入 Argon2 时一并带进来的,不是一件独立的事。把
"留了个洞"和"补上了"记在一起,比拆成两份让读者去两处对照要诚实。

F04(安全基线)就地加 9 条实现注记,标出主干与文档的偏离。这些不是文档笔误,
是照抄会出问题的地方:ROOT actor 用 Scope(org="*") 会先撞上"跨 org 一律拒绝"
反而寸步难行;compare_digest 传 str 在非 ASCII 输入下抛 TypeError,把 401 变成
500;异步 KeyProvider 在已有事件循环的进程里必炸;信封头实际 11 字节且没有
key_id——后者意味着轮换根密钥会让全部历史密文永久不可解,是个真实缺口。

storage/F02 从"加密 KV"扩为"加密存储",补入 FS 侧的 8 条决策与 13 条断言。两个
装饰器同构,合在一份里读者才看得出"明文兼容开关只在 provider 上"是一条贯穿两侧
的约束,而不是各自的实现选择。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
解决四个预期冲突:
- test_dispatch_management_compat.py: 合并身份上下文与新版list API
- F02-encrypted-storage.md: 合并KV和FS加密特性文档
- S07-common.md: 合并公共层接口与安全特性
- src/storage/AGENTS.md: 合并KV/FS加密装饰器规约

自动合并的关键文件已复核:
- handler.py: list返回MemoryListResult.count,身份从上下文来
- LocalMemoryAPI.list: 授权目标与filters一致,审计count/page_count
- KVSpaceManager: 原始枚举改用scan()

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
应用代码格式化到合并后的文件。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
修复审查报告指出的格式化问题。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: 6a67d275f06c0878f160c667d3370cf2dae0d907

任务名称 结果 日志操作
静态检查 ❌FAILED 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

- G.LOG.02: __main__.py 和 mcp_server 使用 logging.error 替代 print
- G.FMT.08: Protocol 方法定义使用多行格式
- G.FMT.07: test_http_slow_upload.py import 顺序调整(importlib 放到标准库区)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: bad0730d6644c53c1aca5ebef099dc8c5c0a878e

任务名称 结果 日志操作
静态检查 ❌FAILED 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: ac70f3210aec41aac20b7efad789c822c0c827d2

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

Comment thread src/security/authenticator.py Outdated
@@ -0,0 +1,51 @@
"""Authenticator — 认证契约(security.md §2.1 / §2.2)。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

head_sha: ac70f3210aec41aac20b7efad789c822c0c827d2

安全相关的都放在src/common/security/security_impl吧

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: a3743f71e7d94aed43aacc435874f8470b1fcfe1

任务名称 结果 日志操作
静态检查 ❌FAILED 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ❌FAILED 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-sync-bot openjiuwen-sync-bot Bot changed the title [WIP][2/3] feat(memory): 角色感知授权与 Agent 代操作 [2/3] feat(memory): 角色感知授权与 Agent 代操作 Aug 6, 2026
@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: 817bb4b50435b02d30c431bcb501ce840a1f845f

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ❌FAILED 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: 99efc49c0d9823f126277aa9cb7292e12ffafea4

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

HankDUMPLINGZhong and others added 4 commits August 7, 2026 09:51
F01、F02 已迁移到 common/F07、F08

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 迁移 security/F01 → common/F07(认证内核)
- 迁移 security/F02 → common/F08(授权上下文)
- 更新 S09-security.md 标题和关联特性文档路径
- 将 F04/F07/F08 中的 S08 引用统一改为 S09

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 添加术语说明部分,定义「认证与加密期」和「授权与上下文期」
- 更新元信息:添加关联特性文档和规范契约引用
- 更新当前落地状态,详细列出 security 子模块结构
- 更新文档末尾的特性文档引用路径

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: 83726e54ab664a5ebcc5225eb2d0ddcfd0bc81c7

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants