mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 01:00:24 +08:00
99 lines
4.8 KiB
Markdown
99 lines
4.8 KiB
Markdown
# ADR-0160:SQLite/PostgreSQL 不可变 Tool Invocation Artifact 仓库
|
||
|
||
- 状态:Accepted
|
||
- 日期:2026-07-26
|
||
- 关联:ADR-0043、ADR-0063、ADR-0125、ADR-0158、ADR-0159;
|
||
RFC D-29/D-30/D-123/D-149/D-150
|
||
|
||
## 背景
|
||
|
||
ADR-0159 已把 Tool input 与审批 preview 从 plan 移到两个不可变 Artifact,但只有领域
|
||
envelope 和 Repository port 仍不足以支持重启、集群派发或主库晋升。双方言必须用同一
|
||
身份和重放语义持久化,同时保持低配设备不引入新进程或依赖,并避免 Cluster 的
|
||
admin、Package 与 Worker authority 取得敏感调用材料。
|
||
|
||
## 决策
|
||
|
||
### 1. 使用现有 Profile adapter package
|
||
|
||
- SQLite adapter 位于 `@qinglong/local-sqlite/tool-invocation-artifact`;
|
||
- PostgreSQL adapter 位于
|
||
`@qinglong/cluster-postgres/tool-invocation-artifact`;
|
||
- 不增加 workspace package、第三方依赖、常驻进程、timer、watcher 或缓存。
|
||
|
||
每个方言各有 input/preview 两张表。表保存受审 mirror column 和完整有界 Artifact
|
||
JSON;input JSON 只有 AES-256-GCM envelope,数据库永不保存 key material 或明文。
|
||
|
||
### 2. 双 Artifact 必须原子提交并精确重放
|
||
|
||
Repository 一次只接受具有相同 Project、action 和 sealing time 的 input/preview
|
||
pair。SQLite 使用共享 `BEGIN IMMEDIATE` operation authority;PostgreSQL 使用短
|
||
`SERIALIZABLE` transaction。任一行失败必须回滚两行。
|
||
|
||
相同 Artifact ID 只有完整规范化内容一致才能返回 `existing`。部分 pair、mirror
|
||
column 漂移、非法 JSON、digest 漂移或相同身份不同内容均失败关闭。PostgreSQL 并发
|
||
唯一键竞争在事务回滚后重读:赢家内容完全一致时收敛为 exact replay,否则为
|
||
conflict。
|
||
|
||
### 3. PostgreSQL 不以行锁换取扩大权限
|
||
|
||
Artifact 行不可变,因此 replay 读取不得使用 `FOR SHARE`。PostgreSQL 对行锁读取会
|
||
要求更新类权限,这与 append-only authority 冲突。runtime 只取得两张表的
|
||
`SELECT, INSERT`;`UPDATE, DELETE` 必须由数据库拒绝。admin、Package manager、
|
||
Package executor 和 Worker ingress 对两表均无 `SELECT/INSERT/UPDATE/DELETE`。
|
||
迁移 authority 继续独占 DDL。
|
||
|
||
### 4. Capability 与 schema 必须锁步
|
||
|
||
- SQLite:`0057-tool-invocation-artifacts` 建表,
|
||
`0058-capability-v29` 发布 `tool_invocation_artifact:1`;当前 58 条 migration、
|
||
capability v29、51 张 typed owned table;
|
||
- PostgreSQL:`pg-0031-tool-invocation-artifacts` 原子建表、安装 ACL 并发布
|
||
capability v30;当前 31 条 migration、capability v30、50 张表。
|
||
|
||
双方言 readiness、Drizzle schema、migration manifest/checksum、table/column/index/
|
||
CHECK/FK contract 必须一起前进,不能只修改 migration SQL。
|
||
|
||
## 低配与集群影响
|
||
|
||
- Edge 仍是单 SQLite 文件和现有共享写 authority;每次调用只增加两个有界行和一次
|
||
短事务,不增加后台工作;
|
||
- input 明文上限 64 KiB,完整 envelope 上限 96 KiB;preview 内容上限 8 KiB,完整
|
||
envelope 上限 16 KiB;
|
||
- Cluster 的两个 Artifact 随 PostgreSQL WAL 复制,不在应用层再造复制协议;
|
||
- retention/rekey 不进入 runtime 热路径,后续必须由短生命周期 maintenance
|
||
authority 实现。
|
||
|
||
## 被否决方案
|
||
|
||
1. **给 runtime 授予 UPDATE 以继续使用 `FOR SHARE`**:为不可变表扩大权限,且不能
|
||
提供额外正确性。
|
||
2. **分别 autocommit 两个 Artifact**:崩溃会留下无法判定的半 pair。
|
||
3. **把 Artifact 写入 start barrier JSON**:扩大热表和恢复读取面,并复制
|
||
ciphertext。
|
||
4. **让 admin/Package executor 代写**:混淆执行 authority 与管理/发布 authority。
|
||
5. **新增 Artifact workspace package**:没有独立部署、依赖或权限生命周期。
|
||
|
||
## 验证
|
||
|
||
- SQLite database/schema/Artifact repository 定向测试 16/16;
|
||
- PostgreSQL migration/schema/readiness/Artifact repository 定向测试 33/33;
|
||
- Artifact repository 额外覆盖 concurrent unique winner exact replay、半 pair
|
||
rollback、损坏 mirror fail-closed 与禁止 `FOR SHARE`;
|
||
- PostgreSQL 18.4 arm64 双节点物理 HA:
|
||
- runtime 原子写入并 exact replay;
|
||
- input JSON 不含测试明文;
|
||
- admin、Package manager、Package executor、Worker ingress 均被数据库拒绝;
|
||
- `remote_apply` standby 已观察两行;
|
||
- timeline 1→2 promotion 后 runtime 可读取并重放;
|
||
- 旧主经 `pg_rewind` 只读同步重入,总 gate `passed=true`。
|
||
|
||
## 后续门禁
|
||
|
||
1. retention、key rotation/rekey、遗失 key 和损坏 row 的 inspect/manual recovery;
|
||
2. 首个 trusted built-in adapter 在 durable start 后解封并再次验证 Registry;
|
||
3. adapter response-loss/进程崩溃的无重复副作用恢复证据。
|
||
|
||
Artifact reference 与最终 start barrier 的双方言原子绑定已由 ADR-0161
|
||
完成,不再属于开放项。
|