Files
qinglong/docs/adr/ADR-0074-authorized-local-secret-administration-and-atomic-audit.md
T

7.5 KiB
Raw Blame History

ADR-0074:授权的本机 Secret 管理与原子安全审计

  • 状态:Proposed
  • 日期:2026-07-20
  • 关联 RFCQL-RFC-0001 D-05、D-17、D-27、D-37、D-48、D-62、D-65、D-72、D-73
  • 关联 ADRADR-0028、ADR-0029、ADR-0047、ADR-0049、ADR-0050、ADR-0063、ADR-0073

上下文

ADR-0073 已让全新本机 application 具备可达的加密 SecretStore,但只提供 envelope、keyring 和运行期解析能力。若直接把 plaintext 写入口放进常驻 application、数据库迁移 authority 或 legacy Controller,就会同时扩大 HTTP 漏洞、DDL 凭据和 Secret 明文的 blast radius;若只在 service 层先查权限、再单独写 envelope 和日志,RoleBinding 撤销及审计失败又会留下 TOCTOU 或“已写密文但没有授权事实”的崩溃窗口。

本机默认 Project 仍是 ownerless。迁移或首次启动自动授予 owner 虽然方便,却会绕过 D-27 的本机强认证 ceremony。目标用户还包括低性能路由设备,因此 Secret 管理不能增加常驻连接、timer、watcher、sidecar 或明文 cache。

决策

1. Secret 管理使用独立、短生命周期 authority

新增 @qinglong/local-secret-admin,生产只依赖 @qinglong/local-secret@qinglong/runtime-core。它不得进入 @qinglong/local-application、edge/standalone application tarball 或任何常驻 Profile 组合根;依赖审计对所有其他 3.0 package 的反向导入 fail closed。

local-admin 继续只负责 SQLite migration/adoption,不能同时取得 Secret plaintext 管理 authority。数据库结构变更与业务密钥管理分离,避免一个运维入口同时拥有 DDL、keyring 和密文写入能力。

2. SQLite capability v5 提供最小 Policy 与审计事实

0009-local-project-policy-audit 新增:

  • ownerless 的 QingLong3Projects 默认 Project
  • append-only、versioned 的 QingLong3ProjectRoleBindings
  • 低敏 QingLong3SecurityAuditEvents

0010-capability-v5 声明 local_project_policylocal_security_auditlocal_secret_authorized_mutation。migration、typed schema、manifest、readiness 与真实 catalog 必须 lockstep;默认 migration 不创建 owner,也不复用 legacy Sequelize 的 0017/0018 bootstrap 表。

3. 认证和 Policy 必须先于 keyring/Secret 访问

管理请求只接受 exact-shape、UUIDv4 mutation/request identity、Project-bound Secret name、expected version、plaintext 和 AuthenticatedPrincipal。User 必须具备 multi_factorhardwarelocal_console assurancesystem/service 仍须是稳定 subject。弱认证先写 authentication_rejected 审计,且不得读取 keyring、查询 Secret 或执行密码学操作。

强认证主体经 ProjectPolicyEngine 检查 secret.manage。owner/admin 可允许,ownerless、operator/viewer、archived、损坏或依赖不可用均 fail closed。拒绝、需要审批和依赖不可用使用低敏审计,不记录 plaintext、密文、key material 或可还原值。

4. 最终授权、envelope 与 allowed audit 在一个事务裁决

service 层的 Policy 结果不是最终写权限。repository 在同一个 BEGIN IMMEDIATE transaction 中重新验证精确 Project version 与 RoleBinding subject/version/state/role fence,然后验证 Secret current version,最后同时追加 encrypted envelope 和 allowed 安全审计。

RoleBinding 在 Policy 判断后被撤销时,旧请求必须得到 LocalSecretAuthorizationFenceConflictError,不能写 envelope 或 allowed audit。audit insert 失败时整个 envelope mutation 回滚;不得以 best-effort 日志替代原子事实。实现复用唯一 LocalSqliteRunRepository 的 DatabaseSync、256 operation 队列和 close fence,不创建第二 SQLite authority。

5. 管理结果不回显明文

成功只返回 canonical SecretRef、version 和 created|existing。mutation replay 必须解密既有 envelope 后做 timing-safe 语义比较:同一 plaintext 返回 existing,不同 plaintext 作为 mutation identity collision 失败;任何响应、错误和审计都不返回输入 plaintext。

同一 mutation identity 一旦用于 authentication/policy 拒绝,不得随后被复用为 allowed mutation;调用方必须生成新的 mutation,以保留每次安全决策的唯一审计身份。

6. 首 owner 与产品入口继续保持不可达

当前 package 是可测试的领域/存储核心,不是可发布管理入口。首次 owner bootstrap 必须由后续本机控制台 ceremony 使用新的 Node 24 SQLite authority 原子建立,不能自动授予、复用默认密码或把 legacy session 直接当强认证。

CLI/HTTP/UI、独立速率限制、Secret 创建/轮换审批、keyring provision/rotation 编排、备份/rekey/retirement 和恢复流程完成前,默认部署不得暴露 Secret mutation。

被否决的替代方案

  1. 把 Secret 写入口放入常驻 local-application:扩大长期 plaintext 与远程攻击面,拒绝。
  2. 把 Secret 管理并入 migration local-admin:让 DDL authority 同时持有 keyring 和业务 mutation,拒绝。
  3. 只在 service 层检查权限:无法关闭撤权与写入之间的 TOCTOU,拒绝。
  4. 先写 envelope、再 best-effort audit:崩溃或审计故障会产生无授权事实的密文,拒绝。
  5. migration 自动建立默认 owner:绕过首 owner 强认证 ceremony,拒绝。
  6. 为管理请求增加专属连接、队列或 watcher:给 edge 增加常驻成本并产生第二 SQLite authority,拒绝。

影响与未完成项

已完成:

  • runtime-core 的本机 Secret 管理 repository/fence contract
  • Node 24 SQLite v5 migration/schema/readiness、ownerless Project、RoleBinding 与安全审计;
  • 强 Principal、secret.manage Policy、拒绝先审计且 key-access-after-allow
  • Project/RoleBinding fence、Secret version、envelope 和 allowed audit 的单事务提交;
  • 撤权竞态、审计回滚、语义 replay 与不回显测试;
  • 二十二个 3.0 importer 的依赖/source/lock/advisory 注册,管理包不进入 application 产物。

仍未完成:

  • Node 24 SQLite 首 owner bootstrap、可信 local-console issuer 与 production authentication wiring
  • 不回显 CLI/HTTP/UI、独立 rate limit、审批与 break-glass 流程;
  • Project/RoleBinding 正式管理入口、审计 query/retention/export/alert
  • 数据库/keyring 配对备份、历史 envelope rekey、key retirement proof 和 crash-resume journal
  • secret.use 对 Task/Workflow/Agent 的完整 Policy/Approval 装配与已知值日志治理;
  • PostgreSQL/KMS/Vault 管理 authority、Remote Worker 临时 Secret delivery 与多副本契约。

因此本 ADR 只关闭本机 Secret mutation 的授权、撤权竞态和原子审计断层;它不使 ownerless 默认部署获得管理能力,也不表示 QingLong 3.0 Secret 产品链已完成。

验证

  1. owner 可以在一个事务中写 encrypted envelope 和 allowed audit,原始 row/响应均无 plaintext。
  2. ownerless Project 被拒绝并审计,且 key provider 未被访问。
  3. 弱认证被审计,Policy、Secret repository 与 key provider 均未被访问。
  4. Policy 判断后撤销 RoleBinding 会触发 fence conflictenvelope/audit 均不写入。
  5. 强制 audit insert 失败会回滚 envelope。
  6. 同 mutation/same plaintext 返回 existing,不同 plaintext 冲突。
  7. capability v5 的十条 migration、十四张 owned table、schema/readiness/manifest 与真实 catalog 一致。
  8. application tarball 仍为十二个 package,且不包含 @qinglong/local-secret-admin