feat(usable): package gui-host validation snapshot
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
253
USABLE_APP_CLI_CONTRACT_SNAPSHOT.md
Normal file
253
USABLE_APP_CLI_CONTRACT_SNAPSHOT.md
Normal 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 就单独拆单”的阶段
|
||||
Reference in New Issue
Block a user