/**
 * @module @arcis/node/guards
 *
 * Guards API. Same Arcis decisioning (rate limit, bot detect, prompt
 * injection, token budget) applied to non-HTTP contexts where there's no
 * `req`/`res` pair. Use this for:
 *
 *   - Job queue workers (BullMQ, agenda, sidekiq-style)
 *   - Agent tool-call handlers (Claude/OpenAI tool dispatch)
 *   - WebSocket / SSE / gRPC handlers
 *   - Background processors (cron jobs, scheduled tasks)
 *
 * Each call to `guards.run(input)` returns a structured decision: `ok` +
 * (when denied) the `vector`, `severity`, `reason`, and `retryAfterSeconds`
 * the deny was triggered by. The first vector that denies short-circuits
 * the rest, so denial latency stays bounded.
 *
 * @example
 * import { Guards } from '@arcis/node';
 *
 * const guards = new Guards({
 *   rateLimit: { max: 50, windowMs: 60_000 },
 *   tokenBudget: { maxTokens: 100_000, windowMs: 60 * 60 * 1000 },
 *   promptInjection: { redactLow: false },
 * });
 *
 * // In a job handler:
 * const decision = guards.run({
 *   key: jobUserId,
 *   tokens: estimateTokens(prompt),
 *   text: prompt,
 * });
 * if (!decision.ok) {
 *   throw new Error(`Job rejected (${decision.vector}): ${decision.reason}`);
 * }
 */
import { type BotProtectionOptions } from './middleware/bot-detection';
import { type PromptInjectionSeverity } from './sanitizers/prompt-injection';
export interface GuardsRateLimitOptions {
    /** Max events per window per key. Default: 100. */
    max?: number;
    /** Window length in milliseconds. Default: 60000 (1 minute). */
    windowMs?: number;
}
export interface GuardsTokenBudgetOptions {
    /** Max tokens a single key can spend in one window. Default: 100,000. */
    maxTokens?: number;
    /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */
    windowMs?: number;
    /**
     * Optional per-call cap. When set, a single call with `tokens > maxRequestTokens`
     * denies BEFORE charging the window budget.
     */
    maxRequestTokens?: number;
}
export interface GuardsPromptInjectionOptions {
    /**
     * Minimum severity that triggers a deny. Default: 'medium' (HIGH and
     * MEDIUM matches deny; LOW matches still surface in `decision.matches`
     * but don't deny).
     */
    denyAt?: PromptInjectionSeverity;
}
export interface GuardsBotOptions {
    /** Categories that pass through. Default: SEARCH_ENGINE, SOCIAL, MONITORING. */
    allow?: BotProtectionOptions['allow'];
    /** Categories that always deny. Default: AUTOMATED. */
    deny?: BotProtectionOptions['deny'];
    /** Default for uncategorized bots. Default: 'allow'. */
    defaultAction?: BotProtectionOptions['defaultAction'];
}
export interface GuardsConfig {
    /** When set, every call is rate-limited per `input.key`. Omit to disable. */
    rateLimit?: GuardsRateLimitOptions;
    /** When set, calls with `input.tokens` charge a per-key sliding-window budget. */
    tokenBudget?: GuardsTokenBudgetOptions;
    /** When set, `input.text` is scanned for prompt-injection signatures. */
    promptInjection?: GuardsPromptInjectionOptions | true;
    /** When set, `input.userAgent` is matched against the bot corpus. */
    bot?: GuardsBotOptions | true;
}
export interface GuardsInput {
    /** Identifier for rate-limit / token-budget bucketing. Required. */
    key: string;
    /** Optional text payload for prompt-injection scanning. */
    text?: string;
    /** Optional token cost for token-budget accounting. */
    tokens?: number;
    /** Optional User-Agent string for bot detection. */
    userAgent?: string;
}
export type GuardsVector = 'rate-limit' | 'token-budget' | 'prompt-injection' | 'bot';
export type GuardsSeverity = 'low' | 'medium' | 'high';
export interface GuardsDecision {
    /** True if the input passes every configured vector. */
    ok: boolean;
    /** Which vector denied. Undefined when `ok` is true. */
    vector?: GuardsVector;
    /** Human-readable reason for the deny. Undefined when `ok` is true. */
    reason?: string;
    /** Severity of the deny. Undefined when `ok` is true. */
    severity?: GuardsSeverity;
    /** How many seconds until the same key can retry (rate-limit / token-budget). */
    retryAfterSeconds?: number;
    /**
     * For prompt-injection: every signature that matched, even when the deny
     * threshold wasn't hit. Lets callers log low-severity matches without
     * blocking on them.
     */
    matches?: ReadonlyArray<{
        rule: string;
        severity: GuardsSeverity;
    }>;
}
/**
 * Guards. Apply Arcis decisions to non-HTTP contexts. Construct once with
 * the vectors you care about, then call `.run(input)` per request/event.
 * Internal state (rate-limit buckets, token-budget buckets) lives on the
 * instance. Call `.close()` to release the periodic-cleanup interval.
 */
export declare class Guards {
    private readonly rl;
    private readonly tb;
    private readonly pi;
    private readonly bot;
    private readonly rlStore;
    private readonly tbStore;
    private readonly cleanup;
    private readonly piDenyRank;
    constructor(config?: GuardsConfig);
    /**
     * Evaluate every configured vector against `input`. Returns a structured
     * decision; the first denying vector short-circuits the rest.
     */
    run(input: GuardsInput): GuardsDecision;
    /** Inspect rate-limit usage for a key. Useful for tests and telemetry. */
    inspectRateLimit(key: string): {
        count: number;
        resetTime: number;
    } | null;
    /** Inspect token-budget usage for a key. */
    inspectTokenBudget(key: string): {
        used: number;
        resetTime: number;
    } | null;
    /** Reset a single key's state, or all keys if `key` is omitted. */
    reset(key?: string): void;
    /** Release the periodic cleanup interval. Idempotent. */
    close(): void;
    private checkRateLimit;
    private checkTokenBudget;
    private checkBot;
    private sweepExpired;
}
export default Guards;
//# sourceMappingURL=guards.d.ts.map