Files
secrets/AGENTS.md
voson 409fd78a35
All checks were successful
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Successful in 3m39s
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Successful in 5s
Release secrets-mcp 0.3.0: folder/type schema and MCP folder disambiguation
- Rename namespace/kind to folder/type on entries, audit_log, and history tables;
  add notes. Unique key is (user_id, folder, name).
- Service layer and MCP tools support name-first lookup with optional folder when
  multiple entries share the same name.
- secrets_delete dry_run uses the same disambiguation as real deletes.
- Add scripts/migrate-v0.3.0.sql for manual DB migration. Refresh README and
  AGENTS.md.

Made-with: Cursor
2026-03-26 15:12:28 +08:00

8.9 KiB
Raw Permalink Blame History

Secrets MCP — AGENTS.md

本仓库为 MCP SaaSsecrets-core(业务与持久化)+ secrets-mcpStreamable HTTP MCP、Web、OAuth、API Key。对外入口见 crates/secrets-mcp

提交 / 推送硬规则(优先于下文)

每次提交和推送前必须执行以下检查,无论是否明确「发版」:

  1. 涉及 crates/**、根目录 Cargo.toml/Cargo.locksecrets-mcp 行为变更的提交,默认视为需要发版,除非明确说明「本次不发版」。
  2. 提交前检查 crates/secrets-mcp/Cargo.tomlversion,再查 taggit tag -l 'secrets-mcp-*'。若当前版本对应 tag 已存在且有代码变更,必须 bump 版本号cargo build 同步 Cargo.lock
  3. 提交前运行 ./scripts/release-check.sh(版本/tag + fmt + clippy --locked + test --locked)。若脚本不存在或不可用,至少运行 cargo fmt -- --check && cargo clippy --locked -- -D warnings && cargo test --locked

项目结构

secrets/
  Cargo.toml
  crates/
    secrets-core/       # db / crypto / models / audit / service
    secrets-mcp/        # rmcp tools、axum、OAuth、Dashboard
  scripts/
    release-check.sh
    setup-gitea-actions.sh
  .gitea/workflows/secrets.yml
  .vscode/tasks.json

数据库

  • 建议库名secrets-mcp(专用实例,与历史库名区分)。
  • 连接:环境变量 SECRETS_DATABASE_URL(本分支无本地配置文件路径)。
  • entries(含 user_id)、secretsentries_historysecrets_historyaudit_logusersoauth_accounts,首次连接 auto-migratesecrets-coremigrate)。
  • Web 会话:与上项 同一数据库 URLsecrets-mcp 启动时对 tower-sessions 的 PostgreSQL 存储 auto-migrate(会话表与业务表共存于该实例,无需第二套连接串)。

表结构(摘录)

entries (
  id          UUID PRIMARY KEY DEFAULT uuidv7(),
  user_id     UUID,                                -- 多租户NULL=遗留行;非空=归属用户
  folder      VARCHAR(128)  NOT NULL DEFAULT '',
  type        VARCHAR(64)   NOT NULL DEFAULT '',
  name        VARCHAR(256)  NOT NULL,
  notes       TEXT          NOT NULL DEFAULT '',
  tags        TEXT[]        NOT NULL DEFAULT '{}',
  metadata    JSONB         NOT NULL DEFAULT '{}',
  version     BIGINT        NOT NULL DEFAULT 1,
  created_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW()
)
-- 唯一UNIQUE(user_id, folder, name) WHERE user_id IS NOT NULL
--       UNIQUE(folder, name) WHERE user_id IS NULL单租户遗留
secrets (
  id          UUID PRIMARY KEY DEFAULT uuidv7(),
  entry_id    UUID         NOT NULL REFERENCES entries(id) ON DELETE CASCADE,
  field_name  VARCHAR(256) NOT NULL,
  encrypted   BYTEA        NOT NULL DEFAULT '\x',
  version     BIGINT       NOT NULL DEFAULT 1,
  created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  UNIQUE(entry_id, field_name)
)

users / oauth_accounts

users (
  id           UUID PRIMARY KEY DEFAULT uuidv7(),
  email        VARCHAR(256),
  name         VARCHAR(256) NOT NULL DEFAULT '',
  avatar_url   TEXT,
  key_salt     BYTEA,         -- PBKDF2 salt32B首次设置密码短语时写入
  key_check    BYTEA,         -- 派生密钥加密已知常量,用于验证密码短语
  key_params   JSONB,         -- 算法参数,如 {"alg":"pbkdf2-sha256","iterations":600000}
  api_key      TEXT UNIQUE,   -- MCP Bearer token当前实现为明文存储
  created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
)

oauth_accounts (
  id           UUID PRIMARY KEY DEFAULT uuidv7(),
  user_id      UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  provider     VARCHAR(32) NOT NULL,
  provider_id  VARCHAR(256) NOT NULL,
  email        VARCHAR(256),
  name         VARCHAR(256),
  avatar_url   TEXT,
  created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(provider, provider_id)
)
-- 另有唯一索引 UNIQUE(user_id, provider)(迁移中 idx_oauth_accounts_user_provider同一用户每种 provider 至多一条关联。

audit_log / history

与迁移脚本一致:audit_logentries_historysecrets_history 用于审计与时间旅行恢复;字段定义见 crates/secrets-core/src/db.rsmigrate SQL。audit_log 含可选 user_id(多租户下标识操作者;可空以兼容遗留数据)。audit_log 中普通业务事件使用 folder / type / name 对应 entry 坐标;登录类事件固定使用 folder='auth',此时 type/name 表示认证目标而非 entry 身份。

MCP 消歧AI 调用)

name 定位条目的工具(get / update / 单条 delete / history / rollback):若该用户下仅一条匹配则直接执行;若多条(同 name、不同 folder)则返回错误并提示补全 foldersecrets_deletedry_run=true 与真实删除使用相同消歧规则。

字段职责

字段 含义 示例
folder 隔离空间(参与唯一键) refining
type 软分类(不参与唯一键) server, service, key, person
name 标识名 gitea, aliyun
notes 非敏感说明 自由文本
tags 标签 ["aliyun","prod"]
metadata 明文描述 ipurlkey_ref
secrets.field_name 加密字段名(明文) token, ssh_key
secrets.encrypted 密文 AES-GCM

PEM 共享(key_ref

将共享 PEM 存为 type=key 的 entry其它记录在 metadata.key_ref 指向该 key 的 name。更新 key 记录后,引用方通过服务层解析合并逻辑即可使用新密钥(实现见 secrets_core::service)。

代码规范

  • 错误:业务层 anyhow::Result,避免生产路径 unwrap()
  • 异步:tokio + sqlx async。
  • SQLsqlx::query / query_as 参数绑定;动态 WHERE 仍须用占位符绑定。
  • 日志:运维用 tracing;面向用户的 Web 响应走 axum handler。tracing 字段风格:变量名即字段名时用简写(%var?varvar),否则用显式形式(field = %expr)。
  • 审计:写操作成功后尽量 audit::log_tx;失败可 warn,不掩盖主错误。
  • 加密:密钥由用户密码短语通过 PBKDF2-SHA256600k 次) 在客户端派生,服务端只存 key_salt/key_check/key_params不持有原始密钥。Web 客户端在浏览器本地完成加解密MCP 客户端通过 X-Encryption-Key 请求头传递密钥,服务端临时解密后返回明文。
  • MCPtools 参数与 JSON Schemaschemars)保持同步,鉴权以请求扩展中的用户上下文为准。

提交前检查

./scripts/release-check.sh

或手动:

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

发版前确认未重复 tag

grep '^version' crates/secrets-mcp/Cargo.toml
git tag -l 'secrets-mcp-*'

CI/CD

  • 触发:任意分支 push,且路径含 crates/**deploy/**、根目录 Cargo.tomlCargo.lock.gitea/workflows/**(见 .gitea/workflows/secrets.yml)。
  • 版本与 tag:从 crates/secrets-mcp/Cargo.toml 读版本;构建成功后打 secrets-mcp-<version>:若远端已存在同名 tagCI 会先删后于当前提交重建并推送(覆盖式发版)。
  • 质量与构建fmt / clippy --locked / test --lockedx86_64-unknown-linux-musl 发布构建 secrets-mcp
  • Release可选secrets.RELEASE_TOKENGitea PAT用于通过 API 创建或更新该 tag 的 Release非 draft、上传 tar.gz + .sha256;未配置则跳过 API Release仅 tag + 构建。
  • 部署(可选):仅 mainfeat/mcpmcp 分支在构建成功时跑 deploy-mcp;需 vars.DEPLOY_HOSTvars.DEPLOY_USERsecrets.DEPLOY_SSH_KEY。勿把 OAuth/DB 等写进 workflowdeploy/.env.example 在目标机配置。
  • Secrets 写法Actions secrets 须为原始值PEM、PAT 明文), base64否则 SSH/Release 会失败。在 CI 中保存 GOOGLE_CLIENT_SECRET、DB 密码。
  • 通知vars.WEBHOOK_URL(可选,飞书)。

环境变量secrets-mcp

变量 说明
SECRETS_DATABASE_URL 必填。PostgreSQL URL。
BASE_URL 对外基址OAuth 回调 ${BASE_URL}/auth/google/callback
SECRETS_MCP_BIND 监听地址,默认 127.0.0.1:9315(容器/远程直接暴露时需改为 0.0.0.0:9315)。
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET 可选;仅运行时配置。
RUST_LOG secrets_mcp=debug

SERVER_MASTER_KEY 已不再需要。新架构下密钥由用户密码短语在客户端派生,服务端不持有。