diff --git a/docs/architecture/secure-local-persistence-architecture.md b/docs/architecture/secure-local-persistence-architecture.md
new file mode 100644
index 00000000..e6cb1da0
--- /dev/null
+++ b/docs/architecture/secure-local-persistence-architecture.md
@@ -0,0 +1,211 @@
+# Secure Local Persistence Architecture
+
+## 目标
+
+这次补丁保持现有 UI 不变,只重设计 `XWorkmate` 的本地配置与任务会话持久层,满足两个约束:
+
+- 本地配置和任务会话必须能跨重启、跨覆盖安装恢复。
+- 持久化以前提 `secure storage` 为本地信任根,避免把可恢复状态明文落盘。
+
+核心结论:
+
+- `FlutterSecureStorage` 仍是长期 secret 的主存储。
+- 本地配置和任务会话不直接明文写入 SQLite / JSON,而是先用本地状态密钥加密后再落盘。
+- 本地状态密钥本身必须优先保存在主 secure storage,不再把它当成普通可降级 secret。
+
+## Trust Boundary
+
+需要明确区分 3 类状态:
+
+1. 用户输入的高敏感 secret
+ - Gateway shared token
+ - Gateway password
+ - AI Gateway API key
+ - Vault token
+
+2. 可恢复但不应明文落盘的本地状态
+ - `SettingsSnapshot`
+ - Assistant 任务线程记录
+ - 最后活动线程
+ - 本地恢复 backup
+
+3. 仅调试或测试环境可接受的替代路径
+ - 注入式 secure storage client
+ - 临时文件型 secure storage fallback
+
+边界规则:
+
+- 第 1 类状态优先进入 secure storage;secure storage 超时或异常时,可进入持久化 fallback 文件,但绝不退化成“仅内存”。
+- 第 2 类状态不直接进入 `SharedPreferences` 或明文 SQLite;必须先 sealed。
+- 第 3 类路径只用于 debug / test,不进入 release 行为。
+
+## 架构图
+
+```mermaid
+flowchart TD
+ A["Gateway / Settings Form"] --> B["SettingsController"]
+ C["Assistant Thread State"] --> D["AppController"]
+ B --> E["SecureConfigStore"]
+ D --> E
+
+ E --> F["Primary Secure Storage
FlutterSecureStorage"]
+ E --> G["Local State Key
xworkmate.local_state.key"]
+ G --> H["AES-GCM Seal / Unseal"]
+
+ H --> I["SQLite config-store.sqlite3"]
+ H --> J["Durable state files
settings-snapshot.json
assistant-threads.json"]
+ H --> K["assistant-state-backup.json
schemaVersion=2 / sealedState"]
+
+ E --> L["Secure secret fallback files
gateway-auth/*"]
+```
+
+## 存储分层
+
+### 1. Primary Secure Storage
+
+用途:
+
+- 保存 Gateway token / password / AI Gateway API key / Vault token
+- 保存本地状态密钥 `xworkmate.local_state.key`
+
+关键要求:
+
+- 主路径仍然是 `FlutterSecureStorage`
+- 本地状态密钥不允许再走“通用 secret fallback”
+- 如果主 secure storage 不可用,不允许把本地状态密钥退化成普通文件常态
+
+### 2. Sealed Local State
+
+本地配置和任务会话的持久化结构统一改为:
+
+- `storageFormat = xworkmate.sealed.local-state.v1`
+- `nonce`
+- `cipherText`
+- `mac`
+
+加密方式:
+
+- AES-GCM 256
+- 每次写入使用新的随机 nonce
+- AAD 绑定存储 key,避免跨 key 错读
+
+当前覆盖对象:
+
+- `xworkmate.settings.snapshot`
+- `xworkmate.assistant.threads`
+- `assistant-state-backup.json`
+
+### 3. Durable Recovery Files
+
+当 SQLite 不可用时,仍需保证本地状态可以恢复。为此保留两类耐久化文件:
+
+- `settings-snapshot.json`
+- `assistant-threads.json`
+
+注意:
+
+- 文件名虽然保持旧风格,但内容已改为 sealed payload,不再是明文 JSON。
+
+### 4. Assistant Backup
+
+`assistant-state-backup.json` 升级到 schema v2:
+
+- 用 `sealedState` 保存整体恢复快照
+- 不再把 settings / threads 明文拼进 backup
+
+这样做的目的:
+
+- 避免备份文件成为最容易泄露的明文副本
+- 保持“数据库损坏时仍可恢复”的能力
+
+## 写入流程
+
+### SettingsSnapshot
+
+1. `SettingsController` 生成新的 `SettingsSnapshot`
+2. `SecureConfigStore.saveSettingsSnapshot()` 进入本地状态写队列
+3. 读取或生成 `xworkmate.local_state.key`
+4. 先 sealed,再写入 SQLite / durable file / backup
+
+### Assistant Threads
+
+1. `AppController` 更新线程记录
+2. 持久化进入 `_assistantThreadPersistQueue`
+3. `SecureConfigStore.saveAssistantThreadRecords()` 串行 sealed 写入
+4. 同步刷新 SQLite / durable file / backup
+
+这么做是为了避免异步写晚到,把旧线程快照覆盖新状态。
+
+## 读取与恢复流程
+
+恢复顺序:
+
+1. 优先读 SQLite
+2. SQLite 不可用时读 durable state files
+3. 若主状态缺失,再读 `assistant-state-backup.json`
+4. 若读到的是旧明文格式,则立即迁移为 sealed 格式
+
+迁移原则:
+
+- 兼容旧明文快照,避免升级后直接丢历史
+- 一旦成功恢复,就把旧格式重写成 sealed 新格式
+- legacy `SharedPreferences` 里的本地状态在迁移后会被清理
+
+## Secure Secret Fallback
+
+Secret fallback 仍然保留,但语义变了:
+
+- 用于 Gateway token / password / API key 等长期 secret 的持久化兜底
+- 不再因为一次超时就退化成“仅内存”
+- 这样即使 secure storage 一时不可用,重启后 secret 仍能恢复
+
+约束:
+
+- `xworkmate.local_state.key` 不在通用 fallback 白名单里
+- 对旧版遗留的 `local-state-key.txt`,启动时做一次迁移,成功后删除
+
+## Clear 行为
+
+`clearAssistantLocalState()` 只清理:
+
+- 本地 settings snapshot
+- 本地 assistant thread records
+- durable state files
+- assistant backup
+
+不会误删:
+
+- 已保存的 Gateway token / password
+- AI Gateway API key
+- Vault token
+- 其他 secure refs
+
+## Debug / Test 策略
+
+为了让测试稳定运行,新增了可注入的 secure storage 层:
+
+- `SecureStorageClient`
+- `FlutterSecureStorageClient`
+- `FileSecureStorageClient`
+- `MemorySecureStorageClient`
+
+策略是:
+
+- release:使用真实 `FlutterSecureStorage`
+- debug / test:允许走注入式或文件型 secure storage,保证单测和回归可跑
+
+这不会改变 release 的安全边界。
+
+## 与现有 UI 的关系
+
+这次补丁不改:
+
+- Gateway 设置页结构
+- Assistant 任务线程 UI
+- 模型、skills、入口按钮布局
+
+变化只在持久层和恢复链路:
+
+- 重启后不再因为 secure storage 一次超时而丢本地配置
+- 覆盖安装后本地配置与任务会话仍可恢复
+- 本地 snapshot / backup 不再以明文保存
diff --git a/docs/cases/secure-local-persistence-postmortem.md b/docs/cases/secure-local-persistence-postmortem.md
new file mode 100644
index 00000000..d8b134bc
--- /dev/null
+++ b/docs/cases/secure-local-persistence-postmortem.md
@@ -0,0 +1,181 @@
+# Secure Local Persistence Postmortem
+
+## 问题摘要
+
+用户现场反馈很直接:
+
+- 当前会话里 Gateway 可以正常连接
+- App 一重启,本地配置和已保存凭证丢失
+- `Gateway 访问` 页重新出现 `gateway token missing`
+
+这不是单点 bug,而是持久层设计里连续几处降级路径叠加后的结果。
+
+## 用户可见症状
+
+### 1. 重启后网关凭证丢失
+
+表现:
+
+- token / password 在当前会话内可用
+- 退出再打开后不可用
+- 首次连接提示重新输入 shared token
+
+### 2. 本地配置或任务会话恢复不稳定
+
+表现:
+
+- settings snapshot 或 assistant threads 在某些路径下恢复失败
+- backup 虽然存在,但仍可能是明文旧格式
+
+### 3. 明文本地状态残留
+
+表现:
+
+- 旧版 `SharedPreferences` 和 SQLite 中存在明文 settings / threads
+- backup 文件也可能保留明文副本
+
+## 根因
+
+## 根因 1:对 `FlutterSecureStorage` 强制套了 400ms 超时
+
+旧逻辑:
+
+- secure storage 读写只要超过 `400ms`,就视为失败
+- 一旦失败,直接退化成“仅内存”
+
+结果:
+
+- 当前进程内看起来一切正常
+- 因为值实际上没持久化,进程退出后凭证全部丢失
+
+这是这次“重启后 token 消失”的直接根因。
+
+## 根因 2:secure storage 失败时降级策略设计错了
+
+旧策略把“可恢复 secret”误当成“会话临时缓存”处理:
+
+- token / password / API key 没写进 durable fallback
+- 只保存在进程内存
+
+这个策略对调试场景看似友好,但对桌面 App 的真实使用是灾难性的,因为用户天然预期“已经保存”的 secret 会跨重启存在。
+
+## 根因 3:legacy prefs 迁移把明文直接写回了主存储
+
+迁移链路里存在一个关键缺口:
+
+- 从 `SharedPreferences` 读取到旧版明文 settings / threads
+- 直接调用数据库写入
+- 没有经过 sealed local state
+
+结果:
+
+- 用户完成升级后,本地状态仍可能继续以明文形式存在 SQLite
+- 旧的 pref key 也没有被及时清理
+
+这让“升级到新版本后自动变安全”的承诺失效了。
+
+## 根因 4:本地状态密钥也被允许走普通 fallback
+
+旧版把 `xworkmate.local_state.key` 当成普通 secret 处理。
+
+结果:
+
+- 一旦它掉进 fallback 文件,secure storage 就不再是本地状态加密的真正前提
+- 架构上变成“有 secure storage 更好,没有也能常态运行”
+
+这违背了本次补丁要建立的安全模型。
+
+## 根因 5:线程状态异步保存存在覆盖竞态
+
+Assistant 线程会话是异步落盘的。旧逻辑没有串行 flush:
+
+- 线程 A 的旧快照可能在稍后写入
+- 覆盖线程 B 或更新后的新状态
+
+在加密封装增加写入成本后,这个竞态更容易暴露。
+
+## 修复策略
+
+### 1. secure storage 不再 400ms 即判死刑
+
+- 超时提高到 `5s`
+- 对真实 `FlutterSecureStorage` 保留超时保护
+- 对测试注入 client 不套这层超时
+
+### 2. secure storage 失败时改为 durable fallback,而不是仅内存
+
+- Gateway token
+- Gateway password
+- AI Gateway API key
+- Vault token
+
+这些 secret 在 secure storage 异常时会写入持久化 fallback,保证跨实例恢复。
+
+### 3. 本地配置和任务会话统一 sealed
+
+对以下状态统一改为 AES-GCM sealed payload:
+
+- `SettingsSnapshot`
+- Assistant thread records
+- `assistant-state-backup.json`
+
+目标是消除明文 SQLite / 明文 JSON backup。
+
+### 4. legacy 明文状态迁移时立即重写并清理旧 pref
+
+新逻辑:
+
+- 读旧 pref
+- 若目标存储不存在,则按 sealed 路径写入
+- 写入成功后删除旧 pref key
+
+这样升级后不会继续遗留明文主副本。
+
+### 5. 本地状态密钥升级为 primary secure storage only
+
+`xworkmate.local_state.key` 现在的规则是:
+
+- 必须优先保存在主 secure storage
+- 不再纳入普通 secure fallback 白名单
+- 对旧版 `local-state-key.txt` 仅做一次迁移,随后删除
+
+### 6. Assistant 线程持久化改为串行队列
+
+新增线程持久化 queue 和 flush 机制,保证:
+
+- 新状态不会被晚到的旧写入覆盖
+- clear / send / view-mode 切换前可以先 flush
+
+### 7. dispose 后的异步通知保护
+
+`SettingsController` 新增 dispose guard,避免恢复链路异步完成后向已销毁对象 `notifyListeners()`。
+
+## 为什么旧方案会失效
+
+旧方案的问题不在“没加密”,而在于它把三件不同的事混在了一起:
+
+- 当前请求是否可用
+- 是否已经持久化
+- 是否已经安全持久化
+
+一旦 secure storage 稍慢,系统就会把“当前连接可继续”错误地当成“数据已经保存”,这正是桌面应用里最危险的误导。
+
+## 回归防线
+
+这次新增的回归覆盖重点包括:
+
+- secure storage 超时后 secret 仍能跨实例恢复
+- SQLite 不可用时,sealed 的 settings / threads 仍能恢复
+- plaintext local state 能迁移为 sealed storage
+- legacy `local-state-key.txt` 能迁移到主 secure storage 并被清理
+- backup 文件不再泄露明文 settings / threads
+
+## 后续约束
+
+后续所有涉及本地状态持久化的修改,都必须继续满足:
+
+- `.env` 仍是预填,不是持久化真值
+- 当前用户发起连接时可直接用表单值握手,不依赖 secure-store 回读
+- local state 不得重新落回 `SharedPreferences` 明文
+- backup 不得重新变成明文副本
+- 不能再让 `xworkmate.local_state.key` 走常态文件 fallback
diff --git a/docs/releases/2026-03-22-secure-persistence-release-update.md b/docs/releases/2026-03-22-secure-persistence-release-update.md
new file mode 100644
index 00000000..cd560577
--- /dev/null
+++ b/docs/releases/2026-03-22-secure-persistence-release-update.md
@@ -0,0 +1,117 @@
+# 2026-03-22 Secure Persistence Release Update
+
+## 摘要
+
+这次补丁修复的是一个发版级问题:
+
+- `XWorkmate.app` 在某些机器上重启后会丢失本地 Gateway 配置和已保存凭证
+- Assistant 本地任务线程和恢复快照的持久化链路存在明文残留和竞态风险
+
+本次发布不改 UI,只修正持久层与恢复链路。
+
+## 用户可感知变化
+
+### 1. 重启后本地配置不应再消失
+
+修复后:
+
+- Gateway host / port / TLS 等本地配置继续恢复
+- 已保存的 shared token / password 不再因为一次 secure storage 超时而只留在内存里
+
+### 2. 覆盖安装后本地状态仍应保留
+
+修复后:
+
+- `/Applications/XWorkmate.app` 覆盖安装不会清掉本地配置和任务会话
+- Assistant 最后活动线程与消息历史应继续可恢复
+
+### 3. 本地快照不再明文持久化
+
+修复后:
+
+- `SettingsSnapshot`
+- Assistant thread records
+- `assistant-state-backup.json`
+
+都改为 sealed local state,而不是明文 JSON/SQLite。
+
+## 核心修复点
+
+- `SecureConfigStore` 的 secure storage 超时从 `400ms` 调整到 `5s`
+- secure storage 超时/异常时,secret 改为 durable fallback,而不是“只存内存”
+- 本地配置与任务线程统一做 AES-GCM sealed persistence
+- `assistant-state-backup.json` 升级为 schema v2,使用 `sealedState`
+- legacy plaintext prefs / local-state key fallback 增加迁移与清理
+- Assistant 线程持久化改为串行队列,避免异步晚到覆盖新状态
+
+## 自动化验收
+
+已执行结果:
+
+- `flutter analyze`:通过
+- `flutter test`:未作为整套 baseline 通过,当前在 `test/features/ai_gateway_page_test.dart` 的 `Settings external agents detail shows Codex bridge runtime states` case 后挂住,未产生断言失败,但进程不退出
+- `flutter test test/runtime/secure_config_store_test.dart test/runtime/app_controller_execution_target_switch_test.dart test/runtime/app_controller_ai_gateway_chat_test.dart test/features/settings_ai_gateway_persistence_test.dart test/runtime/app_controller_gateway_token_state_test.dart`:通过
+- `flutter test integration_test/desktop_navigation_flow_test.dart -d macos`:通过
+- `flutter test integration_test/desktop_settings_flow_test.dart -d macos`:通过
+- `flutter build macos --release`:通过
+- `flutter build ios --simulator`:通过
+- `make install-mac`:通过
+
+补充说明:
+
+- 两个 macOS integration 都出现 `Failed to foreground app; open returned 1`,但设备跑断言本身通过,输出包含 `All tests passed!`
+- 当前未把挂住的 `ai_gateway_page_test` 假定为通过;它被保留为现有测试阻塞项
+
+## 当前机器实机复测
+
+已在当前机器完成两轮宿主级复测。
+
+第一轮,重启恢复:
+
+1. 配置本地 Gateway
+2. 退出 App
+3. 重新打开确认配置和任务会话仍在
+
+第二轮,覆盖安装恢复:
+
+1. 再次执行 `make install-mac`
+2. 重新打开 `/Applications/XWorkmate.app`
+3. 复查本地状态持久化产物
+
+结果:
+
+- `/Applications/XWorkmate.app` 可正常重新打开
+- 本地 SQLite 状态仍为 sealed payload,没有回退成明文
+- `assistant-state-backup.json` 仍为 `schemaVersion = 2` 且包含 `sealedState`
+- legacy `SharedPreferences` 中的 `flutter.xworkmate.settings.snapshot` 在新版 App 启动后一轮迁移后被清理
+- `gateway-auth/` 目录下未再残留 `local-state-key.txt`
+- 第二次覆盖安装后,上述状态保持不变
+
+## 宿主级检查
+
+需要确认:
+
+- `config-store.sqlite3` 中的本地状态是 sealed payload,而不是明文 JSON
+- `assistant-state-backup.json` 为 schema v2 且包含 `sealedState`
+- `settings-snapshot.json` / `assistant-threads.json` 如果存在,内容也应为 sealed payload
+- 不出现明文 token / password
+- 旧版 `local-state-key.txt` 若存在,应完成一次迁移并被清理
+
+当前机器检查结果:
+
+- `config-store.sqlite3`:通过
+- `assistant-state-backup.json`:通过
+- `settings-snapshot.json` / `assistant-threads.json`:存在且为 sealed payload
+- 明文 `token/password`:未发现
+- `local-state-key.txt`:未发现,说明旧文件已迁移并清理
+
+## 兼容与边界
+
+- `.env` 仍然只是 Settings -> Integrations -> Gateway 的预填来源,不会变成持久化真值源
+- 用户发起连接时,仍然使用当前表单值做即时握手,不依赖 secure-store 回读
+- UI 布局不变,只修改持久化和恢复逻辑
+
+## 相关文档
+
+- [Secure Local Persistence Architecture](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/architecture/secure-local-persistence-architecture.md)
+- [Secure Local Persistence Postmortem](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/cases/secure-local-persistence-postmortem.md)
diff --git a/docs/releases/2026-03-22-secure-persistence-social-copy.md b/docs/releases/2026-03-22-secure-persistence-social-copy.md
new file mode 100644
index 00000000..d5482973
--- /dev/null
+++ b/docs/releases/2026-03-22-secure-persistence-social-copy.md
@@ -0,0 +1,83 @@
+# 2026-03-22 Secure Persistence Social Copy
+
+## X
+
+```text
+XWorkmate 刚发了一个很关键的稳定性补丁:
+
+修复了 macOS App 在重启 / 覆盖安装后,本地 Gateway 配置、已保存凭证和任务会话可能丢失的问题。
+
+这次没有改 UI,重点是把本地 settings、assistant threads 和 recovery backup 全部切到 secure-storage 前提下的 sealed persistence。
+
+结果很直接:
+- 重启后状态不再丢
+- 覆盖安装后状态继续保留
+- 本地 snapshot / backup 不再明文落盘
+
+#Flutter #macOS #AIGateway #SecurityEngineering
+```
+
+## 领英
+
+```text
+我们刚完成了 XWorkmate 一次很典型、也很值得发出来的桌面应用可靠性修复。
+
+问题表面上看是“App 重启后本地配置丢失”,但根因并不只是一个保存 bug。我们最终定位到几层叠加问题:
+
+1. Secure storage 读写被硬性套了 400ms 超时,超时后直接退化成“只存内存”
+2. 本地 settings / task session 的恢复链路里还残留 plaintext migration 路径
+3. Assistant thread 的异步持久化存在晚到覆盖新状态的竞态
+
+这次修复后,我们把本地持久层重构为:
+
+- FlutterSecureStorage 作为 secret 和 local-state key 的主信任根
+- SettingsSnapshot、assistant thread records、recovery backup 统一做 AES-GCM sealed persistence
+- SQLite 不可用时,仍通过 sealed durable files 保证可恢复
+- secure storage 失败时,长期 secret 进入 durable fallback,而不是消失在会话内存里
+
+对用户来说,变化是简单的:
+
+- 重启后,Gateway 配置和任务会话不再丢
+- 覆盖安装后,本地状态继续保留
+- 本地 snapshot / backup 不再明文落盘
+
+这类修复的价值,不在于“加了加密”四个字,而在于把“当前请求可用”“已经持久化”“已经安全持久化”这三件事重新分层,并让产品行为和用户预期重新对齐。
+
+#SoftwareArchitecture #SecurityEngineering #Flutter #DesktopApp #Reliability
+```
+
+## 小红书
+
+```text
+最近把 XWorkmate 修了一个很真实的坑,值得单独记一笔。
+
+用户反馈是:
+“这次明明连上了,为什么重启以后本地配置又没了?”
+
+一开始看像保存没写进去,继续往下查才发现问题更深:
+
+1. secure storage 只要慢一点,旧逻辑 400ms 就判失败
+2. 失败后不是写持久化兜底,而是直接退成“只存内存”
+3. 所以当前会话看起来正常,App 一退出,token / password 就跟着没了
+4. 更糟的是,本地 settings 和任务会话的旧迁移链路里还残留明文落盘
+
+这次补丁做了几件事:
+
+- secure storage 超时从 400ms 提到 5s
+- secret 异常时走 durable fallback,不再只活在内存里
+- 本地 settings、assistant threads、backup 全部改成 sealed persistence
+- 修掉旧版 plaintext migration
+- 补上 assistant thread 持久化竞态保护
+
+结果就是:
+
+- 重启后本地 Gateway 配置不再丢
+- 覆盖安装后任务会话还能回来
+- 本地 snapshot / backup 不再是明文
+
+这类问题最难的点,不是修一行代码,而是把“能连上”和“真的保存了”分开看。
+
+桌面 App 做到最后,用户要的不是一个当下能跑的 demo,而是一个重启以后还记得自己的工具。
+
+#独立开发 #Flutter #桌面应用 #AI工具 #产品修复复盘
+```