Skip to main content

lift_inspection_flow/
lift_inspection_flow.rs

1use ed25519_dalek::SigningKey;
2use immutable_trace::{
3    build_signed_record, AuditRecord, InMemoryAuditLedger, InMemoryOperationLog,
4    InMemoryRawDataStore, IngestService, IngestState,
5};
6
7fn main() {
8    let device_id = "lift-01";
9    let signing_key = SigningKey::from_bytes(&[1u8; 32]);
10    let verifying_key = signing_key.verifying_key();
11
12    let mut service = IngestService::new(
13        IngestState::default(),
14        InMemoryRawDataStore::default(),
15        InMemoryAuditLedger::default(),
16        InMemoryOperationLog::default(),
17    );
18    service.register_device(device_id, verifying_key);
19
20    let payloads = [
21        b"check=door,status=ok" as &[u8],
22        b"check=vibration,status=ok",
23        b"check=emergency_brake,status=ok",
24    ];
25
26    let mut prev_hash = AuditRecord::zero_hash();
27    let mut records = Vec::new();
28
29    for (index, payload) in payloads.iter().enumerate() {
30        let sequence = (index as u64) + 1;
31        let record = build_signed_record(
32            device_id,
33            sequence,
34            1_700_000_000_000 + sequence,
35            payload,
36            prev_hash,
37            format!("s3://bucket/{device_id}/inspection-{sequence}.bin"),
38            &signing_key,
39        );
40        prev_hash = record.hash();
41        records.push(record);
42    }
43
44    for record in &records {
45        service
46            .ingest(record.clone(), payloads[record.sequence as usize - 1])
47            .expect("ingest should succeed");
48    }
49
50    println!("Stored {} audit records", service.audit_ledger().records().len());
51
52    let tampered_payload = b"tampered";
53    let tampered_record = build_signed_record(
54        device_id,
55        4,
56        1_700_000_000_004,
57        tampered_payload,
58        prev_hash,
59        "s3://bucket/lift-01/inspection-4.bin",
60        &signing_key,
61    );
62    let mut tampered = tampered_record;
63    tampered.payload_hash[0] ^= 0x01;
64
65    let result = service.ingest(tampered, tampered_payload);
66    assert!(result.is_err(), "tampered record should be rejected");
67    println!("Tampered record rejected: {:?}", result.unwrap_err());
68
69    println!("Operation log entries: {}", service.operation_log().entries().len());
70    for entry in service.operation_log().entries() {
71        println!("  {:?} device={} seq={} msg={}", entry.decision, entry.device_id, entry.sequence, entry.message);
72    }
73}