harness-codex 0.1.1

Codex harness integration for the SteadyMux local continuity router.
Documentation
// SPDX-License-Identifier: AGPL-3.0-or-later

#![forbid(unsafe_code)]

use std::fs;
use std::path::PathBuf;
use std::process::Command;
use tempfile::tempdir;

const BINARY: &str = env!("CARGO_BIN_EXE_codex-config-plan");

fn fixture_auth_command() -> PathBuf {
    std::env::current_exe().expect("current test executable")
}

fn preview_digest(
    root: &std::path::Path,
    config: &std::path::Path,
    port: &str,
    auth: &std::path::Path,
) -> String {
    let output = Command::new(BINARY)
        .env("CODEX_HOME", root)
        .arg("--config")
        .arg(config)
        .args(["--port", port, "--auth-command"])
        .arg(auth)
        .args(["--auth-arg", "CONTINUITY_ROUTER_TOKEN"])
        .output()
        .expect("run preview");
    assert!(output.status.success());
    let preview: serde_json::Value = serde_json::from_slice(&output.stdout).expect("preview JSON");
    preview["machine_plan"]["preview_digest"]
        .as_str()
        .expect("preview digest")
        .to_owned()
}

#[test]
fn preview_is_redacted_and_never_writes() {
    let root = tempdir().expect("temporary config root");
    let config = root.path().join("config.toml");
    let original = b"# isolated fixture\nmodel = \"native\"\n";
    fs::write(&config, original).expect("fixture config");
    let auth_command = fixture_auth_command();
    let output = Command::new(BINARY)
        .env("CODEX_HOME", root.path())
        .arg("--config")
        .arg(&config)
        .args(["--port", "49170", "--auth-command"])
        .arg(&auth_command)
        .args(["--auth-arg", "CONTINUITY_ROUTER_TOKEN"])
        .output()
        .expect("run config plan");
    assert!(output.status.success());
    let stdout = String::from_utf8(output.stdout).expect("UTF-8 output");
    assert!(stdout.contains("\"status\":\"preview\""));
    assert!(stdout.contains("[REDACTED_AUTH_COMMAND]"));
    assert!(!stdout.contains(auth_command.to_string_lossy().as_ref()));
    let preview: serde_json::Value = serde_json::from_str(&stdout).expect("preview JSON");
    let human_diff = preview["human_diff"].as_str().expect("human diff");
    assert!(human_diff.contains("- model = \"native\""));
    assert!(human_diff.contains("+ model = \"router-auto\""));
    assert_eq!(
        preview["machine_plan"]["operation"],
        "replace_routing_settings_and_append_provider"
    );
    assert_eq!(fs::read(&config).expect("unchanged config"), original);
    assert!(
        !root
            .path()
            .join("config.toml.continuity-router-backup")
            .exists()
    );
}

#[test]
fn apply_and_separate_restore_are_confirmation_gated() {
    let root = tempdir().expect("temporary config root");
    let config = root.path().join("config.toml");
    let original = b"# isolated fixture\nmodel = \"native\"\n";
    fs::write(&config, original).expect("fixture config");
    let auth_command = fixture_auth_command();
    let digest = preview_digest(root.path(), &config, "49171", &auth_command);

    let refused = Command::new(BINARY)
        .env("CODEX_HOME", root.path())
        .arg("--config")
        .arg(&config)
        .args(["--port", "49171", "--auth-command"])
        .arg(&auth_command)
        .args(["--auth-arg", "CONTINUITY_ROUTER_TOKEN", "--apply"])
        .output()
        .expect("run refused apply");
    assert!(!refused.status.success());
    assert_eq!(fs::read(&config).expect("unchanged config"), original);

    let applied = Command::new(BINARY)
        .env("CODEX_HOME", root.path())
        .arg("--config")
        .arg(&config)
        .args(["--port", "49171", "--auth-command"])
        .arg(&auth_command)
        .args([
            "--auth-arg",
            "CONTINUITY_ROUTER_TOKEN",
            "--apply",
            "--preview-digest",
            &digest,
            "--confirm",
            "APPLY_USER_CONFIG",
        ])
        .output()
        .expect("run confirmed apply");
    assert!(applied.status.success());
    assert_ne!(fs::read(&config).expect("installed config"), original);
    let installed: toml::Value =
        toml::from_str(&fs::read_to_string(&config).expect("installed config text"))
            .expect("installed TOML");
    assert_eq!(installed["web_search"].as_str(), Some("disabled"));
    let auth = &installed["model_providers"]["continuity_router"]["auth"];
    assert_eq!(
        auth["command"].as_str(),
        Some(auth_command.to_string_lossy().as_ref())
    );
    assert_eq!(
        auth["args"]
            .as_array()
            .expect("auth args")
            .iter()
            .map(toml::Value::as_str)
            .collect::<Vec<_>>(),
        vec![Some("CONTINUITY_ROUTER_TOKEN")]
    );

    let restored = Command::new(BINARY)
        .env("CODEX_HOME", root.path())
        .arg("--config")
        .arg(&config)
        .args(["--restore", "--confirm", "RESTORE_USER_CONFIG"])
        .output()
        .expect("run confirmed restore");
    assert!(restored.status.success());
    assert_eq!(fs::read(&config).expect("restored config"), original);
}

#[test]
fn apply_refuses_wrong_or_stale_preview_digest_without_writing() {
    let root = tempdir().expect("temporary config root");
    let config = root.path().join("config.toml");
    let original = b"model = \"native\"\n";
    fs::write(&config, original).expect("fixture config");
    let auth_command = fixture_auth_command();
    let output = Command::new(BINARY)
        .env("CODEX_HOME", root.path())
        .arg("--config")
        .arg(&config)
        .args(["--port", "49174", "--auth-command"])
        .arg(&auth_command)
        .args([
            "--auth-arg",
            "CONTINUITY_ROUTER_TOKEN",
            "--apply",
            "--preview-digest",
            "0000000000000000000000000000000000000000000000000000000000000000",
            "--confirm",
            "APPLY_USER_CONFIG",
        ])
        .output()
        .expect("run refused apply");
    assert!(!output.status.success());
    assert_eq!(fs::read(&config).expect("unchanged config"), original);
    assert!(
        !root
            .path()
            .join("config.toml.continuity-router-backup")
            .exists()
    );
}

#[test]
fn preview_can_bind_a_future_helper_but_apply_requires_it_to_exist() {
    let root = tempdir().expect("temporary config root");
    let config = root.path().join("config.toml");
    let original = b"model = \"native\"\n";
    fs::write(&config, original).expect("fixture config");
    let future_helper = root.path().join("future-auth-helper");
    let digest = preview_digest(root.path(), &config, "49175", &future_helper);
    let output = Command::new(BINARY)
        .env("CODEX_HOME", root.path())
        .arg("--config")
        .arg(&config)
        .args(["--port", "49175", "--auth-command"])
        .arg(&future_helper)
        .args([
            "--auth-arg",
            "CONTINUITY_ROUTER_TOKEN",
            "--apply",
            "--preview-digest",
            &digest,
            "--confirm",
            "APPLY_USER_CONFIG",
        ])
        .output()
        .expect("run unavailable-helper refusal");
    assert!(!output.status.success());
    assert_eq!(fs::read(&config).expect("unchanged config"), original);
    assert!(
        !root
            .path()
            .join("config.toml.continuity-router-backup")
            .exists()
    );
}

#[test]
fn project_config_target_is_refused_before_access() {
    let project = std::env::current_dir()
        .expect("current directory")
        .join(".codex/config.toml");
    let output = Command::new(BINARY)
        .arg("--config")
        .arg(&project)
        .args(["--port", "49172", "--auth-command"])
        .arg(fixture_auth_command())
        .args(["--auth-arg", "CONTINUITY_ROUTER_TOKEN"])
        .output()
        .expect("run project refusal");
    assert!(!output.status.success());
    assert!(
        String::from_utf8(output.stderr)
            .expect("UTF-8 error")
            .contains("project .codex/config.toml targets are prohibited")
    );
}

#[test]
fn absolute_target_outside_approved_user_config_root_is_refused() {
    let directory = tempdir().expect("temporary directory");
    let approved = directory.path().join("approved");
    let outside = directory.path().join("outside");
    fs::create_dir(&approved).expect("approved root");
    fs::create_dir(&outside).expect("outside root");
    let outside_config = outside.join("config.toml");
    let output = Command::new(BINARY)
        .env("CODEX_HOME", &approved)
        .arg("--config")
        .arg(&outside_config)
        .args(["--port", "49173", "--auth-command"])
        .arg(fixture_auth_command())
        .output()
        .expect("run containment refusal");
    assert!(!output.status.success());
    assert!(
        String::from_utf8(output.stderr)
            .expect("UTF-8 error")
            .contains("approved user config root")
    );
}