8.1 KiB
ADR-0323:Local SQLite Adoption 领域归属
- 状态:Accepted
- 日期:2026-08-10
- 关联 RFC:QL-RFC-0001 D-05、D-06、D-17、D-64、D-87、D-257
- 关联 ADR:ADR-0064、ADR-0095、ADR-0312、ADR-0321、ADR-0322
背景
ADR-0321/0322 已区分 workspace package 与 package-private module:package 表达部署、authority、依赖、adapter、
multi-consumer 或供应链边界,包内领域目录表达共同变化的 ownership。继续审计 @qinglong/local-admin 时发现,
legacy-adoption/localSqliteAdoption.ts 以 1,940 行同时拥有:
- Legacy SQLite read-only 打开、catalog 证据与 crontab inventory/diagnostic;
- reviewed decision receipt、authorization file、issuer 与 publisher bridge;
- migration staging、backup、manifest 与 snapshot verification;
- SQLite source
BEGIN IMMEDIATEwrite fence; - activation document、prepare 与 acquire。
这不是“包太细”,而是同一 Local Admin 运行单元内的五类 ownership 被平铺在一个文件中。把这些职责各自发布成 workspace package 会制造部署和依赖噪声;继续维持单文件则会让 inspection、review、staging 与 activation 的安全边界 难以独立评审。
编辑前已对原文件内全部 49 个 function、class 和 method 执行 GitNexus upstream impact。稳定错误
LocalSqliteAdoptionError 为 CRITICAL(35 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 authority;filesystem.ts 只拥有通用的严格文件证据;
inspection.ts 保持 legacy adoption module 的 lazy load;staging.ts 唯一拥有备份、migration 与 manifest;
sourceFence.ts 是 review 和 activation 共同依赖的安全 primitive,单独放置以避免二者形成循环;review.ts 保持
reviewed authorization/publisher bridge 的 lazy load;activation.ts 唯一拥有 activation 生命周期。
原 facade 只显式 re-export 既有公共类型和 13 个 runtime object。所有 runtime export 与 owner module 保持同一个
class/function identity,instanceof、错误 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”。后续统一采用:
- 只有独立 deployable、authority、dependency、adapter、multi-consumer 或供应链边界才能新建 workspace package;
- 同一 package 内按业务领域和共同变化原因建立私有目录,根
src只保留受审 public facade、composition root 或 bin; - 一个领域允许多个内聚文件,也允许一个纯 schema/codec 文件较大;不按 LOC、函数数或单文件 package 机械拆合;
- 共享 helper 只有在具有稳定语义和两个以上真实 owner 时才提取,禁止建立
utils/杂物层; - 拆分必须保持依赖 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 门。
被否决方案
- 七个 owner 各建 workspace package:不存在七个独立部署或消费者闭包,拒绝。
- 维持 1,940 行平铺文件:inspection、review、staging、fence 与 activation 无法独立评审,拒绝。
- 每个 function 一个文件:破坏同一协议的内聚性并增加导航成本,拒绝。
- 把所有 helper 放进
utils.ts:隐藏 file identity 与安全 fence 的真实 ownership,拒绝。 - 把 source fence 归 review 或 activation:另一侧会反向依赖并可能形成循环,拒绝。
- 趁拆分重写 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 nested,
singleSourcePackages=[]、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 modules;Application 为 4,762,901/4,763,021 bytes、453 files、116 modules;Application AI 为 6,158,278/6,158,410 bytes、532 files、 115 modules。相对 ADR-0322 各增加 10,417 bytes/7 files,loaded module 数不变,六档均 compatible。
- 最终强制索引为 44,038 nodes/100,277 edges/1,729 clusters/274 flows。post-impact 中稳定错误保持 CRITICAL
(40 direct/54 total/0 flows),
sha256Text与 inspection 保持 MEDIUM(7/24、8/13),source fence 为 LOW (3/3),staging/review/activation 代表 coordinator 为 LOW(0/0);高风险调用关系没有因 facade re-export 被隐藏。 detect_changesall/comparedevelop仍只映射已跟踪 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。