//! Integration tests for `tsafe doctor`.
use std::fs;
use std::path::{Path, PathBuf};
use assert_cmd::Command;
use chrono::{Duration, Utc};
use predicates::prelude::PredicateBooleanExt;
use predicates::str::contains;
use serde_json::Value;
use tempfile::tempdir;
const PROFILE: &str = "doctorit";
fn tsafe() -> Command {
Command::cargo_bin("tsafe").unwrap()
}
fn unique_profile(label: &str) -> String {
format!(
"doctorit-{label}-{}",
Utc::now().timestamp_nanos_opt().unwrap()
)
}
fn run_in_vault_dir_for_profile(dir: &Path, profile: &str) -> Command {
let mut cmd = tsafe();
cmd.args(["--profile", profile])
.current_dir(dir)
.env("TSAFE_VAULT_DIR", dir)
.env_remove("TSAFE_PROFILE");
cmd
}
fn run_in_vault_dir(dir: &Path) -> Command {
run_in_vault_dir_for_profile(dir, PROFILE)
}
fn doctor_cmd_for_profile(dir: &Path, profile: &str) -> Command {
let mut cmd = run_in_vault_dir_for_profile(dir, profile);
cmd.arg("doctor")
.env_remove("TSAFE_PASSWORD")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
}
fn doctor_json_cmd_for_profile(dir: &Path, profile: &str) -> Command {
let mut cmd = doctor_cmd_for_profile(dir, profile);
cmd.arg("--json");
cmd
}
fn doctor_cmd(dir: &Path) -> Command {
doctor_cmd_for_profile(dir, PROFILE)
}
fn doctor_json_cmd(dir: &Path) -> Command {
doctor_json_cmd_for_profile(dir, PROFILE)
}
fn vault_path(dir: &Path) -> PathBuf {
dir.join(format!("{PROFILE}.vault"))
}
fn snapshot_profile_path(dir: &Path) -> PathBuf {
dir.join("snapshots").join(PROFILE)
}
fn init_vault(dir: &Path) {
init_vault_for_profile(dir, PROFILE);
}
fn init_vault_for_profile(dir: &Path, profile: &str) {
run_in_vault_dir_for_profile(dir, profile)
.arg("init")
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
}
fn set_secret_for_profile(dir: &Path, profile: &str, key: &str, value: &str) {
run_in_vault_dir_for_profile(dir, profile)
.args(["set", key, value])
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
}
fn run_stdout_stderr(mut cmd: Command) -> (bool, String, String) {
let output = cmd.output().unwrap();
(
output.status.success(),
String::from_utf8_lossy(&output.stdout).into_owned(),
String::from_utf8_lossy(&output.stderr).into_owned(),
)
}
fn run_exit_stdout_stderr(mut cmd: Command) -> (i32, String, String) {
let output = cmd.output().unwrap();
(
output.status.code().unwrap_or(-1),
String::from_utf8_lossy(&output.stdout).into_owned(),
String::from_utf8_lossy(&output.stderr).into_owned(),
)
}
fn help_stdout(mut cmd: Command) -> String {
let output = cmd.output().unwrap();
assert!(
output.status.success(),
"help command failed:\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8_lossy(&output.stdout).into_owned()
}
fn disable_biometric_best_effort(dir: &Path, profile: &str) {
let _ = run_in_vault_dir_for_profile(dir, profile)
.args(["biometric", "disable"])
.assert();
}
fn set_secret(dir: &Path, key: &str, value: &str) {
run_in_vault_dir(dir)
.args(["set", key, value])
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
}
fn set_rotation_policy(dir: &Path, key: &str, rotate_every: &str) {
run_in_vault_dir(dir)
.args(["policy", "set", key, "--rotate-every", rotate_every])
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
}
fn mutate_vault_json(dir: &Path, mutate: impl FnOnce(&mut Value)) {
let path = vault_path(dir);
let mut json: Value = serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
mutate(&mut json);
fs::write(path, serde_json::to_string_pretty(&json).unwrap()).unwrap();
}
#[test]
fn doctor_healthy_vault_exits_zero_and_mentions_quick_unlock_note() {
let dir = tempdir().unwrap();
init_vault(dir.path());
set_secret(dir.path(), "TEST_KEY", "value");
doctor_cmd(dir.path())
.assert()
.success()
.stdout(contains("vault:"))
.stdout(contains("quick unlock: not configured"))
.stdout(contains("tsafe biometric enable"))
.stdout(contains("quick unlock: enabled").not())
.stdout(contains("OS credential store").not())
.stdout(contains("macOS storage tier:").not())
.stdout(contains("exec: preview injectable names with"))
.stdout(contains("vault is healthy"));
}
#[test]
fn doctor_json_healthy_vault_reports_machine_readable_summary() {
let dir = tempdir().unwrap();
init_vault(dir.path());
set_secret(dir.path(), "TEST_KEY", "value");
let (code, stdout, stderr) = run_exit_stdout_stderr(doctor_json_cmd(dir.path()));
assert_eq!(code, 0, "stderr:\n{stderr}\nstdout:\n{stdout}");
let json: Value = serde_json::from_str(&stdout).unwrap();
assert_eq!(json["profile"], PROFILE);
assert_eq!(json["status"], "healthy");
assert_eq!(json["exit_code"], 0);
assert_eq!(json["summary"]["warning_count"], 0);
assert_eq!(json["summary"]["critical_count"], 0);
assert_eq!(json["summary"]["secret_count"], 1);
}
#[test]
fn doctor_missing_vault_reports_actionable_failure_text() {
let dir = tempdir().unwrap();
let (code, stdout, stderr) = run_exit_stdout_stderr(doctor_cmd(dir.path()));
assert_eq!(code, 2, "stderr:\n{stderr}\nstdout:\n{stdout}");
assert!(stdout.contains(&format!("vault not found for profile '{PROFILE}'")));
assert!(stdout.contains(&format!("run: tsafe --profile {PROFILE} init")));
assert!(stderr.contains("issue(s) found"));
}
#[test]
fn doctor_json_missing_vault_reports_critical_status_and_exit_two() {
let dir = tempdir().unwrap();
let (code, stdout, stderr) = run_exit_stdout_stderr(doctor_json_cmd(dir.path()));
assert_eq!(code, 2, "stderr:\n{stderr}\nstdout:\n{stdout}");
let json: Value = serde_json::from_str(&stdout).unwrap();
assert_eq!(json["status"], "critical");
assert_eq!(json["exit_code"], 2);
assert_eq!(json["summary"]["critical_count"], 1);
assert_eq!(json["summary"]["warning_count"], 0);
assert!(
json["checks"]
.as_array()
.unwrap()
.iter()
.any(|check| { check["code"] == "vault.file" && check["status"] == "critical" }),
"expected vault.file critical check in JSON:\n{stdout}"
);
}
#[test]
fn doctor_ci_password_warning_is_nonzero_and_calls_out_removal() {
let dir = tempdir().unwrap();
init_vault(dir.path());
set_secret(dir.path(), "TEST_KEY", "value");
let (code, stdout, stderr) = run_exit_stdout_stderr({
let mut cmd = run_in_vault_dir(dir.path());
cmd.arg("doctor")
.env("TSAFE_PASSWORD", "test-pw")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
});
assert_eq!(code, 1, "stderr:\n{stderr}\nstdout:\n{stdout}");
assert!(stdout.contains("TSAFE_PASSWORD: REMOVE after CI"));
assert!(stderr.contains("issue(s) found"));
}
#[test]
fn doctor_json_warning_exit_reports_warning_status() {
let dir = tempdir().unwrap();
init_vault(dir.path());
set_secret(dir.path(), "TEST_KEY", "value");
let (code, stdout, stderr) = run_exit_stdout_stderr({
let mut cmd = doctor_json_cmd(dir.path());
cmd.env("TSAFE_PASSWORD", "test-pw");
cmd
});
assert_eq!(code, 1, "stderr:\n{stderr}\nstdout:\n{stdout}");
let json: Value = serde_json::from_str(&stdout).unwrap();
assert_eq!(json["status"], "warning");
assert_eq!(json["exit_code"], 1);
assert_eq!(json["summary"]["warning_count"], 1);
assert_eq!(json["summary"]["critical_count"], 0);
assert!(
json["checks"]
.as_array()
.unwrap()
.iter()
.any(|check| { check["code"] == "env.TSAFE_PASSWORD" && check["status"] == "warning" }),
"expected TSAFE_PASSWORD warning in JSON:\n{stdout}"
);
}
#[test]
fn doctor_snapshot_listing_warning_exits_nonzero() {
let dir = tempdir().unwrap();
init_vault(dir.path());
set_secret(dir.path(), "TEST_KEY", "value");
let snapshot_path = snapshot_profile_path(dir.path());
if snapshot_path.exists() {
fs::remove_dir_all(&snapshot_path).unwrap();
}
fs::create_dir_all(snapshot_path.parent().unwrap()).unwrap();
fs::write(&snapshot_path, b"not-a-directory").unwrap();
let (code, stdout, stderr) = run_exit_stdout_stderr(doctor_cmd(dir.path()));
assert_eq!(code, 2, "stderr:\n{stderr}\nstdout:\n{stdout}");
assert!(stdout.contains("snapshots: could not list"));
assert!(stderr.contains("issue(s) found"));
}
#[test]
fn doctor_help_includes_json_flag_and_multiline_examples() {
let stdout = help_stdout({
let mut cmd = tsafe();
cmd.args(["doctor", "--help"]).env_remove("TSAFE_PROFILE");
cmd
});
assert!(stdout.contains(" --json"));
assert!(stdout.contains("Emit machine-readable JSON and use health exit codes"));
assert!(stdout.contains(
"Examples:\n tsafe doctor\n tsafe doctor --json\n tsafe --profile prod doctor"
));
assert!(!stdout.contains("Example: tsafe doctor Example:"));
}
#[test]
fn json_help_is_scoped_to_doctor_only() {
let root_help = help_stdout({
let mut cmd = tsafe();
cmd.arg("--help").env_remove("TSAFE_PROFILE");
cmd
});
assert!(!root_help.contains("--json"));
let doctor_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["doctor", "--help"]).env_remove("TSAFE_PROFILE");
cmd
});
assert!(doctor_help.contains(" --json"));
let list_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["list", "--help"]).env_remove("TSAFE_PROFILE");
cmd
});
assert!(!list_help.contains("--json"));
}
#[test]
fn recent_json_help_surfaces_render_examples_multiline() {
let audit_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["audit", "--help"]).env_remove("TSAFE_PROFILE");
cmd
});
assert!(audit_help.contains(
"Examples:\n tsafe audit\n tsafe audit --limit 100\n tsafe audit --explain\n tsafe audit --explain --json\n tsafe audit --cell-id doom-cell-001"
));
assert!(!audit_help.contains("Example: tsafe audit Example:"));
let rotate_due_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["rotate-due", "--help"])
.env_remove("TSAFE_PROFILE");
cmd
});
assert!(rotate_due_help.contains(
"Examples:\n tsafe rotate-due\n tsafe rotate-due --json\n tsafe rotate-due --fail # for scripts: non-zero if overdue"
));
assert!(!rotate_due_help.contains("Example: tsafe rotate-due Example:"));
let build_info_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["build-info", "--help"])
.env_remove("TSAFE_PROFILE");
cmd
});
assert!(build_info_help.contains("Examples:\n tsafe build-info\n tsafe build-info --json"));
assert!(!build_info_help.contains("Example: tsafe build-info Example:"));
}
#[test]
fn config_exec_and_audit_export_help_render_examples_multiline() {
let config_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["config", "--help"]).env_remove("TSAFE_PROFILE");
cmd
});
assert!(config_help.contains(
"Examples:\n tsafe config show\n tsafe config set-backup-vault main\n tsafe config set-backup-vault default\n tsafe config set-backup-vault off\n tsafe config set-exec-mode hardened\n tsafe config set-exec-redact-output on\n tsafe config add-exec-extra-strip OPENAI_API_KEY"
));
assert!(!config_help.contains("Example: tsafe config show Example:"));
let exec_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["exec", "--help"]).env_remove("TSAFE_PROFILE");
cmd
});
assert!(exec_help.contains(
"Examples:\n tsafe exec -- dotnet run\n tsafe exec -- docker-compose up\n tsafe exec --ns cds-adf -- python pipeline.py\n tsafe exec --dry-run\n tsafe exec --plan -- npm start\n tsafe exec --require API_KEY,DB_URL -- npm test\n tsafe exec --no-inherit -- node index.js\n tsafe exec --only PATH,HOME -- python script.py\n tsafe exec --minimal -- pytest\n tsafe exec --mode hardened -- npm test\n tsafe exec --keys OPENAI_API_KEY,DB_URL -- npm test\n tsafe exec --env MY_API_KEY=VAULT_API_KEY -- npm test\n tsafe exec --preset minimal -- npm test\n tsafe exec --timeout 30 -- npm test\n tsafe exec --redact-output -- npm test\n tsafe exec --contract deploy -- terraform apply\n tsafe exec --contract ci-tests --dry-run"
));
assert!(!exec_help.contains("Example: tsafe exec -- dotnet run Example:"));
let audit_export_help = help_stdout({
let mut cmd = tsafe();
cmd.args(["audit-export", "--help"])
.env_remove("TSAFE_PROFILE");
cmd
});
assert!(audit_export_help.contains(
"Examples:\n tsafe audit-export --format json --output audit.jsonl\n tsafe audit-export --format splunk"
));
assert!(!audit_export_help
.contains("Example: tsafe audit-export --format json --output audit.jsonl Example:"));
}
#[test]
fn doctor_rotation_due_warning_reports_overdue_secret() {
let dir = tempdir().unwrap();
init_vault(dir.path());
set_secret(dir.path(), "DB_PW", "secret");
set_rotation_policy(dir.path(), "DB_PW", "30d");
let overdue = (Utc::now() - Duration::days(45)).to_rfc3339();
mutate_vault_json(dir.path(), |json| {
json["secrets"]["DB_PW"]["updated_at"] = Value::String(overdue);
});
doctor_cmd(dir.path())
.assert()
.failure()
.stdout(contains("1 key(s) overdue for rotation"))
.stdout(contains("DB_PW").not())
.stderr(contains("issue(s) found"));
}
#[test]
fn biometric_status_not_configured_reports_enable_guidance_without_tier_claim() {
let dir = tempdir().unwrap();
let profile = unique_profile("status");
init_vault_for_profile(dir.path(), &profile);
let (ok, stdout, stderr) = run_stdout_stderr({
let mut cmd = run_in_vault_dir_for_profile(dir.path(), &profile);
cmd.args(["biometric", "status"])
.env_remove("TSAFE_PASSWORD")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
});
assert!(ok, "biometric status should succeed:\nstderr:\n{stderr}");
assert!(
stdout.contains("Biometric/keyring unlock is not configured"),
"stdout did not report the not-configured state:\n{stdout}"
);
assert!(
stdout.contains("Run tsafe biometric enable to enable."),
"stdout did not include the enable guidance:\n{stdout}"
);
assert!(
!stdout.contains("macOS storage tier:"),
"status should not claim a storage tier before quick unlock is configured:\n{stdout}"
);
}
#[test]
fn biometric_and_doctor_enabled_path_reports_storage_honestly() {
let dir = tempdir().unwrap();
let profile = unique_profile("enabled");
init_vault_for_profile(dir.path(), &profile);
set_secret_for_profile(dir.path(), &profile, "TEST_KEY", "value");
disable_biometric_best_effort(dir.path(), &profile);
run_in_vault_dir_for_profile(dir.path(), &profile)
.args(["biometric", "enable"])
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
let (status_ok, status_stdout, status_stderr) = run_stdout_stderr({
let mut cmd = run_in_vault_dir_for_profile(dir.path(), &profile);
cmd.args(["biometric", "status"])
.env_remove("TSAFE_PASSWORD")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
});
assert!(
status_ok,
"biometric status should succeed after enable:\nstderr:\n{status_stderr}"
);
assert!(
status_stdout.contains(&format!(
"Biometric/keyring unlock is enabled for '{profile}'"
)),
"status output did not report quick unlock as enabled:\n{status_stdout}"
);
assert!(
!status_stdout.contains("Run tsafe biometric enable to enable."),
"enabled status should not still print the setup guidance:\n{status_stdout}"
);
let (doctor_ok, doctor_stdout, doctor_stderr) =
run_stdout_stderr(doctor_cmd_for_profile(dir.path(), &profile));
assert!(
doctor_ok,
"doctor should stay healthy after enabling quick unlock:\nstderr:\n{doctor_stderr}\nstdout:\n{doctor_stdout}"
);
assert!(
doctor_stdout.contains("vault is healthy"),
"doctor output did not report a healthy vault:\n{doctor_stdout}"
);
assert!(
!doctor_stdout.contains("quick unlock: not configured"),
"doctor should not claim quick unlock is unconfigured after enable:\n{doctor_stdout}"
);
assert!(
!doctor_stdout.contains("tsafe biometric enable"),
"doctor should not keep the enable guidance after quick unlock is configured:\n{doctor_stdout}"
);
if cfg!(target_os = "macos") {
let storage_note = status_stdout
.lines()
.find(|line| line.contains("macOS storage tier:"))
.unwrap_or("");
assert!(
!storage_note.is_empty(),
"macOS biometric status should report the storage tier when configured:\n{status_stdout}"
);
assert!(
doctor_stdout.contains(storage_note.trim()),
"macOS doctor output should repeat the same storage-tier note as biometric status:\nstatus:\n{status_stdout}\ndoctor:\n{doctor_stdout}"
);
assert!(
doctor_stdout.contains("quick unlock: enabled"),
"doctor output did not report quick unlock as enabled:\n{doctor_stdout}"
);
assert!(
!doctor_stdout.contains("quick unlock: enabled (OS credential store)"),
"macOS doctor output should not fall back to the generic OS credential store wording when a storage-tier note is available:\n{doctor_stdout}"
);
} else {
assert!(
!status_stdout.contains("macOS storage tier:"),
"non-macOS status should not claim a macOS storage tier:\n{status_stdout}"
);
assert!(
doctor_stdout.contains("quick unlock: enabled (OS credential store)"),
"non-macOS doctor output should report the generic OS credential store wording:\n{doctor_stdout}"
);
assert!(
!status_stdout.contains("OS credential store"),
"non-macOS biometric status should stay at the narrower enabled/not-configured claim rather than inventing a storage-tier line:\n{status_stdout}"
);
assert!(
!doctor_stdout.contains("macOS storage tier:"),
"non-macOS doctor output should not claim a macOS storage tier:\n{doctor_stdout}"
);
}
disable_biometric_best_effort(dir.path(), &profile);
}
#[test]
fn biometric_enable_allows_later_cli_retrieve_without_tsafe_password_and_disable_revokes_it() {
let dir = tempdir().unwrap();
let profile = unique_profile("quick-unlock");
init_vault_for_profile(dir.path(), &profile);
set_secret_for_profile(dir.path(), &profile, "TEST_KEY", "value");
disable_biometric_best_effort(dir.path(), &profile);
run_in_vault_dir_for_profile(dir.path(), &profile)
.args(["biometric", "enable"])
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
let (get_ok, get_stdout, get_stderr) = run_stdout_stderr({
let mut cmd = run_in_vault_dir_for_profile(dir.path(), &profile);
cmd.args(["get", "TEST_KEY"])
.env_remove("TSAFE_PASSWORD")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
});
assert!(
get_ok,
"get should succeed via stored quick unlock without TSAFE_PASSWORD:\nstderr:\n{get_stderr}\nstdout:\n{get_stdout}"
);
assert_eq!(get_stdout.trim(), "value");
let (disable_ok, disable_stdout, disable_stderr) = run_stdout_stderr({
let mut cmd = run_in_vault_dir_for_profile(dir.path(), &profile);
cmd.args(["biometric", "disable"])
.env_remove("TSAFE_PASSWORD")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
});
assert!(
disable_ok,
"biometric disable should succeed via stored quick unlock without TSAFE_PASSWORD:\nstderr:\n{disable_stderr}\nstdout:\n{disable_stdout}"
);
assert!(
disable_stdout.contains("Biometric/keyring unlock disabled"),
"disable output did not confirm removal of quick unlock:\n{disable_stdout}"
);
let (after_disable_ok, after_disable_stdout, after_disable_stderr) = run_stdout_stderr({
let mut cmd = run_in_vault_dir_for_profile(dir.path(), &profile);
cmd.args(["get", "TEST_KEY"])
.env_remove("TSAFE_PASSWORD")
.env_remove("TSAFE_NEW_MASTER_PASSWORD");
cmd
});
assert!(
!after_disable_ok,
"get should fail after quick unlock is removed:\nstdout:\n{after_disable_stdout}\nstderr:\n{after_disable_stderr}"
);
}
/// Security regression test: `tsafe doctor --json` must NOT leak vault key names.
///
/// The code field used to be `secret.expiry.{key}` / `secret.rotation.{key}` /
/// `exec.risky_env_name.{key}`, which allowed operators to enumerate vault keys
/// from JSON output without the vault password.
#[test]
fn doctor_json_does_not_leak_vault_key_names_in_output() {
let dir = tempdir().unwrap();
let profile = unique_profile("keyleak");
init_vault_for_profile(dir.path(), &profile);
// Store a secret with a clearly identifiable name.
set_secret_for_profile(dir.path(), &profile, "SENSITIVE_SECRET_KEY", "s3cr3t");
// Give it a rotation policy so a rotation check is triggered.
run_in_vault_dir_for_profile(dir.path(), &profile)
.args([
"policy",
"set",
"SENSITIVE_SECRET_KEY",
"--rotate-every",
"30d",
])
.env("TSAFE_PASSWORD", "test-pw")
.assert()
.success();
// Back-date updated_at so the rotation is overdue.
let overdue_ts = (Utc::now() - Duration::days(60)).to_rfc3339();
{
let vault_file = dir.path().join(format!("{profile}.vault"));
let mut json: Value =
serde_json::from_str(&fs::read_to_string(&vault_file).unwrap()).unwrap();
json["secrets"]["SENSITIVE_SECRET_KEY"]["updated_at"] = Value::String(overdue_ts);
fs::write(vault_file, serde_json::to_string_pretty(&json).unwrap()).unwrap();
}
// Run doctor --json; ignore exit code (will be non-zero because of overdue rotation).
let (_, stdout, _) = run_exit_stdout_stderr(doctor_json_cmd_for_profile(dir.path(), &profile));
// The raw key name must not appear anywhere in the JSON output.
assert!(
!stdout.contains("SENSITIVE_SECRET_KEY"),
"doctor --json must not leak vault key names in output, but found 'SENSITIVE_SECRET_KEY':\n{stdout}"
);
// Sanity: the output must still be valid JSON with recognisable check codes.
let json: Value = serde_json::from_str(&stdout)
.unwrap_or_else(|e| panic!("doctor --json produced invalid JSON: {e}\nraw:\n{stdout}"));
let codes: Vec<&str> = json["checks"]
.as_array()
.unwrap()
.iter()
.filter_map(|c| c["code"].as_str())
.collect();
// The rotation overdue check must use the redacted code, not the key-suffixed one.
assert!(
codes.contains(&"secret.rotation_overdue"),
"expected 'secret.rotation_overdue' check code; got: {codes:?}"
);
assert!(
!codes.iter().any(|c| c.contains("SENSITIVE_SECRET_KEY")),
"no check code must contain a raw vault key name; got: {codes:?}"
);
}