Release secrets-mcp 0.3.0: folder/type schema and MCP folder disambiguation
All checks were successful
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Successful in 3m39s
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Successful in 5s

- 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
This commit is contained in:
voson
2026-03-26 15:12:28 +08:00
parent f7afd7f819
commit 409fd78a35
21 changed files with 1108 additions and 558 deletions

View File

@@ -3,7 +3,7 @@ use sqlx::{PgPool, Postgres, Transaction};
use uuid::Uuid;
pub const ACTION_LOGIN: &str = "login";
pub const NAMESPACE_AUTH: &str = "auth";
pub const FOLDER_AUTH: &str = "auth";
fn login_detail(provider: &str, client_ip: Option<&str>, user_agent: Option<&str>) -> Value {
json!({
@@ -16,7 +16,7 @@ fn login_detail(provider: &str, client_ip: Option<&str>, user_agent: Option<&str
/// Write a login audit entry without requiring an explicit transaction.
pub async fn log_login(
pool: &PgPool,
kind: &str,
entry_type: &str,
provider: &str,
user_id: Uuid,
client_ip: Option<&str>,
@@ -24,22 +24,22 @@ pub async fn log_login(
) {
let detail = login_detail(provider, client_ip, user_agent);
let result: Result<_, sqlx::Error> = sqlx::query(
"INSERT INTO audit_log (user_id, action, namespace, kind, name, detail) \
"INSERT INTO audit_log (user_id, action, folder, type, name, detail) \
VALUES ($1, $2, $3, $4, $5, $6)",
)
.bind(user_id)
.bind(ACTION_LOGIN)
.bind(NAMESPACE_AUTH)
.bind(kind)
.bind(FOLDER_AUTH)
.bind(entry_type)
.bind(provider)
.bind(&detail)
.execute(pool)
.await;
if let Err(e) = result {
tracing::warn!(error = %e, kind, provider, "failed to write login audit log");
tracing::warn!(error = %e, entry_type, provider, "failed to write login audit log");
} else {
tracing::debug!(kind, provider, ?user_id, "login audit logged");
tracing::debug!(entry_type, provider, ?user_id, "login audit logged");
}
}
@@ -48,19 +48,19 @@ pub async fn log_tx(
tx: &mut Transaction<'_, Postgres>,
user_id: Option<Uuid>,
action: &str,
namespace: &str,
kind: &str,
folder: &str,
entry_type: &str,
name: &str,
detail: Value,
) {
let result: Result<_, sqlx::Error> = sqlx::query(
"INSERT INTO audit_log (user_id, action, namespace, kind, name, detail) \
"INSERT INTO audit_log (user_id, action, folder, type, name, detail) \
VALUES ($1, $2, $3, $4, $5, $6)",
)
.bind(user_id)
.bind(action)
.bind(namespace)
.bind(kind)
.bind(folder)
.bind(entry_type)
.bind(name)
.bind(&detail)
.execute(&mut **tx)
@@ -69,7 +69,7 @@ pub async fn log_tx(
if let Err(e) = result {
tracing::warn!(error = %e, "failed to write audit log");
} else {
tracing::debug!(action, namespace, kind, name, "audit logged");
tracing::debug!(action, folder, entry_type, name, "audit logged");
}
}