xworkmate-app/docs/howto/persistence-storage-layout.md
2026-03-23 21:45:36 +08:00

118 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Persistence Storage Layout
## 目标
本文定义桌面端持久化层的唯一落地规则。`XWorkmate.svc.plus` 后续必须只认这一套目录和文件约定,不再引入 SQLite、本地 secret fallback、或第二套临时持久化路径。
## 存储原则
- 非敏感配置只写 `settings.yaml`
- 任务线程会话按 `sessionKey` 单文件保存
- 敏感信息只写固定 `secret path`
- 首次启动必须自动建目录
- 重启和升级不能主动删除配置或会话文件
- 文件写入使用临时文件后替换的原子写策略
- 磁盘路径不可用时,只允许退回内存,不再切换到另一套本地 fallback 持久化
## 默认目录结构
默认根目录位于应用支持目录下的 `xworkmate` 子目录。
macOS 示例:
```text
~/Library/Application Support/<App Support>/xworkmate/
```
运行时布局:
```text
xworkmate/
config/
settings.yaml
secret-audit.json
tasks/
index.json
<sessionKey-encoded>.json
secrets/
<key-encoded>.secret
```
## 文件职责
### `config/settings.yaml`
- 唯一非敏感配置源
- 内容对应 `SettingsSnapshot.toJson()`
- 不保存 token、password、API key、device private key 等敏感字段
### `config/secret-audit.json`
- 保存 `SecretAuditEntry` 列表
- 属于本地非敏感审计信息
- 最大长度由运行时控制
### `tasks/index.json`
- 保存线程会话顺序
- 当前格式:
```json
{
"version": 1,
"sessions": ["session-a", "session-b"]
}
```
### `tasks/<sessionKey-encoded>.json`
- 每个线程会话一个文件
- 文件内容为 `AssistantThreadRecord.toJson()`
- 文件名不直接使用原始 `sessionKey`,而是稳定编码后的结果,避免跨平台文件名问题
- 记录内容里的 `sessionKey` 仍保持原值,不修改模型
### `secrets/<key-encoded>.secret`
- 固定 secret path
- 每个 secret key 一个文件
- 保存 Gateway token、Gateway password、AI Gateway API key、Vault token、device identity、device token 等敏感信息
- 文件名使用稳定编码,避免泄露原始 key 名并规避非法字符
## 初始化规则
- `SecureConfigStore.initialize()` 必须先准备目录结构
- 不要求用户先保存一次配置,目录应在首次运行时就存在
- 如果外部显式传入测试路径覆盖,仍然遵守相同布局
## 清理规则
- `clearAssistantLocalState()` 只清理:
- `settings.yaml`
- `tasks/index.json`
- `tasks/*.json`
- 不清理 `secrets/*.secret`
- 不主动清理 `secret-audit.json`
## 恢复规则
- 启动时先读 `settings.yaml`
- 再读 `tasks/index.json` 与对应 task 文件
- `index.json` 缺失时,允许扫描 `tasks/*.json` 进行恢复
- `secret path` 中某个 key 缺失时,只影响该 key不应拖垮整个 store
## 禁止事项
- 禁止重新引入 SQLite 作为桌面持久化主存储
- 禁止把 secret 写入 `SharedPreferences`
- 禁止把 `.env` 自动导入为持久化配置
- 禁止在 secret path 不可用时偷偷切换到另一套磁盘 fallback 路径
- 禁止在升级或启动时主动删除已有配置与会话文件
## 测试建议
- 验证首次启动自动建目录
- 验证重启后 `settings.yaml` 可恢复
- 验证 `tasks/<session>.json` 跨实例可恢复
- 验证 `clearAssistantLocalState()` 不删 secrets
- 验证磁盘不可用时保留内存态,不发生崩溃