Skip to main content

sensitive_diagnostics/
sensitive_diagnostics.rs

1// =============================================================================
2//        #######
3//     ###       ###     F: sensitive_diagnostics.rs
4//    ##   ## ##   ##    P: AppCore-Runtime
5//         ## ##
6//                       C: unknown by dnettoRaw
7//    ##   ## ##   ##    U: working-tree by dnettoRaw
8//      ###########      S: 1.0.2-rc
9// =============================================================================
10
11//! Explicit sensitive output uses only an encrypted DNT sink.
12//!
13//! Set `APPCORE_LOG_DEMO_KEY_HEX` to a 64-character hexadecimal key before
14//! running it. Real deployments obtain key material from their explicit
15//! secret-management boundary instead of environment variables.
16
17use appcore_contracts::ApplicationId;
18use appcore_dnt::{KeyId, SecretKey, StaticDntKeyProvider};
19use appcore_log::{
20    LogDispatcher, LogPolicy, SensitiveDntSink, SensitiveDntSinkConfig, Sensitivity,
21};
22use std::sync::Arc;
23
24fn main() -> Result<(), appcore_log::LogError> {
25    let key_id = KeyId::new("example-log-key").map_err(|_| appcore_log::LogError::Encryption)?;
26
27    let provider =
28        StaticDntKeyProvider::new().with_key(key_id.clone(), SecretKey::new(demo_key()?));
29
30    // The sink bounds the encrypted snapshot by both bytes and event count.
31    let sink = SensitiveDntSink::new(
32        SensitiveDntSinkConfig {
33            path: std::env::temp_dir().join("appcore-sensitive-log.dnt"),
34            application_id: ApplicationId::new("example-log")
35                .map_err(|_| appcore_log::LogError::Encryption)?,
36            key_id,
37            max_bytes: 4096,
38            max_events: 8,
39            retention: 2,
40        },
41        provider,
42    )?;
43
44    // Sensitive mode must be explicit and has no console or JSONL fallback.
45    let mut policy = LogPolicy::default();
46    policy.sensitivity = Sensitivity::Sensitive;
47
48    let log = LogDispatcher::new(policy, vec![Arc::new(sink)]);
49
50    log.event(0, "security").verbosity(2).error("diagnostic");
51
52    Ok(())
53}
54
55fn demo_key() -> Result<[u8; 32], appcore_log::LogError> {
56    let value =
57        std::env::var("APPCORE_LOG_DEMO_KEY_HEX").map_err(|_| appcore_log::LogError::Encryption)?;
58    if value.len() != 64 || !value.is_ascii() {
59        return Err(appcore_log::LogError::Encryption);
60    }
61    let mut key = [0_u8; 32];
62    for (index, byte) in key.iter_mut().enumerate() {
63        let offset = index.saturating_mul(2);
64        *byte = u8::from_str_radix(&value[offset..offset + 2], 16)
65            .map_err(|_| appcore_log::LogError::Encryption)?;
66    }
67    Ok(key)
68}