6.4 KiB
ADR-0142:认证后 Plugin Package 管理 Facade 与 Profile ceremony
- 状态:Accepted(transport-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
- 关联 RFC:QL-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,很容易出现:
- 在解析完整 Package action 前查询 Policy,或绕过
package.manage; - 由 transport 提交 Project/RoleBinding fence,而不是读取当前 Policy snapshot;
- local 与 cluster ceremony 漂移为“全部允许自批”或“全部强制四眼”;
- consumption 复用用户输入的 consumer identity;
- proposal、request、decision、consume 和 dispatch 各自生成不稳定幂等身份;
- 为每种 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.managePolicy,使用返回的 fence 创建 immutable proposal,再创建 digest-bound ApprovalRequest;decide:重新读取 request,以当前 principal 对approval.decide执行 Policy, 再提交强认证 decision;consume:只使用构造时注入的 system consumer authority,重新读取 requester 的package.managePolicy 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,复用唯一LocalSqliteOperationAuthority,edge/standalone dispatcher 默认批量仍为 1/4;@qinglong/cluster-admin/plugin-package-management固定separation_of_duty,使用 admin-only PostgreSQL repository,dispatcher 默认批量 仍为 16;- 两个入口都不从 package root、常驻 runtime、cluster-control 或 worker 导出。
local 新增 @qinglong/local-sqlite/project-policy 窄 adapter,cluster 只给现有
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 仍为 21,runtime-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 数据库协议。
验证
- runtime-core 250/250,其中新增四眼审批、operator mutation-before-deny 与 authorization-before-quota 门禁;
- local-admin 54/54,其中真实 Node 24 SQLite 流程覆盖
propose → self-confirm → consume → dispatch → queued admission; - 弱认证 decision 与过期 propose 在 mutation 前失败,失败 decision 不产生 Audit;
- 完整流程产生 proposal/request/decision/consume/admit 五类 durable Audit;
- cluster-admin 63 pass/1 条件 skip,构造不打开 PostgreSQL且 ceremony 常量固定为
separation_of_duty; - 26 项 source-boundary test 与 cluster dependency audit
findings: []、compatible: true; - 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。