pub use zeph_config::{DurableBackend, DurableConfig, RetentionPolicy};
use crate::error::DurableError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EncryptionGate {
Enabled,
DisabledLocalWarn,
}
pub fn encryption_gate(
cfg: &DurableConfig,
shared_db: bool,
) -> Result<EncryptionGate, DurableError> {
if cfg.encrypt_payload {
return Ok(EncryptionGate::Enabled);
}
if cfg.backend != DurableBackend::Local {
return Err(DurableError::EncryptionRequired { context: "restate" });
}
if shared_db {
return Err(DurableError::EncryptionRequired {
context: "shared-database",
});
}
Ok(EncryptionGate::DisabledLocalWarn)
}
#[cfg(test)]
mod tests {
use super::*;
use std::assert_matches;
#[test]
fn encryption_gate_passes_when_aead_enabled() {
let cfg = DurableConfig::default();
assert!(cfg.encrypt_payload);
assert_eq!(
encryption_gate(&cfg, false).unwrap(),
EncryptionGate::Enabled
);
assert_eq!(
encryption_gate(&cfg, true).unwrap(),
EncryptionGate::Enabled
);
let restate = DurableConfig {
backend: DurableBackend::Restate,
..DurableConfig::default()
};
assert_eq!(
encryption_gate(&restate, true).unwrap(),
EncryptionGate::Enabled
);
}
#[test]
fn encryption_gate_warns_for_local_single_user_override() {
let cfg = DurableConfig {
encrypt_payload: false,
backend: DurableBackend::Local,
..DurableConfig::default()
};
assert_eq!(
encryption_gate(&cfg, false).unwrap(),
EncryptionGate::DisabledLocalWarn
);
}
#[test]
fn encryption_gate_rejects_disabled_aead_on_shared_or_restate() {
let local_shared = DurableConfig {
encrypt_payload: false,
backend: DurableBackend::Local,
..DurableConfig::default()
};
assert_matches!(
encryption_gate(&local_shared, true),
Err(DurableError::EncryptionRequired {
context: "shared-database"
})
);
let restate = DurableConfig {
encrypt_payload: false,
backend: DurableBackend::Restate,
..DurableConfig::default()
};
assert_matches!(
encryption_gate(&restate, false),
Err(DurableError::EncryptionRequired { context: "restate" })
);
}
}