feat(usable): package gui-host validation snapshot
Some checks failed
release-smoke / macos-13 / x86_64-apple-darwin (push) Has been cancelled
release-smoke / ubuntu-latest / x86_64-unknown-linux-gnu (push) Has been cancelled
release-smoke / windows-latest / x86_64-pc-windows-msvc (push) Has been cancelled

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Paperclip CTO
2026-03-31 10:21:36 +00:00
parent 19aeb7784b
commit a28dab4cd9
47 changed files with 6894 additions and 771 deletions

View File

@@ -0,0 +1,253 @@
# `dbtool-usable-v1` Shared App / CLI Contract Snapshot
日期2026-03-27
作者Senior Backend Engineer
对应 issue`CMP-46`
## 1. 目标
本文从 `dbtool-usable-v1` 视角冻结当前 `crates/db-app``apps/cli` 的共享契约、错误边界与当前 gap。
本文不是新的架构提案,只记录当前代码与当前阶段可承诺的 backend 行为边界,供 CTO、Frontend、QA 和 PM 直接引用。
## 2. 当前后端分层
- `crates/db-core`
- 定义数据库无关的领域对象与基础校验:
- `ConnectionTarget`
- `InspectRequest`
- `QueryRequest`
- `ExportRequest`
- `InspectResult`
- `QueryResult`
- `crates/db-config`
- 定义 `ConnectionProfile`
- 负责 password env 注入与脱敏展示
- `crates/db-drivers`
- 收敛 PostgreSQL / MySQL / SQLite 的 connect / inspect / query 差异
- `crates/db-app`
- 是当前唯一共享应用编排入口
- 对 connect / inspect / query / export 暴露统一结构化结果与统一错误对象
- `apps/cli`
- 只负责参数解析、stdout/stderr 渲染、退出码
- 当前不应重新定义 shared app 语义
## 3. 领域模型与持久化边界
### 3.1 当前领域对象
- 连接目标:`ConnectionTarget`
- 连接 profile`ConnectionProfile`
- inspect 请求:`InspectRequest`
- query 请求:`QueryRequest`
- export 请求:`ExportRequest`
- 共享错误:`db_app::AppError`
- 共享状态:
- `AppOperation`
- `OperationState`
- `AppEvent<T>`
### 3.2 当前持久化边界
- 当前产品仍是单次命令执行模型
- backend 当前不引入:
- profile 持久化库
- 历史记录库
- 本地状态库
- 后台 daemon / session 存储
- 当前可见写路径只有:
- 用户显式指定的 export 输出文件
- 用户显式选择的 SQLite 数据库文件
### 3.3 迁移结论
- 当前阶段没有 backend 自身的持久化 schema因此没有迁移脚本或迁移兼容问题
- usable-v1 当前不需要新增 migration 策略
- 若未来引入本地状态存储,必须先单独定义存储边界与兼容策略,再进入实现
## 4. `db-app` 当前稳定契约
### 4.1 Connect
- 输入:`ConnectionProfile`
- 成功结果:`ConnectResponse`
- 当前状态语义:
- `success`
- 不存在 `empty`
### 4.2 Inspect
- 输入:`InspectRequest`
- 成功结果:`InspectResponse`
- `payload.kind`
- `schemas`
- `tables`
- `columns`
- 当前状态语义:
- 非空集合 => `success`
- 空集合 => `empty`
- 执行失败 => `error`
### 4.3 Query
- 输入:`QueryRequest`
- 成功结果:`QueryResponse`
- `result` 字段固定包含:
- `columns`
- `rows`
- `rows_affected`
- `row_count`
- 当前状态语义:
- `rows_affected != null` => command-style success
- 返回至少一行 => `success`
- 零行且 `rows_affected == null` => `empty`
- 执行失败 => `error`
### 4.4 Export
- 输入:
- `QueryRequest`
- `ExportRequest`
- 成功结果:`ExportResponse`
- 成功结果固定包含:
- `target`
- `source`
- `export`
- `row_count`
- 当前状态语义:
- 文件写入成功 => `success`
- `row_count == 0` 仍算 success
## 5. CLI 当前契约
### 5.1 命令面
- `connect`
- `inspect`
- `query`
- `export`
### 5.2 输出模式
- `--result-format text`
- `--result-format json`
### 5.3 成功输出
- text面向人工阅读
- json返回 envelope
```json
{
"status": "success",
"operation": "query",
"state": "success",
"data": {}
}
```
### 5.4 当前退出码约定
- 成功:`0`
- 当前 CLI 错误统一返回:`2`
## 6. 错误边界矩阵
### 6.1 共享应用层已统一的错误
当请求已经进入 `db-app` 后,当前错误会统一收敛为 `AppError`
- `validation`
- `connection`
- `authentication`
- `inspect`
- `query`
- `export`
这些错误在 CLI `--result-format json` 下当前会输出结构化 error envelope并显式带出 `state: error`
### 6.2 当前实际存在的 CLI 前置错误层
在进入 `db-app` 之前,`apps/cli` 仍有一层前置错误来源:
- CLI 参数缺失 / 非法
- `ConnectionTarget` 组装失败
- `ConnectionProfile` 组装失败
- `InspectRequest` 构造失败
- `QueryRequest` 构造失败
- `ExportRequest` 构造失败
- SQL 文件读取失败
- password env 缺失
但在当前源码下,只要用户显式传入 `--result-format json`,这组前置错误也会统一包裹成 JSON `error` envelope`kind` 固定为 `validation``state` 固定为 `error`
这些错误当前仍是字符串错误,不是 `AppError`,因此不完全受 shared error contract 保护。
## 7. 当前 gap / blocker 清单
### 7.1 当前 CLI JSON 状态映射
- CLI JSON envelope 当前固定包含:
- `status`
- `operation`
- `state`
- 当前映射规则:
- envelope 级成功仍返回 `status: success`
- envelope 级失败仍返回 `status: error`
- 共享应用层状态通过 `state` 暴露:
- `connect``success`
- `inspect``success | empty`
- `query``success | empty`
- `export``success`
- 所有错误:`error`
当前判断:
- 这让 CLI JSON 回归样本能显式区分 `empty`
- 同时不破坏既有 `status=success/error` 的 envelope 语义
### 7.2 运行环境说明
- 当前 runner 默认缺少 `cargo` / `rustc` / `cc`
- 本轮通过用户态 Rust toolchain 与 `zig cc` / `zig ar` 包装器完成了源码重建与测试
- 这属于运行环境债务,不是 backend contract defect
### 7.3 Blocker 判断
- 当前没有新的持久化 blocker
- 当前没有 migration blocker
- 当前没有新的 shared contract blocker
- 当前没有新的 backend contract blocker
## 8. 本轮验证证据
静态核对:
- `crates/db-core/src/lib.rs`
- `crates/db-config/src/lib.rs`
- `crates/db-drivers/src/lib.rs`
- `crates/db-app/src/lib.rs`
- `apps/cli/src/main.rs`
- `TUI_BACKEND_CONTRACT.md`
命令复核:
- `cargo run -q -p dbtool-cli -- inspect --driver sqlite --path /tmp/notfound.sqlite --table accounts --result-format json`
- 实际返回 JSON error envelope`kind=validation``state=error`
- `cargo run -q -p dbtool-cli -- query --driver sqlite --path /tmp/notfound.sqlite --sql '' --result-format json`
- 实际返回 JSON error envelope`kind=validation``state=error`
- `cargo run -q -p dbtool-cli -- connect --driver postgres --host 127.0.0.1 --port 5432 --database demo --username demo --password-env MISSING_ENV --result-format json`
- 实际返回 JSON error envelope`kind=validation``state=error`
- `cargo run -q -p dbtool-cli -- query --driver sqlite --path <seeded-db> --sql 'SELECT ticket_id FROM tickets WHERE status = ?1' --param missing --result-format json`
- 实际返回 `status=success``state=empty`
- `cargo test --workspace`
- 当前 runner 经过用户态 Rust + `zig cc` 补齐后,全工作区测试通过
## 9. 当前结论
- usable-v1 当前 shared app 主契约可继续冻结在 `db-app`
- 当前 CLI 主体没有重新发明 shared domain 语义
- 当前源码已经补齐 CLI JSON 模式下的前置 validation error 一致性
- 当前源码已经补齐 CLI JSON 对共享 `empty` 状态的显式映射
- 当前 backend 这条 contract snapshot 主线没有新增 open blocker
- 当前 backend 更像进入“保持 snapshot 与源码一致 + 发现 defect 就单独拆单”的阶段