tvc 0.7.0

CLI for Turnkey Verifiable Cloud
Documentation
use assert_cmd::cargo::cargo_bin_cmd;
use predicates::prelude::*;
use std::collections::HashMap;
use std::fs;
use tempfile::TempDir;
use turnkey_api_key_stamper::TurnkeyP256ApiKey;
use tvc::config::turnkey::{Config, KeyCurve, OrgConfig, StoredApiKey};

const ENV_ORG_ID: &str = "TVC_ORG_ID";
const ENV_API_KEY_PUBLIC: &str = "TVC_API_KEY_PUBLIC";
const ENV_API_KEY_PRIVATE: &str = "TVC_API_KEY_PRIVATE";
const LOCAL_API_BASE_URL: &str = "http://127.0.0.1:1";

fn app_status_cmd() -> assert_cmd::Command {
    let mut cmd = cargo_bin_cmd!("tvc");
    cmd.env_clear()
        .arg("app")
        .arg("status")
        .arg("--app-id")
        .arg("app_test");
    cmd
}

fn generated_api_key() -> (String, String) {
    let stamper = TurnkeyP256ApiKey::generate();
    (
        hex::encode(stamper.compressed_public_key()),
        hex::encode(stamper.private_key()),
    )
}

#[test]
fn env_auth_accepts_all_three_required_vars() {
    let (public_key, private_key) = generated_api_key();

    app_status_cmd()
        .env(ENV_ORG_ID, "org-env")
        .env(ENV_API_KEY_PUBLIC, public_key)
        .env(ENV_API_KEY_PRIVATE, private_key)
        .assert()
        .failure()
        .stderr(predicate::str::contains("failed to fetch app status"))
        .stderr(predicate::str::contains("partial env var auth").not())
        .stderr(predicate::str::contains("failed to load API key").not());
}

#[test]
fn env_auth_rejects_two_required_vars() {
    let (public_key, _) = generated_api_key();

    app_status_cmd()
        .env(ENV_ORG_ID, "org-env")
        .env(ENV_API_KEY_PUBLIC, public_key)
        .assert()
        .failure()
        .stderr(predicate::str::contains("partial env var auth"))
        .stderr(predicate::str::contains(ENV_API_KEY_PRIVATE));
}

#[test]
fn env_auth_rejects_one_required_var() {
    app_status_cmd()
        .env(ENV_ORG_ID, "org-env")
        .assert()
        .failure()
        .stderr(predicate::str::contains("partial env var auth"))
        .stderr(predicate::str::contains(ENV_API_KEY_PUBLIC))
        .stderr(predicate::str::contains(ENV_API_KEY_PRIVATE));
}

#[test]
fn auth_falls_back_to_disk_config_when_required_env_vars_are_unset() {
    let temp = TempDir::new().unwrap();
    let turnkey_dir = temp.path().join(".config").join("turnkey");
    let org_dir = turnkey_dir.join("orgs").join("test");
    let api_key_path = org_dir.join("api_key.json");
    let operator_key_path = org_dir.join("operator.json");
    fs::create_dir_all(&org_dir).unwrap();

    let (public_key, private_key) = generated_api_key();
    fs::write(
        &api_key_path,
        serde_json::to_string_pretty(&StoredApiKey {
            public_key,
            private_key,
            curve: KeyCurve::P256,
        })
        .unwrap(),
    )
    .unwrap();

    let config = Config {
        active_org: Some("test".to_string()),
        orgs: HashMap::from([(
            "test".to_string(),
            OrgConfig {
                id: "org-from-disk".to_string(),
                api_key_path,
                operator_key_path,
                api_base_url: LOCAL_API_BASE_URL.to_string(),
            },
        )]),
        last_created_app_id: HashMap::new(),
        last_operator_ids: HashMap::new(),
    };
    fs::write(
        turnkey_dir.join("tvc.config.toml"),
        toml::to_string_pretty(&config).unwrap(),
    )
    .unwrap();

    app_status_cmd()
        .env("HOME", temp.path())
        .assert()
        .failure()
        .stderr(predicate::str::contains("failed to fetch app status"))
        .stderr(predicate::str::contains("No active organization").not());
}