Go to file
agent 57c3efb70e feat(auth): 服务端托管 Google OAuth;修复未解锁 vault 时 bootstrap
- API:桌面登录 session、Google 托管回调与轮询
- Desktop:轮询登录;bootstrap 在 vault 未解锁时不返回 shell,避免跳过主密码
- 文档与 deploy/.env.example 对齐 GOOGLE_OAUTH_* 与 SECRETS_PUBLIC_BASE_URL
2026-04-14 22:05:11 +08:00

Secrets

这是 v3 架构的仓库,当前主路径已经收敛为:

  • apps/api:远端 JSON API
  • apps/desktop/src-tauri:桌面客户端
  • crates/desktop-daemon:本地 MCP 入口
  • crates/application / domain / infrastructure-db:业务与数据层

本地开发

cp deploy/.env.example .env

# 远端 API
cargo run -p secrets-api --bin secrets-api

# 本地 daemon
cargo run -p secrets-desktop-daemon

# 桌面客户端
cargo run -p secrets-desktop

说明:

  • apps/desktop/src-tauri/tauri.conf.jsonbuild.frontendDist 指向 apps/desktop/dist
  • 当前仓库会直接提交 apps/desktop/dist/ 下的桌面端静态资源
  • 因此新机器 clone 后,无需额外前端构建步骤即可启动 desktop
  • 官网 DMG 正式分发不依赖本地 client_secret_*.json
  • Google OAuth 凭据只配置在 API 服务端desktop 通过浏览器完成托管登录

官网 DMG 的服务端 OAuth 配置

官网 DMG 正式分发时,Google OAuth 只配置在 API 服务端。桌面端不需要本地 client_secret_*.json,也不直接向 Google 换 token。

建议先复制 deploy/.env.example.env,然后至少配置以下变量:

SECRETS_PUBLIC_BASE_URL=https://secrets.example.com
GOOGLE_OAUTH_CLIENT_ID=your-google-oauth-client-id.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=your-google-oauth-client-secret
GOOGLE_OAUTH_REDIRECT_URI=https://secrets.example.com/auth/google/callback

变量含义:

  • SECRETS_PUBLIC_BASE_URL:桌面端打开浏览器时访问的 API 外网基地址,必须是用户浏览器能访问到的公开地址
  • GOOGLE_OAUTH_CLIENT_IDGoogle Cloud Console 中为服务端登录流程配置的 OAuth Client ID
  • GOOGLE_OAUTH_CLIENT_SECRET:对应的 Client Secret只能保留在服务端
  • GOOGLE_OAUTH_REDIRECT_URIGoogle 登录完成后回调到 API 的地址,必须与 Google Console 中登记的回调地址完全一致

配置步骤建议:

  1. 在 Google Cloud Console 创建或选择 OAuth Client
  2. 把授权回调地址加入允许列表,例如 https://secrets.example.com/auth/google/callback
  3. 把上面的 4 个变量配置到 API 服务的运行环境中
  4. 确认 SECRETS_PUBLIC_BASE_URLGOOGLE_OAUTH_REDIRECT_URI 使用同一公开域名
  5. 重启 API 服务后,再用 desktop / DMG 验证浏览器登录流程

注意:

  • GOOGLE_OAUTH_CLIENT_SECRET 不要提交到仓库
  • GOOGLE_OAUTH_REDIRECT_URI 不要写成 localhost,正式分发应使用官网可访问域名
  • 如果 API 部署在反向代理后面,SECRETS_PUBLIC_BASE_URL 应填写用户实际访问的 HTTPS 地址,而不是内网监听地址

当前能力

  • 桌面端使用系统浏览器完成 Google Desktop OAuth 登录
  • 登录成功后向 API 注册设备,并在当前桌面进程内维护登录会话
  • 本地 daemon 提供显式拆分的 MCP 工具:
    • secrets_entry_find / secrets_entry_get
    • secrets_entry_add / secrets_entry_update / secrets_entry_delete / secrets_entry_restore
    • secrets_secret_add / secrets_secret_update / secrets_secret_delete
    • secrets_secret_history / secrets_secret_rollback
    • target_exec
  • 桌面端会自动把本地 daemon MCP 配置写入 CursorClaude Code
  • 桌面端支持条目新建、搜索、按 type 筛选、元数据编辑、最近删除与恢复
  • 桌面端支持 secret 新增、编辑、删除、明文显示、真实复制、历史查看与回滚
  • 不保留 secrets_env_map
  • 不做自动恢复登录;重启 app 后必须重新登录

提交前检查

cargo fmt -- --check
cargo clippy --locked -- -D warnings
cargo test --locked

PostgreSQL TLS 加固

  • 推荐将数据库域名单独设置为 db.refining.ltd,服务域名保持 secrets.refining.app
  • 数据库证书建议使用可校验链路(如 Let's Encrypt 或私有 CA并保证证书 SAN 包含 db.refining.ltd
  • PostgreSQL 侧建议使用 hostssl 规则限制应用来源(如 47.238.146.244/32),逐步移除公网明文 host 访问。
  • 应用端推荐 SECRETS_DATABASE_SSL_MODE=verify-full;仅在过渡阶段可临时用 verify-ca
  • 可执行运维步骤见 [deploy/postgres-tls-hardening.md](deploy/postgres-tls-hardening.md)

MCP 与 AI 工作流v3

当前 v3 以 桌面端 + 本地 daemon 为主路径:

  • 桌面端登录态仅在当前进程内有效,不持久化 device token
  • 本地 daemon 默认监听 http://127.0.0.1:9515/mcp
  • daemon 通过活跃 desktop 进程提供的本地会话转发访问 APIdesktop 进程退出后所有工具不可用
  • target_exec 会显式读取真实 secret 值后再生成 TARGET_* 环境变量
  • 不保留 secrets_env_map

Canonical MCP 工具

工具 说明
secrets_entry_find 从 desktop 已解锁本地 vault 搜索对象,支持 query / folder / type
secrets_entry_get 读取单条本地对象,并返回当前 secrets 的真实值
secrets_entry_add 在本地 vault 创建对象,可选附带初始 secrets
secrets_entry_update 更新本地对象的 folder / type / name / metadata
secrets_entry_delete 将本地对象标记为删除
secrets_entry_restore 恢复本地已删除对象
secrets_secret_add 向已有本地对象新增 secret
secrets_secret_update 更新本地 secret 名称、类型或内容
secrets_secret_delete 删除单个本地 secret
secrets_secret_history 查看单个本地 secret 的历史版本
secrets_secret_rollback 将单个本地 secret 回滚到指定版本
target_exec 用本地对象的 metadata 和 secrets 生成 TARGET_* 环境变量并执行本地命令

AI 客户端配置

桌面端会自动把本地 daemon 写入以下配置:

  • ~/.cursor/mcp.json
  • ~/.claude/mcp.json

写入示例:

{
  "mcpServers": {
    "secrets": {
      "url": "http://127.0.0.1:9515/mcp"
    }
  }
}

数据模型

当前 v3 已切到零知识同步模型

  • 服务端保存 vault_objectsvault_object_revisions
  • desktop 本地保存 vault_objectsvault_object_historypending_changessync_state
  • 搜索、详情、reveal、history 主要在本地已解锁 vault 上完成
  • 服务端负责 auth/device/sync/*,不再承担明文搜索与明文 reveal

主要表:

  • users
  • oauth_accounts
  • devices
  • device_login_tokens
  • auth_events
  • vault_objects
  • vault_object_revisions

字段职责:

位置 字段 说明
vault_objects object_id 同步对象标识
vault_objects object_kind 当前对象类别,当前主要为 cipher
vault_objects revision 服务端对象版本
vault_objects ciphertext 密文对象载荷
vault_objects content_hash 密文摘要
vault_objects deleted_at 对象级删除标记
vault_object_revisions revision / ciphertext 服务端对象历史版本

认证与事件

当前登录流为 Google Desktop OAuth

  • 桌面端使用系统浏览器拉起 Google 授权
  • API 服务端负责发起 OAuth、处理 callback、校验 Google userinfo
  • desktop 通过创建一次性 login session 并轮询状态获取 device token
  • 登录与设备活动写入 auth_events

项目结构

Cargo.toml
apps/
  api/                  # 远端 JSON API
  desktop/src-tauri/    # Tauri 桌面端
crates/
  application/          # v3 应用服务
  client-integrations/  # Cursor / Claude Code mcp.json 注入
  crypto/               # 通用加密辅助
  desktop-daemon/       # 本地 MCP daemon
  device-auth/          # Desktop OAuth / device token 辅助
  domain/               # 领域模型
  infrastructure-db/    # PostgreSQL 连接与迁移
deploy/
  .env.example
  secrets-mcp.service
  postgres-tls-hardening.md
scripts/
  release-check.sh
  setup-gitea-actions.sh

CI/CDGitea Actions

当前以 workspace 级检查为主,见 [.gitea/workflows/secrets.yml](.gitea/workflows/secrets.yml)

提交前建议直接运行:

./scripts/release-check.sh

详见 AGENTS.md(发版规则、代码规范)。

Description
Secrets management project
Readme 4.9 MiB
2026-04-13 08:54:22 +08:00
Languages
Rust 70.7%
HTML 25.7%
Shell 1.7%
Python 1.6%
JavaScript 0.3%