Files
qinglong/docs/adr/ADR-0493-target-native-reconciliation-domain-preservation.md
T

5.3 KiB
Raw Blame History

ADR-0493:目标原生 Reconciliation 域分类与身份保留

  • 状态:Accepted
  • 日期:2026-08-24
  • 决策:D-398
  • 关联:ADR-0483、ADR-0484、ADR-0485、ADR-0488、ADR-0492

背景

Reconciliation 必须同时处理两类不同事实:从 2.x 迁入的数据,以及已经属于 QingLong 3.0 目标库的原生数据。此前实现把 identity_policy_audit 整域无条件标为 manual_required/identity_custody_required,因此即使 Legacy 完全没有 Auths/Usersfresh v52 目标库自带的 Project、RoleBinding、Credential、Pepper、SecurityAudit 与 LocalOwner 表也会阻止全局 completion。

同一盘点还发现 fresh v52 的六张已知表没有进入稳定领域,被误归为 unknown

  • AutomationQingLong3LegacyAdoptionsQingLong3LegacyAdoptionTasksQingLong3LocalExecutionContextRecipesQingLong3LocalTaskExecutionRevisions
  • Run HistoryQingLong3RunAttemptLogArtifactTombstonesQingLong3RunAttemptLogRetentionState

这不是缺少新 adapter,而是现有 planner 对目标原生 schema 的知识不完整。为绕过门禁而伪造 completion receipt 或把整个 QingLong3* 前缀视为可信都会破坏 fail-closed 边界。

决策

1. 已知目标表使用精确领域目录

上述六张表按精确表名分别归入 Automation 与 Run History。Schema object 继续按其 tableName 继承同一领域,因此相关 index/trigger 不需要单独的宽泛名称规则。

不引入 QingLong3*LegacyAdoption*Local* 的整体通配。未来新增但尚未登记的目标表仍进入 unknown,不读取行数,并要求人工外部处理。

2. 目标原生身份是保留事实,不是迁移事实

identity_policy_audit 的 disposition 改为按来源判定:

  • Legacy 存在 Auths/Users 时继续 manual_required
  • Legacy 没有身份事实、Target 有已知身份事实时为 target_only
  • 两端都没有时为 aligned

Target 身份诊断是 required/reviewable_fact,必须在 signed review 中逐事实选择 retain_target 才能形成 no_effect application action。它不能选择 adopt_legacyexclude_legacy。Legacy 身份诊断仍是 blocked/identity_custody_required,只允许 defer|manual_external,本 ADR 不声明 2.x credential、session、password hash、token、Policy 或 Audit 已迁移。

3. Completion 只消费既有闭合证据

本 ADR 不增加 completion schema、adapter、instance state 或绕过规则。目标原生身份经过 canonical diagnostics、signed decision 和 application summary 后,以既有 no_effect/application_summary 进入 completion;真正未知表和任何 Legacy 身份事实仍阻止 completion。

完整 v52 + Legacy Secret/Config fixture 必须通过真实 v3 completion,而不是测试直接构造 receipt、推进 head 或调用 storage collector。只有 completed head durable 后,Secret/Config backup 才能由既有流程回收。

4. 部署与资源边界不变

实现只修改既有 Local Owner 一次性 reconciliation planner/reviewer,没有新增 workspace package、production dependency、SQL migration、daemon、listener、timer、Pool、容器或 Kubernetes workload。Edge/Standalone 常驻闭包、SQLite cache 上限和 artifact 预算不变;Cluster 仍使用自己的 PostgreSQL、Secret provider 与 HA authority。

被拒绝的替代方案

为目标原生身份增加 migration adapter

拒绝。没有 Legacy 身份输入时不存在要迁移的数据;额外 adapter 只会复制已经由目标数据库拥有的事实并扩大权限面。

信任全部 QingLong3 前缀

拒绝。名称前缀不是 schema ownership 证明,会让未来未知表自动越过人工审查。

自动跳过目标身份评审

拒绝。target_only 仍必须形成逐事实 signed retain_target 决策,不能仅凭分类器直接授权 completion。

放行 Legacy Auths/Users

拒绝。旧身份材料的 custody、hash/token 兼容、撤销、Policy 与 Audit 语义尚未建立独立 adapter;本 ADR 只消除目标原生数据被误当成迁移输入的问题。

验证

  • 定向回归 4/4fresh v52 unknown=0、目标身份 retain_target、Legacy 身份继续 blocked、真正未知表继续 row-free/manual
  • Secret/Config completion v3 使用真实 complete → replay → verify 链路,首调 completed、重放 existingreceipt 为 v3 且 Identity/Unknown 均为 no_effect
  • completed head durable 后 Secret/Config backup 被回收,加密 material 与 receipt 保持只读;
  • Local Owner 受限沙箱为 301 total / 291 pass / 7 conditional skip / 3 loopback EPERM,两个 loopback 文件在沙箱外 15/15,有效结果 301/294/7/0
  • 完整 backend 为 1567 total / 1565 pass / 2 conditional skip / 0 fail18-package clean build 与逐包顺序测试除 Worker 三条 sandbox loopback 外全部通过,对应 Worker 文件在沙箱外 8/8
  • package boundary、精确 Cluster dependency、122-module Edge import、service-manager bridge import、本地镜像与 14/14 Local artifact audit 全部 compatibleworkspace 保持 18 packagessingleSourcePackages=[]shallowSourcePackages=[]
  • 基础 Edge/Standalone 保持 2,635,529 / 2,635,607 bytes、323 files、58 loaded modules,没有 Cluster/PostgreSQL 闭包。