canic-host 0.70.6

Host-side build, install, deployment, and fleet-template library for Canic workspaces
Documentation
use super::super::*;

#[test]
fn role_artifact_source_round_trips_through_json() {
    let source = sample_role_artifact_source(RoleArtifactSourceKindV1::LocalWasmGz);

    assert_json_round_trip(&source);
    let encoded = serde_json::to_value(&source).expect("source should encode");
    assert_object_keys(
        &encoded,
        &[
            "role",
            "kind",
            "locator",
            "previous_receipt_kind",
            "previous_receipt_lineage_digest",
            "expected_wasm_sha256",
            "expected_wasm_gz_sha256",
            "expected_candid_sha256",
            "expected_canonical_embedded_config_sha256",
        ],
    );
}

#[test]
fn role_promotion_input_round_trips_through_json() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SealedWasm);

    assert_json_round_trip(&input);
    let encoded = serde_json::to_value(&input).expect("input should encode");
    assert_object_keys(
        &encoded,
        &[
            "role",
            "promotion_level",
            "source",
            "require_byte_identical_wasm",
            "require_target_embedded_config",
            "target_store_has_artifact",
        ],
    );
}

#[test]
fn role_promotion_policy_round_trips_through_json() {
    let policy = sample_role_promotion_policy();

    validate_role_promotion_policy(&policy).expect("policy should validate");
    assert_json_round_trip(&policy);
    let encoded = serde_json::to_value(&policy).expect("policy should encode");
    assert_object_keys(
        &encoded,
        &["role", "allowed_promotion_levels", "requirements"],
    );
}

#[test]
fn role_promotion_policy_validation_rejects_sealed_only_policy_with_source_build_allowed() {
    let mut policy = sample_role_promotion_policy();
    policy
        .allowed_promotion_levels
        .push(PromotionArtifactLevelV1::SourceBuild);

    let err = validate_role_promotion_policy(&policy)
        .expect_err("sealed-only policy cannot allow source build");

    std::assert_matches!(
        err,
        PromotionPolicyCheckError::DecisionMismatch {
            role,
            field: "sealed_bytes"
        } if role == "root"
    );
}

#[test]
fn promotion_policy_check_accepts_sealed_wasm_policy() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SealedWasm);
    let policy = sample_role_promotion_policy();

    let check = check_promotion_policy(PromotionPolicyCheckRequest {
        check_id: "promotion-policy-1".to_string(),
        inputs: vec![input],
        policies: vec![policy],
    })
    .expect("policy check should validate");

    assert_eq!(check.status, PromotionReadinessStatusV1::Ready);
    assert_eq!(check.roles.len(), 1);
    assert!(check.roles[0].policy_satisfied);
    assert!(
        check.roles[0]
            .requirements
            .contains(&PromotionPolicyRequirementV1::SealedBytes)
    );
    assert!(
        check.roles[0]
            .requirements
            .contains(&PromotionPolicyRequirementV1::ByteIdenticalWasm)
    );
    assert!(
        check.roles[0]
            .requirements
            .contains(&PromotionPolicyRequirementV1::TargetConfigDigest)
    );
    assert_json_round_trip(&check);
    let encoded = serde_json::to_value(&check).expect("policy check should encode");
    assert_object_keys(
        &encoded,
        &[
            "schema_version",
            "check_id",
            "promotion_policy_check_digest",
            "status",
            "roles",
            "blockers",
        ],
    );
    assert!(
        encoded["promotion_policy_check_digest"]
            .as_str()
            .is_some_and(|digest| digest.len() == 64)
    );
    let role = &encoded["roles"][0];
    assert_object_keys(
        role,
        &[
            "role",
            "requested_promotion_level",
            "allowed_promotion_levels",
            "requirements",
            "claims",
            "level_allowed",
            "policy_satisfied",
        ],
    );
}

#[test]
fn promotion_policy_check_blocks_source_build_when_sealed_bytes_are_required() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SourceBuild);
    let policy = sample_role_promotion_policy();

    let check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);

    assert_eq!(check.status, PromotionReadinessStatusV1::Blocked);
    assert!(!check.roles[0].policy_satisfied);
    assert!(check.blockers.iter().any(|finding| {
        finding.code == "promotion_policy_level_not_allowed"
            || finding.code == "promotion_policy_must_use_sealed_bytes"
    }));
    validate_promotion_policy_check(&check).expect("blocked policy check should validate");
}

#[test]
fn promotion_policy_check_distinguishes_byte_identity_from_sealed_bytes() {
    let mut input = sample_role_promotion_input(PromotionArtifactLevelV1::SourceBuild);
    input.require_byte_identical_wasm = true;
    let mut policy = sample_role_promotion_policy();
    policy.allowed_promotion_levels = vec![PromotionArtifactLevelV1::SourceBuild];
    policy.requirements = vec![PromotionPolicyRequirementV1::ByteIdenticalWasm];

    let check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);

    assert_eq!(check.status, PromotionReadinessStatusV1::Ready);
    assert!(check.roles[0].policy_satisfied);
    assert!(
        !check.roles[0]
            .requirements
            .contains(&PromotionPolicyRequirementV1::SealedBytes)
    );
    assert!(
        check.roles[0]
            .requirements
            .contains(&PromotionPolicyRequirementV1::ByteIdenticalWasm)
    );
}

#[test]
fn promotion_policy_check_blocks_missing_byte_identity_claim() {
    let mut input = sample_role_promotion_input(PromotionArtifactLevelV1::SourceBuild);
    input.require_byte_identical_wasm = false;
    let mut policy = sample_role_promotion_policy();
    policy.allowed_promotion_levels = vec![PromotionArtifactLevelV1::SourceBuild];
    policy.requirements = vec![PromotionPolicyRequirementV1::ByteIdenticalWasm];

    let check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);

    assert_eq!(check.status, PromotionReadinessStatusV1::Blocked);
    assert!(
        check
            .blockers
            .iter()
            .any(|finding| { finding.code == "promotion_policy_byte_identity_required" })
    );
}

#[test]
fn promotion_policy_check_blocks_duplicate_policy_roles_without_matching_input() {
    let mut duplicate_policy = sample_role_promotion_policy();
    duplicate_policy.role = "wasm_store".to_string();

    let check = promotion_policy_check_from_inputs(
        "promotion-policy-1",
        &[sample_role_promotion_input(
            PromotionArtifactLevelV1::SealedWasm,
        )],
        &[
            sample_role_promotion_policy(),
            duplicate_policy.clone(),
            duplicate_policy,
        ],
    );

    assert_eq!(check.status, PromotionReadinessStatusV1::Blocked);
    assert!(check.blockers.iter().any(|finding| {
        finding.code == "promotion_policy_duplicate"
            && finding.subject.as_deref() == Some("wasm_store")
    }));
    validate_promotion_policy_check(&check).expect("duplicate-policy blocker should validate");
}

#[test]
fn promotion_policy_check_text_reports_passive_summary() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SealedWasm);
    let policy = sample_role_promotion_policy();
    let check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);

    let text = promotion_policy_check_text(&check);

    assert!(text.contains("Promotion policy check"));
    assert!(text.contains("mode: passive"));
    assert!(text.contains("status: ready"));
    assert!(text.contains("check_id: promotion-policy-1"));
    assert!(text.contains("promotion_policy_check_digest:"));
    assert!(text.contains("policy_satisfied: 1"));
    assert!(text.contains("root SealedWasm: policy_satisfied=true"));
}

#[test]
fn promotion_policy_check_round_trips_through_json() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SealedWasm);
    let policy = sample_role_promotion_policy();
    let check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);

    assert_json_round_trip(&check);
    let encoded = serde_json::to_value(&check).expect("promotion policy check should encode");
    assert_object_keys(
        &encoded,
        &[
            "schema_version",
            "check_id",
            "promotion_policy_check_digest",
            "status",
            "roles",
            "blockers",
        ],
    );
    assert_eq!(encoded["check_id"], "promotion-policy-1");
    assert!(
        encoded["promotion_policy_check_digest"]
            .as_str()
            .is_some_and(|digest| digest.len() == 64)
    );
}

#[test]
fn promotion_policy_check_validation_rejects_stale_decision() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SealedWasm);
    let policy = sample_role_promotion_policy();
    let mut check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);
    check.roles[0].policy_satisfied = false;

    let err = validate_promotion_policy_check(&check).expect_err("stale decision should fail");

    std::assert_matches!(
        err,
        PromotionPolicyCheckError::DecisionMismatch {
            role,
            field: "policy_satisfied"
        } if role == "root"
    );
}

#[test]
fn promotion_policy_check_validation_rejects_stale_digest() {
    let input = sample_role_promotion_input(PromotionArtifactLevelV1::SealedWasm);
    let policy = sample_role_promotion_policy();
    let mut check = promotion_policy_check_from_inputs("promotion-policy-1", &[input], &[policy]);
    check.promotion_policy_check_digest = sample_sha256("9");

    let err = validate_promotion_policy_check(&check)
        .expect_err("stale promotion policy check digest should fail");

    std::assert_matches!(
        err,
        PromotionPolicyCheckError::LinkageMismatch {
            field: "promotion_policy_check_digest"
        }
    );
}