feat: vault core/CLI/workbench, vaultd token path, filetree view-state cleanup

Land password-vault dedicated workbench and mnote-vault-core/CLI, agent token
read path design, vault transport split, and retire obsolete filetree smokes.
Ignore local vault reimport scripts that trip secret scanners.
This commit is contained in:
Agent Board
2026-07-24 11:36:06 +08:00
parent b798f628ee
commit bc6f8488ee
41 changed files with 13072 additions and 2316 deletions
+55
View File
@@ -813,6 +813,17 @@ impl ControlPlaneStore for SqliteControlPlaneStore {
)
.optional()?
.ok_or_else(|| ControlPlaneError::Unauthorized("账号或密码错误".to_string()))?;
// 登录成功后对齐同用户全部 password_* identity 的哈希。
// 避免仅更新邮箱 identity 后,用户名登录仍用旧密码(liaibo 线上漂移过)。
let now = now_text();
let _ = conn.execute(
"UPDATE auth_identities
SET password_hash = ?1, updated_at = ?2
WHERE user_id = ?3
AND provider IN ('password_username', 'password_email')
AND password_hash != ?1",
params![expected_hash, now, user.id],
)?;
drop(conn);
let session = self.create_session(CreateSessionInput {
@@ -4869,6 +4880,50 @@ mod tests {
.is_none());
}
#[test]
fn authenticate_password_syncs_sibling_password_identity_hashes() {
let store = store();
let current_password = ["current", "secret"].join("-");
let stale_password = ["stale", "secret"].join("-");
create_password_identity(&store, "dana", "dana@example.com", &current_password);
// 模拟仅邮箱 identity 被改密、用户名 identity 仍是旧哈希的漂移。
{
let conn = store.lock_conn().expect("lock");
conn.execute(
"UPDATE auth_identities
SET password_hash = ?1
WHERE provider = 'password_username' AND provider_subject = 'dana'",
params![password_hash_v1(&stale_password)],
)
.expect("stale username hash");
}
store
.authenticate_password(AuthenticatePasswordInput {
account: "dana@example.com".to_string(),
password: current_password.clone(),
session_id: None,
token_hash: session_token_hash("dana-email-repair"),
user_agent: None,
ip_hash: None,
expires_at: None,
})
.expect("email login should still work");
store
.authenticate_password(AuthenticatePasswordInput {
account: "dana".to_string(),
password: current_password,
session_id: None,
token_hash: session_token_hash("dana-username-after-sync"),
user_agent: None,
ip_hash: None,
expires_at: None,
})
.expect("username login should work after sibling hash sync");
}
#[test]
fn ai_tool_events_append_and_list() {
let store = store();
+55
View File
@@ -1337,6 +1337,17 @@ impl ControlPlaneStore for TursoControlPlaneStore {
)
.optional()?
.ok_or_else(|| ControlPlaneError::Unauthorized("账号或密码错误".to_string()))?;
// 登录成功后对齐同用户全部 password_* identity 的哈希。
// 避免仅更新邮箱 identity 后,用户名登录仍用旧密码(liaibo 线上漂移过)。
let now = now_text();
let _ = conn.execute(
"UPDATE auth_identities
SET password_hash = ?1, updated_at = ?2
WHERE user_id = ?3
AND provider IN ('password_username', 'password_email')
AND password_hash != ?1",
params![expected_hash, now, user.id],
)?;
drop(conn);
let session = self.create_session(CreateSessionInput {
@@ -5235,6 +5246,50 @@ mod tests {
.is_none());
}
#[test]
fn authenticate_password_syncs_sibling_password_identity_hashes() {
let store = store();
let current_password = ["current", "secret"].join("-");
let stale_password = ["stale", "secret"].join("-");
create_password_identity(&store, "dana", "dana@example.com", &current_password);
// 模拟仅邮箱 identity 被改密、用户名 identity 仍是旧哈希的漂移。
{
let conn = store.lock_conn().expect("lock");
conn.execute(
"UPDATE auth_identities
SET password_hash = ?1
WHERE provider = 'password_username' AND provider_subject = 'dana'",
params![password_hash_v1(&stale_password)],
)
.expect("stale username hash");
}
store
.authenticate_password(AuthenticatePasswordInput {
account: "dana@example.com".to_string(),
password: current_password.clone(),
session_id: None,
token_hash: session_token_hash("dana-email-repair"),
user_agent: None,
ip_hash: None,
expires_at: None,
})
.expect("email login should still work");
store
.authenticate_password(AuthenticatePasswordInput {
account: "dana".to_string(),
password: current_password,
session_id: None,
token_hash: session_token_hash("dana-username-after-sync"),
user_agent: None,
ip_hash: None,
expires_at: None,
})
.expect("username login should work after sibling hash sync");
}
// --- Fault injection tests ---
#[test]