Skip to main content

aa_security/
redaction.rs

1//! Redaction primitive: the credential-scanner output attached to a governance
2//! event before it is forwarded or written to the audit log.
3
4use crate::scanner::CredentialFinding;
5
6/// Optional credential-redaction artefacts produced by a credential-scanner pass.
7///
8/// Populated when an enforcement layer ran the [`CredentialScanner`](crate::scanner::CredentialScanner)
9/// and produced at least one finding. Both fields default to empty / `None`,
10/// matching the legacy code path that constructs audit entries without scanner
11/// output. `Redaction::default()` carries no findings, so consumers can treat it
12/// as "scan was clean / not run" without special-casing.
13///
14/// ## Security invariant
15///
16/// Neither field stores the raw secret value. `credential_findings` holds only
17/// the [`CredentialKind`](crate::scanner::CredentialKind), byte offset, and the
18/// `[REDACTED:<kind>]` label (`CredentialFinding`'s `end` field is
19/// `#[serde(skip)]`). `redacted_payload` holds the sanitised payload returned by
20/// [`ScanResult::redact`](crate::scanner::ScanResult::redact) where every match
21/// has been replaced with its `[REDACTED:<kind>]` label.
22#[derive(Debug, Clone, PartialEq, Eq, Default)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct Redaction {
25    /// All credential / PII findings detected by the scanner. Empty when the
26    /// scanner found nothing.
27    pub credential_findings: Vec<CredentialFinding>,
28    /// The redacted version of the action payload (raw secret bytes replaced
29    /// with `[REDACTED:<kind>]` labels). `None` when no findings were produced.
30    pub redacted_payload: Option<String>,
31}