One-way data flow, deterministic core.
A small stdlib-only engine with thin surfaces around it. Text flows in one direction — and every verdict is reproducible.
The data-flow pipeline
Each message is scored; the session is what gets acted on.
Trust boundaries & surfaces
Untrusted text enters on the left; the same engine is exposed four ways.
How the session score works
On each event the stored (unclamped) accumulator is decayed by e^(−λ·Δt) where λ = ln2 / half_life, the event's combined finding score is added, and the result is banded to 0–100. Risk rises with hostile turns and bleeds off when things go quiet — so the score reflects a campaign, not a single message. All time comes from an injectable clock, so a recorded event log replays to a byte-identical trajectory. That is what makes "why was this session blocked?" answerable in an audit.
EWMA is an advisory recent-severity signal; sliding-window caps are a hard override for floods. The policy maps the banded score to an action and to an Agent Control Standard disposition.
Design principles (constraints)
- Deterministic & auditable first — no cloud/ML in the hot path; every point of a score is explainable and replayable. ML is optional, pluggable enrichment.
- Defense-in-depth, never prevention theatre — assume injection eventually succeeds; see the campaign build and limit blast radius.
- Blast-radius thinking — default fail-closed; least privilege in every default.
- Drop-in anywhere — stdlib-only core; server, stores and ML are extras.
- Standards-anchored — every rule cites an OWASP/AISVS ID; emit ACS dispositions.
Read the full spec & research.
build-plan.md and finding.md live in the repo — the whole thing was spec-reviewed before a line of code.