stackless-core 0.1.7

Definition model, state store, and lifecycle engine for stackless
Documentation
//! Golden tests for the definition layer, anchored on the ยง1 schema
//! reference (the atto dogfood) parsed verbatim.

// Test helpers panic by design; the workspace denies apply to shipped code.
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]

use stackless_core::def::{self, DefError, Namespace, Node, StackDef};
use stackless_core::fault::{Fault, codes};

/// The substrate names the binary registers; core takes them as input.
const KNOWN: &[&str] = &["local", "render", "vercel"];

fn fixture(name: &str) -> String {
    let path = format!("{}/tests/fixtures/{name}", env!("CARGO_MANIFEST_DIR"));
    std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("read {path}: {err}"))
}

fn parse_valid(name: &str) -> def::StackDef {
    let def = StackDef::parse(&fixture(name)).unwrap_or_else(|err| panic!("parse {name}: {err}"));
    def.validate_hosts(KNOWN)
        .unwrap_or_else(|err| panic!("validate {name}: {err}"));
    def
}

#[test]
fn atto_parses_to_the_documented_model() {
    let def = parse_valid("atto.toml");

    assert_eq!(def.stack.name.as_str(), "atto");
    let verify = def.stack.verify.as_ref().unwrap();
    assert_eq!(verify.run.as_deref(), Some("bun e2e/smoke.ts"));
    assert_eq!(verify.env["ATTO_STACKLESS"], "1");
    assert_eq!(verify.env["ATTO_E2E_WEB_ORIGIN"], "${services.web.origin}");
    assert_eq!(verify.env["ATTO_E2E_API_ORIGIN"], "${services.api.origin}");
    assert_eq!(verify.env["ATTO_E2E_TENANT_SLUG"], "${instance.name}");
    assert_eq!(
        verify.env["CLERK_SECRET_KEY"],
        "${integrations.clerk.secret_key}"
    );
    assert_eq!(
        verify.env["VITE_CLERK_PUBLISHABLE_KEY"],
        "${integrations.clerk.publishable_key}"
    );
    let render = def.stack.substrates["render"].as_table().unwrap();
    assert_eq!(render["region"].as_str().unwrap(), "oregon");
    assert_eq!(
        def.stack
            .projects
            .stripe
            .as_ref()
            .and_then(|stripe| stripe.project.as_deref()),
        Some("project_61UqVKJia4fs...")
    );

    assert_eq!(def.secrets.required, vec!["GITHUB_PACKAGES_TOKEN"]);
    let clerk = &def.integrations["clerk"];
    assert_eq!(clerk.provider, "clerk");
    let clerk_config = clerk.effective_config("local", KNOWN);
    assert_eq!(
        clerk_config["app_name"].as_str(),
        Some("${stack.name}-${instance.name}")
    );
    assert_eq!(clerk_config["credential_set"].as_str(), Some("development"));
    assert_eq!(clerk_config["organizations"].as_bool(), Some(true));

    let api = &def.services["api"];
    assert_eq!(api.source.repo, "https://github.com/haaku-co/atto-server");
    assert_eq!(api.source.reference, "main");
    assert_eq!(api.setup.as_deref(), Some("mise install"));
    assert_eq!(
        api.prepare.as_deref(),
        Some("just migrate-run && just seed")
    );
    assert!(api.secrets.is_empty());
    assert_eq!(
        api.env["CLERK_SECRET_KEY"],
        "${integrations.clerk.secret_key}"
    );
    assert_eq!(api.health.path, "/health");
    assert_eq!(api.health.status.get(), 200);
    assert_eq!(api.health.contains.as_deref(), Some("ok"));
    assert!(!api.root_origin);

    let web = &def.services["web"];
    assert!(web.root_origin);
    assert_eq!(web.health.contains.as_deref(), Some(r#"id="root""#));

    // Substrate env overlays the common env, overlay wins (ยง1).
    let api_render_env = api.effective_env("api", "render").unwrap();
    assert_eq!(api_render_env["SQLX_OFFLINE"], "true");
    assert_eq!(api_render_env["RUST_LOG"], "info");
    let api_local_env = api.effective_env("api", "local").unwrap();
    assert!(!api_local_env.contains_key("SQLX_OFFLINE"));
}

#[test]
fn minimal_stack_is_valid() {
    let def = parse_valid("minimal.toml");
    let graph = def::DependencyGraph::derive(&def).unwrap();
    assert_eq!(graph.startup_order(), &[Node::Service("web".into())]);
    assert!(graph.wiring().is_empty());
}

#[test]
fn atto_graph_orders_clerk_before_api_without_origin_cycles() {
    let def = parse_valid("atto.toml");
    let graph = def::DependencyGraph::derive(&def).unwrap();

    let order = graph.startup_order();
    let pos = |node: &Node| order.iter().position(|n| n == node).unwrap();
    // clerk before api/web: integration outputs are ordering edges.
    assert!(pos(&Node::Integration("clerk".into())) < pos(&Node::Service("api".into())));
    assert!(pos(&Node::Integration("clerk".into())) < pos(&Node::Service("web".into())));
    // api <-> web mutual origin references are wiring, not a cycle:
    // derive succeeded and both are in the order.
    assert_eq!(order.len(), 3);

    // Wiring records the origin edges (the future egress seam).
    let wiring = graph.wiring();
    assert!(wiring.contains(&(Node::Service("api".into()), Node::Service("web".into()))));
    assert!(wiring.contains(&(Node::Service("web".into()), Node::Service("api".into()))));
    assert!(wiring.contains(&(
        Node::Service("api".into()),
        Node::Integration("clerk".into())
    )));
    assert!(wiring.contains(&(
        Node::Service("web".into()),
        Node::Integration("clerk".into())
    )));
}

#[test]
fn atto_plan_orders_integration_before_services() {
    let def = parse_valid("atto.toml");
    let steps = def.plan().unwrap();
    let integration = steps
        .iter()
        .position(|step| step.id == "integration:clerk")
        .unwrap();
    let start_api = steps
        .iter()
        .position(|step| step.id == "start:api")
        .unwrap();
    assert!(integration < start_api);
}

#[test]
fn atto_validates_for_both_substrates() {
    let def = parse_valid("atto.toml");
    def.validate_for_substrate("local").unwrap();
    def.validate_for_substrate("render").unwrap();
}

#[test]
fn minimal_lacks_render_config() {
    let def = parse_valid("minimal.toml");
    def.validate_for_substrate("local").unwrap();
    let err = def.validate_for_substrate("render").unwrap_err();
    assert_eq!(err.code(), codes::DEF_SUBSTRATE_CONFIG_MISSING);
    assert!(!err.remediation().is_empty());
}

#[test]
fn api_env_resolves_against_a_namespace() {
    let def = parse_valid("atto.toml");
    let api = &def.services["api"];
    let mut namespace = Namespace {
        instance_name: stackless_core::types::DnsName::try_new("demo").unwrap(),
        ..Namespace::default()
    };
    namespace
        .service_origins
        .insert("web".into(), "http://web.demo.localhost:4444".into());
    namespace
        .service_origins
        .insert("api".into(), "http://api.demo.localhost:4444".into());

    let resolve = |value: &str| def::interp::resolve(value, &namespace, "test").unwrap();
    assert_eq!(
        resolve(&api.env["CORS_ALLOWED_ORIGINS"]),
        "http://web.demo.localhost:4444"
    );
    assert_eq!(resolve(&api.env["TENANT_SLUG"]), "demo");
    assert_eq!(resolve(&api.env["RUST_LOG"]), "info");
}

fn expect_invalid(name: &str, expected_code: &str) {
    let text = fixture(&format!("invalid/{name}"));
    let result = StackDef::parse(&text).and_then(|def| def.validate_hosts(KNOWN));
    let err = result.unwrap_err();
    assert_eq!(err.code(), expected_code, "fixture {name}: {err}");
    assert!(
        !err.remediation().is_empty(),
        "fixture {name}: empty remediation"
    );
}

#[test]
fn invalid_fixtures_produce_stable_codes() {
    expect_invalid("undeclared_reference.toml", codes::DEF_UNDECLARED_REFERENCE);
    expect_invalid("bad_name.toml", codes::DEF_NAME_INVALID);
    expect_invalid("depends_on.toml", codes::DEF_DEPENDS_ON_REJECTED);
    expect_invalid("unknown_key.toml", codes::DEF_UNKNOWN_KEY);
    expect_invalid("secret_not_required.toml", codes::DEF_SECRET_NOT_REQUIRED);
    expect_invalid("root_origin_conflict.toml", codes::DEF_ROOT_ORIGIN_CONFLICT);
    expect_invalid("reference_syntax.toml", codes::DEF_REFERENCE_SYNTAX);
}

#[test]
fn missing_health_is_a_schema_error() {
    let text = r#"
[stack]
name = "bad"
[services.web]
source = { repo = "https://example.invalid/web", ref = "main" }
[services.web.local]
run = "true"
"#;
    let err = StackDef::parse(text).unwrap_err();
    assert_eq!(err.code(), codes::DEF_PARSE_SCHEMA);
}

#[test]
fn toml_syntax_error_is_its_own_code() {
    let err = StackDef::parse("[stack\nname = ").unwrap_err();
    assert_eq!(err.code(), codes::DEF_PARSE_SYNTAX);
}

#[test]
fn unknown_top_level_section_is_rejected() {
    let text = r#"
[stack]
name = "bad"
[volumes]
x = 1
[services.web]
source = { repo = "https://example.invalid/web", ref = "main" }
health = { path = "/" }
[services.web.local]
run = "true"
"#;
    let err = StackDef::parse(text).unwrap_err();
    assert_eq!(err.code(), codes::DEF_PARSE_SCHEMA);
}

#[test]
fn datastores_section_is_rejected_on_fresh_parse() {
    let text = r#"
[stack]
name = "bad"
[datastores.db]
engine = "postgres"
version = "16"
[services.web]
source = { repo = "https://example.invalid/web", ref = "main" }
health = { path = "/" }
[services.web.local]
run = "true"
"#;
    let err = StackDef::parse(text).unwrap_err();
    assert_eq!(err.code(), codes::DEF_PARSE_SCHEMA);
}

#[test]
fn parse_snapshot_strips_legacy_datastores() {
    let text = r#"
[stack]
name = "legacy"
[stack.verify]
run = "true"
env = { DATABASE_URL = "${datastores.db.url}" }
[datastores.db]
engine = "postgres"
version = "16"
[services.web]
source = { repo = "https://example.invalid/web", ref = "main" }
health = { path = "/" }
env = { DATABASE_URL = "${datastores.db.url}", ORIGIN = "${services.web.origin}" }
[services.web.local]
run = "true"
"#;
    let def = StackDef::parse_snapshot(text).unwrap();
    def.validate_hosts(KNOWN).unwrap();
    assert_eq!(def.stack.name.as_str(), "legacy");
    assert!(def.legacy_datastores.contains("db"));
    assert!(def.services.contains_key("web"));
    assert_eq!(
        def.services["web"]
            .env
            .get("DATABASE_URL")
            .map(String::as_str),
        Some("${datastores.db.url}")
    );
    assert_eq!(
        def.services["web"].env.get("ORIGIN").map(String::as_str),
        Some("${services.web.origin}")
    );
    assert_eq!(
        def.stack
            .verify
            .as_ref()
            .and_then(|v| v.env.get("DATABASE_URL"))
            .map(String::as_str),
        Some("${datastores.db.url}")
    );
}

#[test]
fn errors_are_reportable() {
    let err = DefError::NoServices;
    let report = stackless_core::fault::Report::from_fault(&err);
    assert_eq!(report.code, codes::DEF_NO_SERVICES);
    assert!(!report.remediation.is_empty());
}