Files
qinglong/docs/adr/ADR-0142-authenticated-plugin-package-management-facade.md

6.4 KiB
Raw Permalink Blame History

ADR-0142:认证后 Plugin Package 管理 Facade 与 Profile ceremony

  • 状态:Acceptedtransport-neutral 管理 facade、SQLite 真实端到端闭环与 local/cluster Profile 组合已实现;本机 CLI 由 ADR-0143 完成,Cluster transport 边界由 ADR-0144 冻结,identity/keyset 与 HTTP process 由 ADR-0145 完成; durable quota 由 ADR-0146 完成,ADR-0149 已完成原子 resource generation identity/source;真实双 User/UI 与资源语义 materializer 待完成)
  • 日期:2026-07-25
  • 关联 RFCQL-RFC-0001 D-05、D-08、D-09、D-85、D-130 至 D-140

上下文

ADR-0141 已完成 immutable proposal、durable Approval、execution/start barrier、 Package 原子 admission 和调用方驱动 dispatcher,但这些能力仍是彼此独立的显式 authority。若 HTTP、CLI、UI 或自动化入口自行拼接这些 repository,很容易出现:

  1. 在解析完整 Package action 前查询 Policy,或绕过 package.manage
  2. 由 transport 提交 Project/RoleBinding fence,而不是读取当前 Policy snapshot
  3. local 与 cluster ceremony 漂移为“全部允许自批”或“全部强制四眼”;
  4. consumption 复用用户输入的 consumer identity
  5. proposal、request、decision、consume 和 dispatch 各自生成不稳定幂等身份;
  6. 为每种 transport 或 Profile 新建 workspace package。

公开 transport 现在还不能直接开放,但必须先建立唯一的 use-case 组合边界,后续 adapter 才不会再次复制安全协议。

决策

1. 共享 use-case 留在 runtime-core 显式子路径

新增 @qinglong/runtime-core/plugin-package-management,不新增 workspace package、 第三方依赖、timer、watcher、socket 或数据库连接。Facade 只接受已经认证且仍 active 的 SecurityPrincipal,并固定提供:

  • propose:规范化完整 install action,执行 package.manage Policy,使用返回的 fence 创建 immutable proposal,再创建 digest-bound ApprovalRequest
  • decide:重新读取 request,以当前 principal 对 approval.decide 执行 Policy 再提交强认证 decision
  • consume:只使用构造时注入的 system consumer authority,重新读取 requester 的 package.manage Policy fence,再原子生成 dispatch/execution baseline
  • inspect:只读取 proposal 与 request durable fact
  • dispatch:调用既有 bounded dispatcher,不安装后台循环。

Facade 不接收调用方提供的 Policy fence、consumer subject、action digest 或 preview digest;这些事实必须分别来自 Policy engine、固定 composition 和 canonical proposal。

2. 幂等身份由请求显式携带

写操作必须携带稳定的 action/request/decision/consumption/dispatch/audit identity 以及对应发生时间。相同 identity 与相同语义可 exact replay;不同内容复用 actionRef 或 approvalRequestId 必须冲突。Facade 不在响应丢失后静默生成新 identity。

默认 Approval lifetime 为 15 分钟,可由受信 composition 缩短或在领域允许的 24 小时 上限内调整。已超出 lifetime 的新 propose 调用在任何 mutation 前拒绝。

3. Profile 固定 ceremony,不让 transport 选择

  • @qinglong/local-admin/package-management 固定 human_confirmation,复用唯一 LocalSqliteOperationAuthorityedge/standalone dispatcher 默认批量仍为 1/4
  • @qinglong/cluster-admin/plugin-package-management 固定 separation_of_duty,使用 admin-only PostgreSQL repositorydispatcher 默认批量 仍为 16
  • 两个入口都不从 package root、常驻 runtime、cluster-control 或 worker 导出。

local 新增 @qinglong/local-sqlite/project-policy 窄 adaptercluster 只给现有 PostgresProjectPolicyRepository 增加显式 project-policy export。没有新增表、 migration、连接或 importer。

4. 公开 transport 继续失败关闭

本 ADR 的“认证后”表示 facade 不接受匿名/过期 principal,并不表示 bearer token、 本机 credential file、MFA/hardware assertion 或 HTTP session 已在这里完成验证。 真实 transport adapter 必须在调用 facade 前完成:

  • bounded request/body/command-file 解析;
  • credential 或本机 console proof
  • rate limit、取消和 response mapping
  • secret 不进入 argv/stdout/audit
  • transport response-loss 的 idempotency key 保留。

因此当前不能把内部 subpath 注册为 2.x Controller route,也不能宣称 UI 或 cluster admin transport 已生产开放。本机私有 command-file CLI 由 ADR-0143 完成; ADR-0145 提供的 cluster HTTP process 和 Kubernetes operation 仍默认关闭,生产 ingress 继续受 keyset anti-rollback、真实双 User 与 live ingress 门约束。

影响

  • Package 管理 use-case 不再由每种 transport 自行拼 repository
  • workspace importer 仍为 21runtime-core 只增加一个纯协调 source
  • edge 禁用 Package 时不会加载 facade 或任何 Package storage
  • cluster-control/runtime/worker 仍无 proposal、decision、consume 或 admission 写权限;
  • ADR-0143 已在同一 facade 上实现短生命周期本机 CLI;独立 cluster admin API 已由 ADR-0144 冻结双 authority 边界,仍无需改变领域和 Package 数据库协议。

验证

  1. runtime-core 250/250,其中新增四眼审批、operator mutation-before-deny 与 authorization-before-quota 门禁;
  2. local-admin 54/54,其中真实 Node 24 SQLite 流程覆盖 propose → self-confirm → consume → dispatch → queued admission
  3. 弱认证 decision 与过期 propose 在 mutation 前失败,失败 decision 不产生 Audit
  4. 完整流程产生 proposal/request/decision/consume/admit 五类 durable Audit
  5. cluster-admin 63 pass/1 条件 skip,构造不打开 PostgreSQL且 ceremony 常量固定为 separation_of_duty
  6. 26 项 source-boundary test 与 cluster dependency audit findings: []compatible: true
  7. importer 仍为 21;新增能力均为既有 package 的显式 subpath。

后续门禁

  • 为 keyset generation/revocation 增加跨全副本重启的 durable anti-rollback
  • response-loss 下相同 transport idempotency key 的完整端到端重放;
  • PostgreSQL 真库 separation-of-duty/concurrent decision/consume
  • ADR-0149 已完成 generation publisher/source;继续实现 Task/Workflow/Prompt/Tool 语义 materializer
  • UI 只消费低敏 preview/status,不持有数据库或 dispatcher authority。