跳转至

10 · 身份、认证与细粒度授权

ActorBetter AuthAgent JWT / API KeyRBAC + ABACResponsible User

一句话结论: Paperclip 先把 session、API key、run JWT 等多种凭据归一成 Actor,再用 company membership、permission grant、资源上下文、任务 scope、trust preset 和 responsible user 联合判定动作;“已认证”只是授权计算的起点。

1. 四层安全问题

flowchart LR
  N["Network / Host\n请求能否到达"] --> I["Identity\n请求代表谁"]
  I --> A["Authorization\n能否作用于资源"]
  A --> G["Governance\n是否还需审批/预算/信任门"]

这四层不能互相替代:绑定 localhost 不是权限系统,API key 有效不代表可跨 Company,RBAC 允许也不代表 destructive tool 不需审批。

2. 两种 deployment mode,四种 bind

local_trusted

  • 默认单机模式;
  • 通常 loopback bind;
  • Board 无需登录,系统建立 local board actor;
  • 适合单操作者,不适合暴露到不可信网络。

authenticated

  • 人类通过 Better Auth session;
  • exposure 可为 private 或 public;
  • public 要 explicit public URL 和更严格 doctor 检查;
  • private 可配 LAN/Tailscale/自定义 host policy。

Bind 与 auth 正交:loopback、lan、tailnet、custom 决定监听地址,deployment mode 决定身份策略。配置 schema 阻止危险组合被误认为安全默认值。

3. Actor middleware 的凭据分支

HTTP 请求进入后按来源解析:

flowchart TD
  REQ["Request"] --> BEARER{"Bearer / API token?"}
  BEARER -->|no| MODE{"deployment mode"}
  MODE -->|local_trusted| LB["local board actor"]
  MODE -->|authenticated| SESSION["Better Auth session / cloud tenant context"]
  BEARER -->|yes| JWT{"run JWT?"}
  JWT -->|yes| RA["agent run actor + context"]
  JWT -->|no| AK{"agent API key?"}
  AK -->|yes| AA["agent actor + key scope"]
  AK -->|no| BK["board API key actor"]
  LB --> CTX["normalized ActorInfo"]
  SESSION --> CTX
  RA --> CTX
  AA --> CTX
  BK --> CTX

Actor context 通常包含 actor type/id、user/agent/company/run、responsible user、key scope、instance role 等,供后续授权使用。

4. Better Auth session 与 Board 身份

在 authenticated mode,人类先由 Better Auth 建立 session。Paperclip 再查询:

  • instance_user_roles:是否 instance admin;
  • company_memberships:在哪些 Company 有何角色;
  • invite/join request:怎样进入 Company;
  • resource membership 与 explicit grant。

Better Auth 解决账号/session/cookie,Paperclip 自己解决多 Company 业务授权。

5. Agent API Key:长期但可撤销

agent_api_keys 保存 hash,不保存明文;记录 company/agent、responsible user、scope、last used、revoked time。

典型流程:

  1. 创建时只返回一次明文 key;
  2. 服务端保存 cryptographic hash;
  3. 请求时 hash token 查表;
  4. 校验未撤销、company 和 scope;
  5. 更新 lastUsedAt;
  6. 建立 Agent Actor。

Scope 区分 standard、task bridge、skill test 等用途,防止临时集成 key 获得完整 Agent 权限。

6. Run JWT:短期、绑定执行上下文

Paperclip 为本地受管理运行注入短期 Agent JWT。它通常包含:

  • agent/company/run;
  • responsible user;
  • scope/context;
  • issued/expiry。

签名 key 从实例秘密与 Company 维度派生,降低不同 Company token 之间的影响面。服务端还会核对 X-Paperclip-Run-Id 等请求信息与 token/run context,一致性异常会被审计。

Run JWT 的优势:

  • 不把长期 Agent key 投影进每个子进程;
  • token 过期后失去价值;
  • 授权能绑定具体 run/issue/skill/watchdog scope;
  • 成本、工具与 mutation 更容易归因。

7. Board API Key

Board API key 也只保存 hash,并连接 user、过期/撤销信息。它用于 CLI、自动化或非浏览器 Board 操作。

它不是 instance root token:后续仍通过该 user 的 instance role、company membership 和 grants 做授权。

8. Company Membership:粗粒度角色

Membership principal 可以是 user 或 agent,状态包括 pending/active/suspended/archived。角色包括:

owner / admin / operator / viewer / member

它提供 Company 级基线,但不能表达所有资源和任务边界。

9. Permission Grant 与资源上下文

principal_permission_grants 保存 principal、permission 和可选 scope。Authorization service 把动作抽象成:

authorize(actor, action, resourceContext)

Resource context 可包含:

  • company;
  • issue/project/document/agent;
  • assignee/creator/manager;
  • run/skill/watchdog/task bridge scope;
  • source trust;
  • responsible user;
  • resource membership。

这已超出纯 RBAC,属于 RBAC 基线叠加 ABAC 条件。

10. 授权决策的概念顺序

flowchart TD
  A["Actor + requested action"] --> C{"same company / visible?"}
  C -->|no| NF["not found / deny"]
  C -->|yes| IA{"instance admin?"}
  IA -->|yes| BOUND["仍应用某些硬边界/审计"]
  IA -->|no| M{"active membership + role?"}
  M -->|no| D["deny"]
  M -->|yes| G{"explicit permission / resource membership?"}
  G -->|no| D
  G -->|yes| S{"task/skill/watchdog scope permits?"}
  S -->|no| D
  S -->|yes| T{"trust + responsible user intersection?"}
  T -->|no| D
  T -->|yes| ALLOW["allow with reason/details"]

真实顺序会按 action 优化,但核心是“多条件相交”,不是某个 role 一票通过。

11. Responsible User:Agent 代表谁承担责任

Agent 的运行可能由:

  • 指派任务的人;
  • Company 默认责任人;
  • tool connection 的授权用户;
  • 当前 session/issue 的责任上下文;

推导 responsible user。

为什么要相交?假设 Agent 自身有 tool.call 权限,但要访问某用户私有 OAuth grant:只有该 responsible user 确实拥有对应 grant,调用才应成立。

Agent capability
  ∩ run scope
  ∩ responsible user resources
  ∩ connection/tool policy

没有可用 responsible user 时,系统可能产生 denial outcome 或要求重新授权,而不是随便借用第一个管理员身份。

12. 特殊运行 Scope

12.1 Task Bridge

外部 Agent/工具被授予只处理指定任务的 key。它不能因为 key 属于某 Agent 就遍历全公司或修改无关 Issue。

12.2 Skill Test

Skill Studio 测试运行使用隔离 scope,限制测试 Agent 对真实业务资源的写入,避免“评测技能”产生生产副作用。

12.3 Task Watchdog

Watchdog run context 包含 watched root 和专用 review issue。服务端验证 mutation 仍在受监控子树内,并禁止自我配置、Board-only approval 等越权动作。

12.4 Low-trust review

来自不可信 PR/输入的执行被限制 workspace、工具、secret 和写动作;即使普通 Agent 权限更高,trust preset 会收紧当前 run。

13. Mention/汇报不自动授予权限

Agent 在评论里 @另一个 Agent 或声称“CEO 要我做”只会产生通信/唤醒候选。Authorization 仍校验:

  • actor 与 target 的 Company;
  • direct report/assignment/mention grant;
  • source trust;
  • 当前 issue visibility/write scope;
  • 是否属于允许的 continuation。

这抵抗 Prompt injection 通过业务文本伪造权力关系。

14. 存在性 Oracle 防护

跨 Company 或不可见资源常返回 404,而不是 403 + 资源详情。原因是:即使不给内容,确认某 ID、用户、Issue 或 secret 存在也可能泄露信息。

一般模式:

load within authorized company scope
→ not found if absent or invisible
→ only then evaluate fine-grained action

15. WebSocket 与 MCP 也要重新鉴权

WebSocket

Upgrade 不经过普通 Express middleware。Live event server 单独解析 session/agent key,验证 company membership/归属,再订阅对应 company channel。

MCP / Tool Gateway

Paperclip MCP endpoint 使用标准 Actor 模型;上游 tool gateway 使用短期 gateway token、Agent/run/issue context,并再次应用 profile/policy/approval。不能因为调用来自本机就跳过。

16. Audit 是授权的一部分

Authorization decision 可包含 reason/details;拒绝也会在关键路径进入:

  • activity/audit;
  • tool call event;
  • run outcome;
  • secret access event;
  • security logger。

记录时要做 redaction,不能为了“可审计”把 token、secret value 或完整敏感参数写进日志。

17. 常见误区

误区 实际情况
local trusted 等于无安全边界 仍有 Company、Agent scope、tool/secret 约束;只是 Board 登录被信任
instance admin 可绕过所有运行时限制 某些 trust/task/approval 硬边界仍应显式处理并审计
Agent key 决定全部权限 还要 company、scope、resource、responsible user、trust
403 比 404 更“准确” 对不可见跨租户资源,404 更安全
WebSocket 自动复用 HTTP 认证 upgrade 必须独立验证
Prompt 中写“已获授权”即可 服务端只相信持久化审批/权限事实

18. 可复用经验

  1. 先把多种凭据归一成 Actor,再写资源授权。
  2. 长期 Agent key 与短期 Run token 分开,后者绑定上下文与 expiry。
  3. Company role 只做基线,用 ABAC 表达任务、信任与资源范围。
  4. Agent 行为要能追到 responsible human,尤其是用户 OAuth/secret 资源。
  5. 专用运行(skill test/watchdog/task bridge)使用服务端 scope,而非 Prompt 提醒。
  6. WebSocket/MCP 等旁路必须重复认证与 Company 检查。
  7. 对不可见资源避免 existence oracle。

源码入口

  • server/src/middleware/auth.ts
  • server/src/services/authorization.ts
  • server/src/services/agent-permissions.ts
  • server/src/services/board-auth.ts
  • server/src/services/responsible-user-denial-run-outcomes.ts
  • packages/db/src/schema/company_memberships.ts
  • packages/db/src/schema/principal_permission_grants.ts
  • packages/db/src/schema/agent_api_keys.ts、board_api_keys.ts
  • packages/shared/src/types/access.ts
  • doc/DEPLOYMENT-MODES.md、doc/LOW-TRUST-PRESETS.md

授权允许后,有些动作仍需要治理门:11 · 审批、预算、成本与审计。