liminal-server 0.24.9

Standalone server for the liminal messaging bus
Documentation
use std::sync::OnceLock;

use liminal_protocol::wire::{BindingEpoch, ConnectionIncarnation, Generation};

use super::restore_checkpoint_history::{
    CheckpointHistoryNode, CheckpointHistoryRoot, HistoryCodecError, ROOT_ENCODED_BYTES,
};
use super::restore_checkpoint_history_key::{
    CheckpointHistoryKey, HistoryEntryKey, HistoryLineageKey, HistoryOccurrenceKey,
};

struct Fixture {
    keys: Vec<CheckpointHistoryKey>,
    entry: CheckpointHistoryNode,
    root: CheckpointHistoryRoot,
    encoded_entry: Vec<u8>,
}

fn fixture_entry_keys(epoch: BindingEpoch) -> Vec<CheckpointHistoryKey> {
    let entries = [
        HistoryEntryKey::FateOccurrence {
            participant_id: 2,
            binding_epoch: epoch,
        },
        HistoryEntryKey::RetiredIdentity { participant_id: 2 },
        HistoryEntryKey::EnrollmentReverse { token: [4; 16] },
        HistoryEntryKey::CommittedAdmission {
            token: [4; 16],
            participant_id: 2,
            fingerprint: [5; 32],
        },
        HistoryEntryKey::AttachProvenance {
            participant_id: 2,
            token: [4; 16],
        },
        HistoryEntryKey::AckSource { source_sequence: 6 },
        HistoryEntryKey::RecipientObligation {
            participant_id: 2,
            delivery_sequence: 7,
        },
        HistoryEntryKey::AckFrontier { participant_id: 2 },
        HistoryEntryKey::MarkerAckFrontier { participant_id: 2 },
        HistoryEntryKey::OutboxRetiredIdentity { participant_id: 2 },
        HistoryEntryKey::CursorFact {
            participant_index: 2,
            boundary: 8,
        },
        HistoryEntryKey::RetiredAdmission {
            token: [4; 16],
            participant_id: 2,
            fingerprint: [5; 32],
        },
    ];
    entries
        .into_iter()
        .map(|entry| CheckpointHistoryKey::new(9, entry))
        .collect()
}

static FIXTURE: OnceLock<Result<Fixture, HistoryCodecError>> = OnceLock::new();

fn fixture() -> Result<&'static Fixture, HistoryCodecError> {
    FIXTURE
        .get_or_init(|| {
            let generation = Generation::new(3).ok_or(HistoryCodecError::Generation)?;
            let epoch = BindingEpoch::new(ConnectionIncarnation::new(1, 2), generation);
            let mut keys = fixture_entry_keys(epoch);
            for occurrence in [
                HistoryOccurrenceKey::AttachedTerminal {
                    participant_id: 2,
                    terminal_delivery_sequence: 7,
                },
                HistoryOccurrenceKey::DetachedTerminal {
                    participant_id: 2,
                    terminal_delivery_sequence: 7,
                },
                HistoryOccurrenceKey::DiedTerminal {
                    participant_id: 2,
                    terminal_delivery_sequence: 7,
                },
                HistoryOccurrenceKey::ParticipantAck {
                    participant_id: 2,
                    through_sequence: 7,
                    source_sequence: 6,
                },
                HistoryOccurrenceKey::MarkerAck {
                    participant_id: 2,
                    marker_delivery_sequence: 7,
                    resulting_cursor: 8,
                    base_log_head: 6,
                    extension_sequence: 3,
                },
                HistoryOccurrenceKey::Leave {
                    participant_id: 2,
                    left_delivery_sequence: 7,
                },
                HistoryOccurrenceKey::RecoveredFate {
                    participant_id: 2,
                    binding_epoch: epoch,
                    resulting_floor: 8,
                },
            ] {
                keys.push(CheckpointHistoryKey::new(
                    9,
                    HistoryEntryKey::ObserverOccurrence(occurrence),
                ));
            }
            for lineage in [
                HistoryLineageKey::ParticipantCursor,
                HistoryLineageKey::ParticipantTerminal,
                HistoryLineageKey::BindingFateFloor,
            ] {
                keys.push(CheckpointHistoryKey::new(
                    9,
                    HistoryEntryKey::ObserverLineage {
                        participant_id: 2,
                        lineage,
                    },
                ));
            }
            let entry = CheckpointHistoryNode::entry(keys[3], vec![1, 2, 3, 4]);
            let encoded_entry = entry.encode_canonical()?;
            let root = CheckpointHistoryRoot::for_node(&entry)?;
            Ok(Fixture {
                keys,
                entry,
                root,
                encoded_entry,
            })
        })
        .as_ref()
        .map_err(|error| *error)
}

#[test]
fn every_history_key_keeps_its_full_typed_identity() -> Result<(), HistoryCodecError> {
    let image = fixture()?;
    assert_eq!(image.keys.len(), 22);
    let mut distinct = std::collections::BTreeSet::new();
    for key in &image.keys {
        let bytes = key.encode_canonical();
        assert_eq!(CheckpointHistoryKey::decode_canonical(&bytes, 9)?, *key);
        assert!(distinct.insert(bytes));
    }
    assert_eq!(distinct.len(), 22);
    Ok(())
}

#[test]
fn history_key_refuses_foreign_unknown_trailing_and_zero_generation()
-> Result<(), HistoryCodecError> {
    let image = fixture()?;
    let bytes = image.keys[0].encode_canonical();
    assert!(matches!(
        CheckpointHistoryKey::decode_canonical(&bytes, 10),
        Err(HistoryCodecError::Conversation {
            expected: 10,
            actual: 9
        })
    ));
    let mut unknown = bytes.clone();
    unknown[14] = 255;
    assert!(matches!(
        CheckpointHistoryKey::decode_canonical(&unknown, 9),
        Err(HistoryCodecError::Tag { .. })
    ));
    let mut trailing = bytes.clone();
    trailing.push(0);
    assert!(matches!(
        CheckpointHistoryKey::decode_canonical(&trailing, 9),
        Err(HistoryCodecError::Trailing)
    ));
    let mut zero_generation = bytes;
    let start = zero_generation.len() - 8;
    zero_generation[start..].fill(0);
    assert!(matches!(
        CheckpointHistoryKey::decode_canonical(&zero_generation, 9),
        Err(HistoryCodecError::Generation)
    ));
    Ok(())
}

#[test]
fn history_root_schema_has_exact_algorithm_width_and_conversation() -> Result<(), HistoryCodecError>
{
    let image = fixture()?;
    let bytes = image.root.encode_canonical();
    assert_eq!(bytes.len(), ROOT_ENCODED_BYTES);
    assert_eq!(ROOT_ENCODED_BYTES, 15 + blake3::OUT_LEN);
    assert_eq!(
        CheckpointHistoryRoot::decode_canonical(&bytes, 9)?,
        image.root
    );
    assert!(matches!(
        CheckpointHistoryRoot::decode_canonical(&bytes[..bytes.len() - 1], 9),
        Err(HistoryCodecError::Length)
    ));
    let mut foreign_algorithm = bytes;
    foreign_algorithm[6] = 2;
    assert!(matches!(
        CheckpointHistoryRoot::decode_canonical(&foreign_algorithm, 9),
        Err(HistoryCodecError::Algorithm(2))
    ));
    assert!(matches!(
        CheckpointHistoryRoot::decode_canonical(&bytes, 10),
        Err(HistoryCodecError::Conversation {
            expected: 10,
            actual: 9
        })
    ));
    Ok(())
}

#[test]
fn authenticated_history_node_rejects_content_and_key_association_damage()
-> Result<(), HistoryCodecError> {
    let image = fixture()?;
    assert_eq!(
        CheckpointHistoryNode::decode_canonical(&image.encoded_entry, image.root)?,
        image.entry
    );
    let mut damaged = image.encoded_entry.clone();
    let last = damaged.len() - 1;
    damaged[last] ^= 1;
    assert!(matches!(
        CheckpointHistoryNode::decode_canonical(&damaged, image.root),
        Err(HistoryCodecError::Integrity)
    ));
    assert_eq!(
        &image.root.routed_node_key()[..27],
        b"checkpoint/history/node/v2/"
    );
    Ok(())
}

#[test]
fn branch_children_and_depth_are_validated_before_publication() -> Result<(), HistoryCodecError> {
    let image = fixture()?;
    let empty = CheckpointHistoryRoot::empty(9);
    let branch = CheckpointHistoryNode::branch(9, 0, image.root, empty)?;
    let root = CheckpointHistoryRoot::for_node(&branch)?;
    assert_eq!(
        CheckpointHistoryNode::decode_canonical(&branch.encode_canonical()?, root)?,
        branch
    );
    assert!(matches!(
        CheckpointHistoryNode::branch(9, 256, image.root, empty),
        Err(HistoryCodecError::Depth(256))
    ));
    assert!(matches!(
        CheckpointHistoryNode::branch(9, 0, image.root, CheckpointHistoryRoot::empty(10)),
        Err(HistoryCodecError::Conversation {
            expected: 9,
            actual: 10
        })
    ));
    Ok(())
}