Expand description
Anti-bot change-detection feed (T88).
Detects canary, proxy, and extraction deltas and emits actionable incident packets via the metrics surface and the diagnostics payload. Anti-bot change-detection feed (T88).
§What this module does
Anti-bot vendors rotate wall-logic, escalate challenges, and rewrite challenge JS without notice. The change feed is the early-warning surface: it consumes regression signals from the canary (T92 + T84), proxy intelligence (T86), and extraction reliability (T87) pipelines and emits actionable incident packets when the signals agree.
The feed is deterministic — no HashMap,
no stochastic thresholds, no ML. The same input
always produces the same classification, so
downstream runbook tooling can dedupe and audit
without trusting the call site.
§Detection flow
ChangeDeltaInput[] (boundary type)
│
▼
ChangeDetector::detect() (this module)
│
├── per-target aggregate
│ - max(weight * source_weight)
│ - banded via ChangeFeedThresholds
│
├── ChangeFeedReport (always returned)
│
└── ChangeEventSink::record_change_event
- InMemoryChangeFeedSink (always available)
- MetricsCollector (with `metrics` feature)§Classification
| Band | Default score range | What the operator sees |
|---|---|---|
Noise | < 0.20 | Log only, no event |
Suspected | [0.20, 0.55) | Advisory event |
Probable | ≥ 0.55 or critical tier | Runbook event |
A single canary delta cannot reach Probable
on its own — the default canary_weight is
1.00, so a delta with weight 0.55 reaches the
floor only when paired with another source or
marked Critical by the upstream signal.
§Schema
The ChangeEvent payload is the operator-facing
view of the regression. It carries the affected
target, the delta summary (headline + score +
sources + severities), the vendor hint, the
target class, the runbook mitigation pointer, and
the structured evidence preserved from the
upstream deltas. ChangeFeedReport is the
per-cycle aggregate that the runbook diagnostics
surface consumes.
§Metrics surface
When the metrics feature is enabled, the
MetricsCollector (see crate::metrics::MetricsCollector; only compiled
with --features metrics)
implements ChangeEventSink so the detector
records events directly into the existing
Prometheus exporter. The change_feed_* series
are only emitted when at least one counter is
non-zero, so dashboards that have not wired the
change feed in keep their existing layout
unchanged.
§Feature flag
The module is default-on (gated behind the
caching feature, which is part of the
stygian-charon default feature set). No new
feature gate is introduced — the public surface
is purely additive and existing serialisers see
no change unless they explicitly opt in via the
new fields on ChangeFeedReport /
ChangeEvent.
§Example
use stygian_charon::change_feed::{
ChangeDeltaInput, ChangeDetector, InMemoryChangeFeedSink, DeltaSeverity, DeltaSource,
};
let detector = ChangeDetector::new();
let sink = InMemoryChangeFeedSink::new();
// Two deltas on the same target — a canary
// warning plus a proxy advisory. Neither
// alone is enough for `Probable`, but the
// canary marks itself `Critical`.
let deltas = vec![
ChangeDeltaInput::new(
DeltaSource::Canary,
"example.com",
0.40,
DeltaSeverity::Critical,
"integrity probe webdriver regressed",
),
ChangeDeltaInput::new(
DeltaSource::Proxy,
"example.com",
0.50,
DeltaSeverity::Warning,
"proxy score dropped",
),
];
let report = detector.detect(&deltas, &sink);
assert_eq!(report.aggregate_classification, stygian_charon::change_feed::ChangeClassification::Probable);
assert_eq!(report.probable_targets, vec!["example.com".to_string()]);
assert_eq!(sink.len(), 1);Structs§
- Change
Delta Input - A single regression delta consumed by the
ChangeDetector. - Change
Detector - Deterministic change-feed detector.
- Change
Event - A single change-feed event.
- Change
Feed Report - Aggregated change-feed report for a single detection cycle.
- Change
Feed Thresholds - Configurable thresholds and source weights for
the
ChangeDetector. - Delta
Summary - Per-event delta summary.
- InMemory
Change Feed Sink - In-memory sink for
ChangeEventrecords. - Mitigation
Path - Stable pointer to the runbook section an
operator should consult when responding to a
ChangeEvent.
Enums§
- Change
Classification - Coarse-grained change-feed classification.
- Delta
Severity - Severity tier attached to a delta by its source.
- Delta
Source - Source channel for a
ChangeDeltaInput.
Constants§
- DEFAULT_
CANARY_ WEIGHT - Default weight for canary-source deltas.
- DEFAULT_
EXTRACTION_ WEIGHT - Default weight for extraction-source deltas.
- DEFAULT_
NOISE_ CEILING - Default ceiling below which a per-target score is
classified as
Noise. - DEFAULT_
PROBABLE_ FLOOR - Default floor at or above which a per-target score
is classified as
Probable. - DEFAULT_
PROXY_ WEIGHT - Default weight for proxy-source deltas.
Traits§
- Change
Event Sink - Trait alias for any sink that can receive
ChangeEventrecords.
Functions§
- record_
change_ event - Free-function form of
ChangeEventSink::record_change_event.