liminal-server 0.23.1

Standalone server for the liminal messaging bus
Documentation
//! Route pin (b) for R3b review row 11: no route rebinds a participant to a
//! lower or equal capability generation. The recovered-fate witness state
//! orders a participant's fates by that generation, so this is the route it
//! relies on.
//!
//! No pre-fix tree produces this red: attach has minted exactly the next
//! generation (`ops_attach.rs` `stored_attach_allocation`) and refused any
//! other presented generation at lookup throughout. A binding epoch has no
//! order of its own, and the pin shows why: the second
//! rebind names an earlier connection.

use std::error::Error;

use liminal_protocol::wire::{
    CommonStaleAuthorityEnvelope, ConnectionIncarnation, ServerValue, StaleAuthority,
};

use super::ProductionParticipantHandler;
use super::tests::{dispatch, open_disk_store_for_tests, test_participant_config};
use super::tests_receipts::{GEN_ONE, attach, attach_request, detach, enroll, generation};

#[test]
fn no_route_rebinds_to_a_lower_or_equal_generation() -> Result<(), Box<dyn Error>> {
    let home = tempfile::tempdir()?;
    let store = open_disk_store_for_tests(&home.path().join("durability"))?;
    let handler = ProductionParticipantHandler::new(store, test_participant_config())?;
    let conversation_id = 9051;
    let earlier_connection = ConnectionIncarnation::new(905, 1);
    let later_connection = ConnectionIncarnation::new(905, 2);

    let receipt = enroll(&handler, later_connection, conversation_id, [21; 16])?;
    let participant_id = receipt.participant_id();
    detach(
        &handler,
        later_connection,
        conversation_id,
        participant_id,
        GEN_ONE,
        [22; 16],
    )?;
    let first = attach(
        &handler,
        later_connection,
        attach_request(
            conversation_id,
            participant_id,
            GEN_ONE,
            receipt.attach_secret(),
            [23; 16],
        ),
    )?;
    detach(
        &handler,
        later_connection,
        conversation_id,
        participant_id,
        generation(2)?,
        [24; 16],
    )?;
    let second = attach(
        &handler,
        earlier_connection,
        attach_request(
            conversation_id,
            participant_id,
            generation(2)?,
            first.attach_secret(),
            [25; 16],
        ),
    )?;
    let (first_epoch, second_epoch) = (first.origin_binding_epoch(), second.origin_binding_epoch());
    assert_eq!(
        (
            first_epoch.capability_generation,
            second_epoch.capability_generation
        ),
        (generation(2)?, generation(3)?),
        "each rebind is at exactly the next generation"
    );
    assert!(
        second_epoch.connection_incarnation < first_epoch.connection_incarnation,
        "the second rebind is on a connection opened before the first's: {second_epoch:?} against \
         {first_epoch:?}"
    );

    detach(
        &handler,
        earlier_connection,
        conversation_id,
        participant_id,
        generation(3)?,
        [26; 16],
    )?;
    let current = generation(3)?;
    for (presented, token) in [(GEN_ONE, [27; 16]), (generation(2)?, [28; 16])] {
        let refused = dispatch(
            &handler,
            later_connection,
            attach_request(
                conversation_id,
                participant_id,
                presented,
                first.attach_secret(),
                token,
            ),
        )?;
        assert!(
            matches!(
                refused,
                ServerValue::StaleAuthority(StaleAuthority::Live {
                    request: CommonStaleAuthorityEnvelope::CredentialAttach(_),
                    current_generation,
                }) if current_generation == current
            ),
            "R3b review row 11: an attach presenting generation {presented:?} below the current \
             3 was not refused as stale: {refused:?}"
        );
    }
    Ok(())
}