Skip to main content

Module replay_defense

Module replay_defense 

Source
Expand description

Adaptive session replay defense mode for browser identity.

§What is “replay-style” anti-bot detection?

Several anti-bot vendors record a session (TLS handshake + a sequence of navigations + identity surface values) and replay the same artifacts later. If the same fingerprint, nonce, or challenge response shows up in two different sessions (or after a site-side rotation), the vendor flags the second session as a replay. This is distinct from coherence drift (one session has multiple inconsistent identity surfaces) — replay detection specifically looks at session-lifetime artifacts:

  • The session nonce issued by a challenge / challenge-response endpoint.
  • The browser fingerprint captured at session start.
  • The age of the session.

§How this module helps

ReplayDefensePolicy captures three orthogonal levers the runner can use to defeat replay-style detection:

The deterministic check function evaluates a ReplayDefenseState (the per-session record) against a ReplayDefenseCheckInput (the observed context) and returns a ReplayDefenseDecision. The decision is purely derived from the inputs — no I/O, no clock reads — so unit tests can exercise the full state space.

§Integration with AcquisitionRunner

AcquisitionRequest::replay_defense carries the live context (policy + state) into the runner. The runner evaluates the policy before any stage executes:

  1. The decision is logged via ReplayDefenseReport::log.
  2. If the decision is invalid and force_reset_on_drift is true, the runner calls BrowserPool::release_context to invalidate the sticky session, then short-circuits with a StageFailureKind::Setup failure tagged replay_defense_forced_refresh.
  3. The full report is attached to the AcquisitionResult::replay_defense field so downstream automation can attribute the rejection.

§Feature flag

This module is default-on and is always compiled as part of the stygian-browser crate. No new feature gate is introduced.

§Default policy

ReplayDefensePolicy::default returns a deterministic baseline that is safe to ship in production:

  • rotation_interval = 1800 s (30 min)
  • nonce_validity_window = 300 s (5 min)
  • force_reset_on_drift = true

Callers can override any field via the with-builder methods or by deserialising a config from JSON / TOML.

§Example

use stygian_browser::replay_defense::{
    ReplayDefenseCheckInput, ReplayDefenseDecision, ReplayDefensePolicy,
    ReplayDefenseState, check,
};
use std::time::Duration;

let policy = ReplayDefensePolicy::default();
let captured = stygian_browser::freshness::unix_epoch_ms();
let state = ReplayDefenseState::with_fingerprint(
    "example.com",
    "sha256:abc",
    Some("nonce-001"),
    captured,
);

let observed = ReplayDefenseCheckInput::new(
    "example.com",
    Some("sha256:abc"),
    Some("nonce-001"),
    captured + 1_000,
);
let decision = check(&policy, &state, &observed);
assert!(decision.is_valid());

Structs§

ReplayDefenseCheckInput
Observed context passed to check on every session reuse.
ReplayDefensePolicy
Adaptive session-replay defense policy.
ReplayDefenseReason
Structured reason a replay-defense check invalidated a session.
ReplayDefenseReport
Compact replay-defense report attached to acquisition results and emitted via tracing.
ReplayDefenseState
Per-session replay-defense state captured when the session was first bound.

Enums§

ReplayDefenseDecision
Decision produced by check.
ReplayDefenseError
Errors produced by replay-defense policy / state construction.
ReplayDefenseInvalidationKind
Machine-readable reason tag attached to ReplayDefenseReason.

Functions§

check
Evaluate policy + state against input and return a deterministic ReplayDefenseDecision.
unix_epoch_ms
Current Unix epoch in milliseconds, clamped to u64.