elicitation_kani 0.8.3

Kani model-checking proofs for elicitation contract types
Documentation
//! Kani proofs for elicitation mechanism contracts.
//!
//! These proofs verify that elicitation methods (Survey, Affirm, etc.)
//! work correctly, independent of the data types being elicited.

use elicitation::I8Positive;

// ============================================================================
// Mechanism Contract Proofs
// ============================================================================

// Mechanism contracts prove that elicitation methods (Survey, Affirm, etc.)
// work correctly, independent of the data types being elicited.

/// Prove AffirmReturnsBoolean contract.
///
/// Affirm mechanism always returns a valid boolean (true or false).
#[kani::proof]
fn verify_affirm_returns_boolean() {
    use elicitation::Contract;
    use elicitation::verification::mechanisms::AffirmReturnsBoolean;

    let contract = AffirmReturnsBoolean;

    // Test with true
    let output_true = true;
    assert!(
        AffirmReturnsBoolean::requires(&output_true),
        "Affirm has no preconditions"
    );
    assert!(
        AffirmReturnsBoolean::ensures(&output_true, &output_true),
        "Affirm ensures true is valid"
    );
    assert!(contract.invariant(), "Affirm invariant holds");

    // Test with false
    let output_false = false;
    assert!(
        AffirmReturnsBoolean::ensures(&output_false, &output_false),
        "Affirm ensures false is valid"
    );

    // Prove for all possible booleans
    let any_bool: bool = kani::any();
    assert!(
        AffirmReturnsBoolean::ensures(&any_bool, &any_bool),
        "Affirm ensures any boolean is valid"
    );
}

/// Prove SurveyReturnsValidVariant contract properties.
///
/// Survey mechanism returns one of the declared enum variants.
/// The type system guarantees this, but we prove the contract explicitly.
#[kani::proof]
fn verify_survey_returns_valid_variant() {
    use elicitation::Contract;
    use elicitation::verification::mechanisms::SurveyReturnsValidVariant;

    // Test with bool (simplest enum-like type that implements required traits)
    let contract = SurveyReturnsValidVariant::<bool>::new();
    assert!(contract.invariant(), "Survey invariant holds");

    // Test with both boolean values
    let value_true = true;
    let value_false = false;

    assert!(
        SurveyReturnsValidVariant::<bool>::requires(&value_true),
        "Survey has no preconditions for true"
    );
    assert!(
        SurveyReturnsValidVariant::<bool>::ensures(&value_true, &value_true),
        "Survey ensures true is valid variant"
    );
    assert!(
        SurveyReturnsValidVariant::<bool>::ensures(&value_false, &value_false),
        "Survey ensures false is valid variant"
    );

    // Prove for any boolean
    let any_bool: bool = kani::any();
    assert!(
        SurveyReturnsValidVariant::<bool>::ensures(&any_bool, &any_bool),
        "Survey ensures any bool variant is valid"
    );
}

/// Prove composition: Mechanism + Type contracts both hold.
///
/// If Survey mechanism returns valid variant AND I8Positive contract holds,
/// then the entire elicitation is proven correct.
#[kani::proof]
fn verify_mechanism_type_composition() {
    // Prove: Survey(enum) + I8Positive(value) = Fully verified elicitation

    // Part 1: Type contract (already proven in verify_i8_positive)
    let value: i8 = kani::any();
    if let Ok(positive) = I8Positive::new(value) {
        let val: i8 = positive.get();
        assert!(val > 0, "Type contract holds");

        // Part 2: If this was returned by Survey, Survey contract also holds
        // (Survey contract is trivially satisfied by type system)

        // Composition: Both contracts proven ⟹ Entire elicitation proven
        assert!(
            val > 0,
            "Composed verification: type + mechanism both proven"
        );
    }
}

/// Prove Select mechanism returns one of declared options.
///
/// Select (formerly Choice) ensures returned value is from valid option set.
#[kani::proof]
fn verify_select_returns_valid_option() {
    // Define simple enum implementing Select pattern
    #[derive(Debug, Clone, Copy, PartialEq)]
    enum Color {
        Red,
        Green,
        Blue,
    }

    // Prove that any Color value is one of the three variants
    let any_color = if kani::any() {
        if kani::any() {
            Color::Red
        } else {
            Color::Green
        }
    } else {
        Color::Blue
    };

    // Type system guarantees only these variants exist
    let is_valid = any_color == Color::Red || any_color == Color::Green || any_color == Color::Blue;
    assert!(is_valid, "Select returns valid option");
}

/// Prove elicitation mechanisms preserve trenchcoat pattern.
///
/// Even when eliciting through mechanisms (Survey/Affirm/Select),
/// the trenchcoat pattern holds: wrap → validate → unwrap.
#[kani::proof]
fn verify_mechanism_preserves_trenchcoat() {
    let value: i8 = kani::any();

    // Simulates: Survey elicits i8 → wraps in I8Positive → unwraps
    if let Ok(positive) = I8Positive::new(value) {
        let unwrapped: i8 = positive.into_inner();

        // Mechanism contract: Survey returns valid variant (satisfied by type system)
        // Type contract: I8Positive invariant holds
        // Trenchcoat: wrap/unwrap preserves value
        assert!(
            unwrapped == value && unwrapped > 0,
            "Mechanism + trenchcoat composition proven"
        );
    }
}

// ============================================================================
// URL Contract Proofs