use assert_cmd::Command;
use predicates::str::contains;
fn tsafe() -> Command {
Command::cargo_bin("tsafe").unwrap()
}
#[test]
fn explain_lists_topics_without_topic_arg() {
tsafe()
.arg("explain")
.assert()
.success()
.stdout(contains("exec"))
.stdout(contains("exec-security"))
.stdout(contains("namespaces"))
.stdout(contains("pull"))
.stdout(contains("pull-auth"))
.stdout(contains("pull-reliability"));
}
#[test]
fn explain_exec_prints_workflow() {
tsafe()
.args(["explain", "exec"])
.assert()
.success()
.stdout(contains("dry-run"))
.stdout(contains("whole vault"))
.stdout(contains("stripped"))
.stdout(contains("abort the spawn"))
.stdout(contains("--"));
}
#[cfg_attr(
not(all(feature = "cloud-pull-aws", feature = "cloud-pull-gcp")),
ignore = "requires cloud-pull-aws and cloud-pull-gcp features"
)]
#[test]
fn explain_pull_prints_sources() {
tsafe()
.args(["explain", "pull"])
.assert()
.success()
.stdout(contains("local-first runtime authority"))
.stdout(contains("Cloud providers are read-only"))
.stdout(contains("sources — secrets are synced in"))
.stdout(contains("Nothing is written back to the cloud"))
.stdout(contains("tsafe exec scopes them to one process"))
.stdout(contains("aws-pull"))
.stdout(contains("gcp-pull"))
.stdout(contains("ssm-pull"))
.stdout(contains("kv-pull"))
.stdout(contains(".tsafe.yml"));
}
#[test]
fn explain_agent_prints_temporary_local_session_boundary() {
tsafe()
.args(["explain", "agent"])
.assert()
.success()
.stdout(contains("starts a session (TTL"))
.stdout(contains("agent socket"))
.stdout(contains("without typing the master"))
.stdout(contains("tsafe agent lock"));
}
#[cfg_attr(
not(all(
feature = "cloud-pull-aws",
feature = "cloud-pull-gcp",
feature = "cloud-pull-vault"
)),
ignore = "requires cloud-pull-aws, cloud-pull-gcp, and cloud-pull-vault features"
)]
#[test]
fn explain_pull_auth_prints_provider_credentials() {
tsafe()
.args(["explain", "pull-auth"])
.assert()
.success()
.stdout(contains("AWS_ACCESS_KEY_ID"))
.stdout(contains("GOOGLE_CLOUD_PROJECT"))
.stdout(contains("AZURE_TENANT_ID"))
.stdout(contains("VAULT_TOKEN"));
}
#[test]
fn explain_pull_reliability_prints_error_modes() {
tsafe()
.args(["explain", "pull-reliability"])
.assert()
.success()
.stdout(contains("--on-error fail-all"))
.stdout(contains("--on-error skip-failed"))
.stdout(contains("HTTP 429"));
}
#[test]
fn explain_contracts_prints_manifest_shape() {
tsafe()
.args(["explain", "contracts"])
.assert()
.success()
.stdout(contains("allowed_secrets"))
.stdout(contains("allowed_targets"))
.stdout(contains("trust_level"))
.stdout(contains("inherit"))
.stdout(contains("deny_dangerous_env"))
.stdout(contains("redact_output"))
.stdout(contains("cannot widen"));
}
#[test]
fn explain_vault_recovery_prints_recovery_paths() {
tsafe()
.args(["explain", "vault-recovery"])
.assert()
.success()
.stdout(contains("biometric"))
.stdout(contains("TSAFE_PASSWORD"));
}
#[test]
fn explain_unknown_topic_fails() {
tsafe().args(["explain", "nope"]).assert().failure();
}