Files
qinglong/docs/adr/ADR-0323-local-sqlite-adoption-domain-ownership.md
T

8.1 KiB
Raw Blame History

ADR-0323Local SQLite Adoption 领域归属

  • 状态:Accepted
  • 日期:2026-08-10
  • 关联 RFCQL-RFC-0001 D-05、D-06、D-17、D-64、D-87、D-257
  • 关联 ADRADR-0064、ADR-0095、ADR-0312、ADR-0321、ADR-0322

背景

ADR-0321/0322 已区分 workspace package 与 package-private modulepackage 表达部署、authority、依赖、adapter、 multi-consumer 或供应链边界,包内领域目录表达共同变化的 ownership。继续审计 @qinglong/local-admin 时发现, legacy-adoption/localSqliteAdoption.ts 以 1,940 行同时拥有:

  1. Legacy SQLite read-only 打开、catalog 证据与 crontab inventory/diagnostic
  2. reviewed decision receipt、authorization file、issuer 与 publisher bridge
  3. migration staging、backup、manifest 与 snapshot verification
  4. SQLite source BEGIN IMMEDIATE write fence
  5. activation document、prepare 与 acquire。

这不是“包太细”,而是同一 Local Admin 运行单元内的五类 ownership 被平铺在一个文件中。把这些职责各自发布成 workspace package 会制造部署和依赖噪声;继续维持单文件则会让 inspection、review、staging 与 activation 的安全边界 难以独立评审。

编辑前已对原文件内全部 49 个 function、class 和 method 执行 GitNexus upstream impact。稳定错误 LocalSqliteAdoptionError 为 CRITICAL35 direct/55 total/0 flows);共享 path/file/hash helper 与 inspectLegacySqlitePath 主要为 MEDIUM,其余多数为 LOW。CRITICAL 风险已先告警,本轮只移动实现归属和维持同一 export identity,不改变 SQLite、文件系统或 adoption 协议。

决策

保持一个 @qinglong/local-admin package、一个既有 public subpath 和 66 行稳定 facade,在 legacy-adoption/local-sqlite-adoption/ 下形成以下 package-private ownership

localSqliteAdoption.ts                   # stable public facade
local-sqlite-adoption/
├── contracts.ts                        # schemas, types and stable error identity
├── filesystem.ts                       # path, file identity, hashing and atomic private writes
├── inspection.ts                       # legacy catalog and task inventory
├── staging.ts                          # backup, migration, manifest and verification
├── sourceFence.ts                      # shared SQLite source write fence
├── review.ts                           # reviewed receipt/authorization/publication bridge
└── activation.ts                       # activation prepare and acquire

内部依赖保持有向无环。contracts.ts 不取得文件系统或 SQLite authorityfilesystem.ts 只拥有通用的严格文件证据; inspection.ts 保持 legacy adoption module 的 lazy loadstaging.ts 唯一拥有备份、migration 与 manifest sourceFence.ts 是 review 和 activation 共同依赖的安全 primitive,单独放置以避免二者形成循环;review.ts 保持 reviewed authorization/publisher bridge 的 lazy loadactivation.ts 唯一拥有 activation 生命周期。

原 facade 只显式 re-export 既有公共类型和 13 个 runtime object。所有 runtime export 与 owner module 保持同一个 class/function identityinstanceof、错误 code/message、package export 与调用路径不变;package-private FileIdentity、hash、atomic write 和 fence helper 不扩展为公共 API。没有新增 public subpath、workspace package、 dependency 或部署单元。

本轮不修改:SQLite read-only inspection、catalog/schema evidence、任务分类、decision receipt/authorization、source file identity、hash、backup、migration、manifest、原子写入、no-follow/realpath fence、BEGIN IMMEDIATE、snapshot verification、activation fence、错误映射或返回结构。

包与目录粒度规则

packages/*/src 不应长期用大量无领域归属的平铺实现文件承载系统,但修复方式也不是“一目录一 package”。后续统一采用:

  1. 只有独立 deployable、authority、dependency、adapter、multi-consumer 或供应链边界才能新建 workspace package
  2. 同一 package 内按业务领域和共同变化原因建立私有目录,根 src 只保留受审 public facade、composition root 或 bin
  3. 一个领域允许多个内聚文件,也允许一个纯 schema/codec 文件较大;不按 LOC、函数数或单文件 package 机械拆合;
  4. 共享 helper 只有在具有稳定语义和两个以上真实 owner 时才提取,禁止建立 utils/ 杂物层;
  5. 拆分必须保持依赖 DAG、公共 export identity、Profile closure、制品预算与部署拓扑。

小设备与集群影响

本轮只影响包含 Local Admin adoption 能力的六档制品,分别增加 10,417 bytes/7 physical files,实际 loaded module 数 不变:Adopted 为 50、Application 为 116、Application AI 为 115。最小 Edge/Standalone 和基础 AI Profile 不包含 Local Admin,因此低配路由设备不会因为包内目录化增加其安装闭包或常驻模块。

六档 pack/install/import/RSS 门全部 compatible;本机 RSS 样本保持在现有 Profile 门限内。物理文件增加用于源码和 制品 ownership,不等于增加进程、线程、listener、timer、数据库连接或服务发现。

Cluster 继续通过原 Local Admin/Runtime contract 组合集群能力;本轮没有 SQL、migration、PostgreSQL、Cluster runtime、Kubernetes resource 或部署拓扑变化,因此不重复 PostgreSQL HA Docker 门。

被否决方案

  1. 七个 owner 各建 workspace package:不存在七个独立部署或消费者闭包,拒绝。
  2. 维持 1,940 行平铺文件inspection、review、staging、fence 与 activation 无法独立评审,拒绝。
  3. 每个 function 一个文件:破坏同一协议的内聚性并增加导航成本,拒绝。
  4. 把所有 helper 放进 utils.ts:隐藏 file identity 与安全 fence 的真实 ownership,拒绝。
  5. 把 source fence 归 review 或 activation:另一侧会反向依赖并可能形成循环,拒绝。
  6. 趁拆分重写 adoption 协议CRITICAL blast radius 下无法区分 ownership 回归与语义回归,拒绝。

验收证据

  • facade 1,940→66 行;contracts 229、filesystem 172、inspection 290、review 446、staging 504、sourceFence 117、 activation 311 行。
  • facade 与 owner 的 13 个 runtime export identity 全部相同;Local Admin 91/91。
  • 完整 16-package clean topology build/test 在允许 loopback TLS 与 crash 子进程的门环境退出 0。
  • package boundary 为 16 package、830 source、25 root、805 nestedsingleSourcePackages=[]shallowSourcePackages=[]、findings 为空;Local Admin 为 43 source、1 root/42 nested。Edge import、Cluster dependency 与 Cluster deployment 全部 compatible。
  • Adopted Edge/Standalone 为 4,265,052/4,265,112 bytes、394 files、50 loaded modulesApplication 为 4,762,901/4,763,021 bytes、453 files、116 modulesApplication AI 为 6,158,278/6,158,410 bytes、532 files、 115 modules。相对 ADR-0322 各增加 10,417 bytes/7 filesloaded module 数不变,六档均 compatible。
  • 最终强制索引为 44,038 nodes/100,277 edges/1,729 clusters/274 flows。post-impact 中稳定错误保持 CRITICAL 40 direct/54 total/0 flows),sha256Text 与 inspection 保持 MEDIUM7/24、8/13),source fence 为 LOW 3/3),staging/review/activation 代表 coordinator 为 LOW0/0);高风险调用关系没有因 facade re-export 被隐藏。
  • detect_changes all/compare develop 仍只映射已跟踪 Legacy baseline 的 12/31 与 14/34、low/0 process;当前 QL3 孵化树尚未完整进入 Git baseline,因此该结果只作补充,不能替代强制全索引、完整测试和六档制品门。

后续约束

Local SQLite Adoption 后续修改必须落入明确 owner,并继续保持 source fence 为共享安全 primitive、公共 facade identity 和现有 adoption contract tests。下一轮仍只处理确有多个变化原因的实现;纯 schema、normalizer 或单一 repository authority 不因文件较大机械拆分,也不因包内文件较少机械合并 workspace package。