test(credentials): 登记 B-01 生产验收

This commit is contained in:
2026-09-09 09:58:17 +08:00
parent 22c15fc65d
commit 43d7106cff
5 changed files with 246 additions and 1 deletions
+87
View File
@@ -1023,6 +1023,93 @@ mod tests {
assert!(broker.resolve(&Scope::Provider, &id).unwrap().is_none());
}
#[test]
fn b01_domain_matrix_never_exposes_or_cross_resolves_secrets() {
let temp = tempfile::tempdir().unwrap();
let file = temp.path().join("credentials.v1");
let mut broker = CredentialBroker::new(file.clone());
broker.unlock(password()).unwrap();
let domains = [
("provider", Scope::Provider),
("plugin", Scope::Plugin("reviewer".into())),
("mcp", Scope::Mcp("calendar".into())),
("sync", Scope::Sync("server-account".into())),
];
let mut records = Vec::new();
for (label, scope) in &domains {
for index in 0..3 {
let id = CredentialId {
scope: scope.clone(),
id: format!("b01-{label}-{index}"),
};
let secret = format!("b01-planted-{label}-{index}-value").into_bytes();
broker.put(&id, Zeroizing::new(secret.clone())).unwrap();
records.push((id, secret));
}
}
let callers = domains
.iter()
.map(|(_, scope)| scope.clone())
.collect::<Vec<_>>();
let mut public_errors = Vec::new();
for (id, secret) in &records {
for caller in &callers {
if caller == &id.scope {
let resolved = broker.resolve(caller, id).unwrap().unwrap();
assert!(resolved.as_slice() == secret, "same-domain secret mismatch");
} else {
let error = broker.resolve(caller, id).unwrap_err();
assert_eq!(error, "CREDENTIAL_SCOPE_DENIED");
public_errors.push(error);
}
}
let wrong_owner = match &id.scope {
Scope::Plugin(_) => Some(Scope::Plugin("another-plugin".into())),
Scope::Mcp(_) => Some(Scope::Mcp("another-mcp".into())),
Scope::Sync(_) => Some(Scope::Sync("another-sync-account".into())),
Scope::Provider => None,
};
if let Some(wrong_owner) = wrong_owner {
let error = broker.resolve(&wrong_owner, id).unwrap_err();
assert_eq!(error, "CREDENTIAL_SCOPE_DENIED");
public_errors.push(error);
}
}
assert_eq!(records.len(), 12);
assert_eq!(public_errors.len(), 45);
assert_eq!(broker.list().unwrap().len(), 12);
let public_status = serde_json::to_vec(&serde_json::json!({
"locked": broker.is_locked(),
"credentials": broker.list().unwrap(),
"errors": public_errors,
}))
.unwrap();
let vault = tempfile::tempdir().unwrap();
let mut workspace = crate::workspace::Workspace::open(vault.path()).unwrap();
workspace
.write("note.md", "", b"safe note", "local")
.unwrap();
let binding = workspace
.sync_bind_empty("https://sync.example", "remote", "account")
.unwrap();
let job = workspace.sync_next(&binding.id).unwrap().unwrap();
let sync_payload =
serde_json::to_vec(&workspace.sync_commit_payload(&job).unwrap()).unwrap();
let encrypted = fs::read(&file).unwrap();
for (_, secret) in &records {
for exposed in [&encrypted, &public_status, &sync_payload] {
assert!(
!exposed.windows(secret.len()).any(|window| window == secret),
"secret appeared outside the scoped resolver"
);
}
}
broker.lock();
assert!(records.iter().all(|(id, _)| broker
.resolve(&id.scope, id)
.is_err_and(|error| error == "CREDENTIALS_LOCKED")));
}
#[test]
fn corrupt_store_is_not_recreated() {
let temp = tempfile::tempdir().unwrap();
let path = temp.path().join("credentials.v1");
+14
View File
@@ -101,6 +101,20 @@ fn real_core_credential_api_uses_host_stronghold_without_plaintext_response() {
"credential API did not succeed"
);
assert!(!response.contains("fixture-credential-via-host-pipe"));
let status_session = core
.request_session("/api/credentials/fixture-provider")
.unwrap();
let mut socket = std::net::TcpStream::connect(endpoint).unwrap();
socket
.set_read_timeout(Some(std::time::Duration::from_secs(30)))
.unwrap();
write!(socket, "GET /api/credentials/fixture-provider HTTP/1.1\r\nHost: {endpoint}\r\nAuthorization: {}\r\nX-Core-Generation: {}\r\nConnection: close\r\n\r\n", status_session.authorization.as_str(), status_session.generation).unwrap();
let mut status_response = String::new();
socket.read_to_string(&mut status_response).unwrap();
assert!(status_response.starts_with("HTTP/1.1 200"));
assert!(status_response.contains("\"credential_id\":\"fixture-provider\""));
assert!(status_response.contains("\"configured\":true"));
assert!(!status_response.contains("fixture-credential-via-host-pipe"));
let id = CredentialId {
scope: Scope::Provider,
id: "fixture-provider".into(),