Skip to main content

InternalContext

Struct InternalContext 

Source
pub struct InternalContext(/* private fields */);
Expand description

Type-safe wrapper for internal-only error contexts.

§Trust Boundary Enforcement

This newtype ensures internal diagnostic data cannot be accidentally exposed externally. The Display implementation returns a redacted placeholder, not actual content, preventing misuse in external-facing code paths.

§Access Patterns

  • payload(): Returns structured data for SOC logging (zero allocation)
  • expose_sensitive(): Returns raw sensitive content (requires SocAccess capability)

Both methods require conscious choice and cannot be used accidentally via generic string formatting.

§Memory Safety

Implements ZeroizeOnDrop to clear owned string data. Sensitive variants receive additional volatile write treatment in InternalContextField::drop() to prevent compiler optimization of the clearing operation.

§No Clone/Copy Policy

Single-owner semantics prevent sensitive diagnostic data from being duplicated across memory regions, reducing attack surface for memory inspection.

Implementations§

Source§

impl InternalContext

Source

pub fn diagnostic(message: impl Into<Cow<'static, str>>) -> Self

Create a standard diagnostic internal context.

§Use Case

For typical internal error diagnostics that SOC analysts need but that should never be exposed externally (stack traces, internal state, etc.).

§Example
InternalContext::diagnostic("SQL injection detected in /api/users?id=1' OR '1'='1")
Source

pub fn sensitive(message: impl Into<Cow<'static, str>>) -> Self

Create a sensitive internal context with best-effort memory clearing.

§Use Case

For internal diagnostics containing:

  • Personally identifiable information (PII)
  • Credentials or API keys
  • Filesystem paths that reveal system topology
  • Database connection strings
  • Any data that could aid an attacker
§Memory Clearing Strategy

When this context is dropped:

  1. Owned string data is cleared via zeroize crate
  2. Volatile writes prevent LLVM dead-store elimination
  3. Compiler fence prevents instruction reordering

This provides best-effort clearing against casual memory inspection and compiler optimizations. It does NOT provide guarantees against:

  • Hardware cache persistence
  • Allocator-level memory reuse
  • Swap file or DMA copies

For cryptographic key material, use dedicated secure allocators.

§Example
InternalContext::sensitive(format!("Failed login for username: {}", username))
Source

pub fn lie(message: impl Into<Cow<'static, str>>) -> Self

Create an internal context marked as deceptive.

§Use Case

When internal logs themselves may be exfiltrated and you need to track deceptive narratives without exposing them externally. The payload() method will return this with a Lie marker to prevent SOC analysts from treating it as authentic diagnostic data.

§Distinction from PublicContext::lie()
  • PublicContext::lie(): For external consumption
  • InternalContext::lie(): For internal tracking of deception operations
§Example
InternalContext::lie("Normal database query executed successfully")
Source

pub const fn classification(&self) -> &'static str

Get classification label for logging and metrics.

§Returns

Static string identifying the context type:

  • "InternalDiagnostic": Standard internal error information
  • "Sensitive": Contains high-value data requiring special handling
  • "InternalLie": Deceptive content tracked internally
§Use Case

For indexing in log aggregation systems, metrics collection, or routing different context types to different storage backends.

Source

pub fn payload(&self) -> Option<InternalPayload<'_>>

Get structured payload for internal logging without heap allocation.

§Returns
  • Some(InternalPayload::Truth(_)): For diagnostic contexts
  • Some(InternalPayload::Lie(_)): For lie contexts (marked for SOC awareness)
  • None: For sensitive contexts (use expose_sensitive() instead)
§Performance

Zero allocation. The returned InternalPayload borrows directly from the underlying Cow<'static, str>. Loggers can format this without heap use:

match context.payload() {
    Some(payload) => println!("{}", payload),  // No allocation
    None => println!("[SENSITIVE REDACTED]"),
}
§Rationale

Previous design allocated format!("[LIE] {}", msg) on every access. This approach defers formatting to the logger, allowing:

  • Zero-copy access to underlying data
  • Logger-controlled formatting policy
  • Better performance under high error rates
Source

pub fn expose_sensitive(&self, _access: &SocAccess) -> Option<&str>

Expose raw sensitive content with capability-based access control.

§Access Control

Requires SocAccess capability token, which forces:

  1. Explicit privilege acquisition (cannot call accidentally)
  2. Grep-able sensitive data access points
  3. Future integration with RBAC or audit systems
§Security Contract

Caller must ensure returned data is sent ONLY to:

  • Authenticated, encrypted, access-controlled endpoints
  • SOC-exclusive dashboards with strict RBAC
  • Encrypted internal logging with key rotation
  • Forensic analysis workstations with air-gapped storage

Never send to:

  • External SIEMs or cloud logging services
  • Unencrypted log files
  • Monitoring services that aggregate across trust boundaries
§Returns
  • Some(&str): Raw sensitive content (if this is a Sensitive context)
  • None: If this is not a Sensitive context
§Why #[must_use]

Forces caller to explicitly handle the returned sensitive data rather than accidentally discarding it (which might indicate a logic error).

§Example
let access = SocAccess::acquire();
if let Some(sensitive) = context.expose_sensitive(&access) {
    send_to_encrypted_soc_siem(sensitive);
}

Trait Implementations§

Source§

impl Debug for InternalContext

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Debug representation for internal development and diagnostics.

§Redaction Policy
  • Diagnostic: Shows full content (for debugging)
  • Sensitive: Redacted (to prevent accidental logging)
  • Lie: Redacted (to prevent aggregation as factual data)
§Use Case

Primarily for unit tests and local development. Production logging should use payload() or expose_sensitive() for explicit control.

Source§

impl Display for InternalContext

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Display implementation for internal contexts.

§Security Policy

This ALWAYS returns a redacted placeholder, never actual content. Internal contexts should not be formatted for external display under any circumstances. This implementation exists only to satisfy trait bounds in generic code.

§Correct Usage
  • Use payload() for SOC logging
  • Use expose_sensitive() for controlled sensitive access
  • Do NOT use Display or ToString on internal contexts
Source§

impl Zeroize for InternalContext

Source§

fn zeroize(&mut self)

Zero out this object from memory using Rust intrinsics which ensure the zeroization operation is not “optimized away” by the compiler.
Source§

impl ZeroizeOnDrop for InternalContext

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.