/**
 * @module @arcis/node/middleware/overload
 *
 * Event-loop overload protection (sdk-vectors.md tier 1 #30, issue #51).
 *
 * Rate limiting caps per-client load; this middleware caps **total server
 * load** by sampling event-loop lag and shedding new requests with 503
 * when the loop is saturated. Pairs with rate-limit (per-client) +
 * `methodAllowlist` (per-route) to give Arcis three orthogonal layers
 * of "this server is healthy enough to do work" gating.
 *
 * ```ts
 * import { eventLoopProtection } from '@arcis/node';
 *
 * app.use(eventLoopProtection({
 *   maxLagMs: 500,         // 503 above this smoothed lag
 *   sampleIntervalMs: 250, // measure every 250ms
 * }));
 * ```
 *
 * Sampling strategy:
 *   - `setInterval(fn, sampleIntervalMs)` is scheduled; the callback
 *     compares wall-clock elapsed against the configured interval. Lag
 *     IS the difference: when the loop is busy, the timer fires late.
 *   - The interval handle is `.unref()`-ed so the process can exit
 *     cleanly even if the caller forgets to call `close()`.
 *   - Exponential moving average (`smoothed = 0.7 * smoothed + 0.3 *
 *     measured`) smooths out single-sample spikes — a 600ms GC pause
 *     shouldn't cause every request to 503 for the next sample window.
 *
 * Implementation deliberately picks `setTimeout` measurement over
 * `perf_hooks.monitorEventLoopDelay` (Node 12+ alternative) for two
 * reasons: (1) it works on every supported Node version with no feature
 * detection branch, (2) the perf_hooks histogram returns nanosecond
 * lag from a 10ms-resolution sampler, but applying the spec's EMA
 * formula on that signal would skew toward unreal lag values that the
 * sampler smoothed away. Keeping the sampler the spec calls for keeps
 * the math testable.
 */
import type { RequestHandler } from 'express';
export interface EventLoopProtectionOptions {
    /** Smoothed lag threshold in ms above which the middleware returns 503. Default: 500. */
    maxLagMs?: number;
    /** Sample frequency in ms. Default: 250. Lower = more responsive, higher = less overhead. */
    sampleIntervalMs?: number;
    /** Status code to return when overloaded. Default: 503. */
    statusCode?: number;
    /** Error message in the response body. Default: "Server overloaded, please retry". */
    message?: string;
    /** Retry-After header value in seconds. Default: 5. */
    retryAfterSeconds?: number;
    /**
     * EMA smoothing factor for the new measurement. Default: 0.3 (per
     * issue #51 spec). Must be in (0, 1]; lower values smooth harder
     * (longer memory of past samples), higher values track more reactively.
     */
    alpha?: number;
    /**
     * When true, every response gets `X-EventLoop-Lag: <ms>` so monitoring
     * can graph saturation independent of the deny decision. Off by default
     * because most apps don't need it and an extra header on every response
     * adds noise.
     */
    exposeLagHeader?: boolean;
}
export interface EventLoopProtectionMiddleware extends RequestHandler {
    /**
     * Stop the sampler. Call from a SIGTERM handler so the interval doesn't
     * keep a misconfigured process alive. Idempotent: subsequent calls are
     * no-ops.
     */
    close(): void;
    /**
     * Read the current smoothed lag in ms. Useful for tests that want to
     * assert the smoothing math without mocking timers, and for callers
     * who want to expose the value through a different surface (Prometheus,
     * dashboard panel, etc.).
     */
    currentLagMs(): number;
}
/**
 * Build an event-loop protection middleware. Returns a request handler
 * with `close()` and `currentLagMs()` attached (Pattern 6 in the
 * monorepo's middleware conventions: factories return a callable
 * augmented with cleanup helpers).
 */
export declare function eventLoopProtection(options?: EventLoopProtectionOptions): EventLoopProtectionMiddleware;
export default eventLoopProtection;
export declare const __test: {
    ema(prior: number, measured: number, alpha: number): number;
};
//# sourceMappingURL=overload.d.ts.map