/** * Per-fingerprint event flood guard * * Lives in `protocol-types` because EVERY producer needs it — node taps, the Nest * sink, the gateway, the bridge, and (since the admission decision must happen * BEFORE a payload is built) the browser runtime. It is pure logic with no Node * APIs, so a browser bundle can carry it. — a token bucket per fingerprint, shared by * every bus WRITER (lensEmit, the cluster gateway's observability emit, the * bridge env sink mirrors it). One hot fingerprint (an app retrying a fetch in * a loop, a valtio store churning per frame) must not be able to write hundreds * of lines/sec into events.jsonl: the 2026-07-28 incident sustained ~680 ev/s, * grew the bus file to 254 MB in two hours, and OOM-crash-looped every consumer * that ingests it. The guard keeps the SIGNAL (the first burst, then a trickle * with a `floodSuppressed` count) while dropping the redundant repetition. */ export interface FloodAdmit { ok: boolean; /** Events dropped for this fingerprint since the last admitted one (0 normally). */ suppressed: number; } export interface FloodGuard { admit(fingerprint: string): FloodAdmit; } export interface FloodGuardOptions { /** Instantaneous burst allowance per fingerprint (bucket capacity). Default 30. */ burst?: number; /** Sustained events/sec per fingerprint (bucket refill). Default 5. */ perSec?: number; /** Max distinct fingerprints tracked before stale buckets are evicted. Default 2048. */ maxKeys?: number; } export declare function createEventFloodGuard(opts?: FloodGuardOptions): FloodGuard;