Skip to main content

DualContextError

Struct DualContextError 

Source
pub struct DualContextError { /* private fields */ }
Expand description

Dual-context error model for honeypot systems with constructor-enforced invariants.

§Type Safety Guarantees

  1. Public and internal contexts use distinct wrapper types (cannot be confused)
  2. Fields are private (all construction goes through validated constructors)
  3. Constructors enforce semantic consistency rules at creation time

§Enforced Invariants

  • Public truth requires internal truth (no internal lies when external truth)
  • Public lie allows any internal context (deception is flexible)
  • Sensitive data flows only through InternalContext (type system prevents external leakage)

§Constructor Selection

  • with_lie(): Public deception + internal diagnostic (most common)
  • with_lie_and_sensitive(): Public deception + best-effort cleared sensitive internal
  • with_truth(): Public truth + internal truth (feature-gated, enforces consistency)
  • with_double_lie(): Public deception + internal deception (for log exfiltration scenarios)

§Memory Management

Implements ZeroizeOnDrop to clear all owned string data. Sensitive contexts receive additional volatile write treatment in InternalContextField::drop() to prevent LLVM from eliding the zeroization as a dead-store optimization.

This provides best-effort memory clearing but does not guarantee:

  • Hardware cache flushes
  • Cross-thread memory visibility
  • Protection against allocator reuse before physical clear

§No Clone/Copy Policy

Single-owner semantics prevent:

  • Duplicate error contexts in memory (reduced attack surface)
  • Inconsistent public/internal message pairs
  • Accidental persistence of sensitive data across scopes

Implementations§

Source§

impl DualContextError

Source

pub fn with_lie( public_lie: impl Into<Cow<'static, str>>, internal_diagnostic: impl Into<Cow<'static, str>>, category: OperationCategory, ) -> Self

Create error with public deception and internal diagnostic.

§Use Case

Standard constructor for honeypot deployments. External attackers see deceptive error message while SOC analysts see actual diagnostic data.

§Invariant

Public message is explicitly marked as DeceptiveLie. Internal message is authentic diagnostic data for SOC analysis.

§Example
DualContextError::with_lie(
    "Permission denied",  // Attacker sees generic error
    "Blocked SQL injection attempt: UNION SELECT detected in query parameter 'id'",
    OperationCategory::Detection,
)
§Performance

Zero allocation if string literals are passed. Into<Cow<'static, str>> allows both literals and owned strings without forcing allocation.

Source

pub fn with_lie_and_sensitive( public_lie: impl Into<Cow<'static, str>>, internal_sensitive: impl Into<Cow<'static, str>>, category: OperationCategory, ) -> Self

Create error with public deception and sensitive internal data.

§Use Case

When internal diagnostic contains PII, credentials, file paths, or other high-value data requiring best-effort memory clearing on drop.

§Memory Clearing Strategy

When this error is dropped, sensitive data receives:

  1. High-level clearing via zeroize crate
  2. Volatile writes to prevent compiler optimization
  3. Compiler fence to prevent instruction reordering

This provides best-effort defense against casual memory inspection and compiler optimizations. See module-level docs for limitations.

§Example
DualContextError::with_lie_and_sensitive(
    "Resource not found",
    format!("Attempted access to restricted path: /var/secrets/api_keys.txt by user {}", username),
    OperationCategory::IO,
)
§Invariant

Public message is deceptive. Internal message is marked sensitive and will be redacted in most logging contexts (requires explicit access via expose_sensitive() with SocAccess capability).

Source

pub fn with_truth( public_truth: impl Into<Cow<'static, str>>, internal_diagnostic: impl Into<Cow<'static, str>>, category: OperationCategory, ) -> Self

Create error with public truth and internal diagnostic.

§Availability

Only available when external_signaling feature is enabled. Without this feature, all public contexts must be deceptive (compile-time enforcement).

§Invariant Enforcement

When telling truth externally, internal context must also be truthful. This constructor enforces semantic consistency - you cannot lie internally while being honest externally.

§Use Case

For honeypots that intentionally signal some authentic errors to appear more legitimate (e.g., benign validation failures that don’t reveal defensive posture).

§Example
DualContextError::with_truth(
    "Invalid JSON format",
    "JSON parse error at line 42, column 15: expected closing brace",
    OperationCategory::Configuration,
)
Source

pub fn with_double_lie( public_lie: impl Into<Cow<'static, str>>, internal_lie: impl Into<Cow<'static, str>>, category: OperationCategory, ) -> Self

Create error where both public and internal contexts are deceptive.

§Use Case

Advanced deception scenarios where even internal logs may be exfiltrated by sophisticated attackers. Both contexts contain lies, but the internal lie is marked to prevent SOC analysts from treating it as authentic.

§Behavior
  • External systems see the public lie (generic error)
  • Internal logs show internal lie prefixed with [LIE] marker
  • SOC analysts are warned not to trust this diagnostic data
§Example
DualContextError::with_double_lie(
    "Service temporarily unavailable",
    "Routine maintenance window in progress",
    OperationCategory::System,
)
§Rationale

In environments where log exfiltration is a threat (compromised SIEM, malicious cloud provider, etc.), truthful internal logs become a liability. This constructor allows full deception while maintaining analyst awareness.

Source

pub const fn public(&self) -> &PublicContext

Get the public context (safe for external display).

§Returns

Borrowed reference to PublicContext, which can be used with Display trait to render external error messages.

§Lifetime

Reference borrows from self, valid until this error is dropped.

Source

pub const fn internal(&self) -> &InternalContext

Get the internal context (SOC-only visibility).

§Returns

Borrowed reference to InternalContext. Use payload() or expose_sensitive() methods for accessing content.

§Security Note

Do NOT use Display or ToString on this reference. Those implementations return redacted placeholders. Use explicit accessor methods instead.

Source

pub const fn category(&self) -> OperationCategory

Get the operation category.

§Returns

Copy of the OperationCategory enum. Can be used with display_name() for internal logging or deceptive_name() for external contexts.

Source

pub fn external_message(&self) -> &str

Get the external-facing error message as a string.

§Returns

Borrowed string slice suitable for HTTP responses, external APIs, or any untrusted context. May be deceptive depending on constructor used.

§Use Case

Primary method for rendering errors to external clients:

let error = DualContextError::with_lie(...);
http_response.body(error.external_message());
§Performance

Returns borrowed reference, no allocation. Delegates to PublicContext::as_str() which in turn delegates to Cow::as_ref().

Source

pub fn external_category(&self) -> &'static str

Get the deceptive category name for external display.

§Returns

Static string that masks honeypot operations as generic activity. Honeypot-specific categories return “Routine Operation”.

§Use Case

For structured error responses where category field is included:

json!({
    "error": error.external_message(),
    "category": error.external_category(),
})
§Performance

Const function, compiles to direct pointer return. Zero runtime cost.

Trait Implementations§

Source§

impl Debug for DualContextError

Source§

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

Debug representation for development and internal diagnostics.

§Output Format

Structured representation showing all three fields:

  • public: May be redacted if deceptive
  • internal: May be redacted if sensitive
  • category: Always shown
§Use Case

For unit tests, local development logging, and internal debugging. Not intended for production SOC logging (use explicit accessors instead).

Source§

impl Display for DualContextError

Source§

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

Render error for external display.

§Behavior

Displays only the public context. Internal diagnostic data is never included in this output.

§Use Case

For generic error handling where you want automatic string conversion:

println!("Error occurred: {}", error);
§Security Note

This is safe for external use. Only public context is rendered, which can only contain PublicTruth or DeceptiveLie - never internal diagnostics.

Source§

impl Zeroize for DualContextError

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 DualContextError

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.