Skip to main content

edgesentry_rs/ingest/
policy.rs

1use ed25519_dalek::VerifyingKey;
2
3use crate::record::AuditRecord;
4use super::verify::{IngestError, IngestState};
5
6/// Enforces signature, sequence, and route identity integrity before persistence.
7///
8/// This is the P0 policy gate: every record must pass all checks here
9/// before it is allowed through to storage.
10#[derive(Default)]
11pub struct IntegrityPolicyGate {
12    state: IngestState,
13}
14
15impl IntegrityPolicyGate {
16    pub fn new() -> Self {
17        Self::default()
18    }
19
20    pub fn register_device(&mut self, device_id: impl Into<String>, key: VerifyingKey) {
21        self.state.register_device(device_id, key);
22    }
23
24    /// Run all integrity checks for `record`.
25    ///
26    /// Checks (in order):
27    /// 1. Route identity — `cert_identity` must match `record.device_id` when present.
28    /// 2. Signature — payload hash must be signed by the registered device key.
29    /// 3. Sequence — must be strictly monotonic and non-duplicate.
30    /// 4. Previous-record hash — must match the last accepted record's hash.
31    pub fn enforce(
32        &mut self,
33        record: &AuditRecord,
34        cert_identity: Option<&str>,
35    ) -> Result<(), IngestError> {
36        if let Some(identity) = cert_identity {
37            if identity != record.device_id {
38                return Err(IngestError::CertDeviceMismatch {
39                    cert_identity: identity.to_string(),
40                    device_id: record.device_id.clone(),
41                });
42            }
43        }
44
45        self.state.verify_and_accept(record)
46    }
47}
48