/**
 * PackEvaluator -- synchronous pack-aware enforcement for the execute() hot path.
 *
 * Resolves active packs for a tenant, runs a flattened classifier index against
 * the action context, and returns a verdict (ALLOW / DENY / PENDING).
 *
 * Architecture decisions locked in KANBAN.md GAP-S3-01:
 *  - Per-tenant cache, 5-minute TTL, explicit flush on pack change events.
 *  - Synchronous evaluate() -- no await in the hot path.
 *  - Strictest-wins across packs: DENY > PENDING > ALLOW.
 *  - BLOCK action from dataPolicy.categoryActions -> DENY verdict.
 *  - WARN action -> PENDING verdict (human review required by default).
 *  - No classifier hit -> ALLOW.
 *
 * @connexum/ai-governance  GAP-S3-01
 */
import type { PackRegistry } from '../packs/index';
import type { EventBus } from '../audit/event-bus';
import type { ActionContext } from '../adapters/index';
export interface PackEvaluatorConfig {
    /** Cache TTL in milliseconds. Default: 5 minutes. */
    ttlMs: number;
    /** Enable per-tenant pack cache. Default: true. */
    enableCache: boolean;
}
export interface PackEvaluatorVerdict {
    verdict: 'ALLOW' | 'DENY' | 'PENDING';
    /** Pack IDs whose rules contributed to this verdict. */
    triggeringPackIds: string[];
    /** Classifier IDs (category strings) that fired. */
    triggeringClassifierIds: string[];
    /** Human-readable explanation. */
    reason: string;
    /** Epoch ms when the verdict was produced. */
    timestamp: number;
}
export declare class PackEvaluator {
    private readonly config;
    private readonly packRegistry;
    private readonly cache;
    constructor(packRegistry: PackRegistry, eventBus: EventBus, config?: Partial<PackEvaluatorConfig>);
    /**
     * Evaluate whether the action context is permitted under active pack policies.
     *
     * Synchronous by design: must not await anything.
     * Cache hit: uses cached pack set.
     * Cache miss: resolves from registry, populates cache, evaluates.
     *
     * @param allowedPackIds - Phase 2 SE Blocker #1 strict-membership filter.
     *   When provided, classifier index entries are restricted to packs whose IDs
     *   are in this set. Packs that are bound (active for the tenant) but NOT in
     *   this set are silently skipped — they do not contribute to the verdict.
     *   When absent (or undefined), all active packs evaluate (existing behaviour,
     *   preserves backward compat for legacy-token / non-entitlement paths).
     */
    evaluate(tenantId: string, agentId: string, actionContext: ActionContext, allowedPackIds?: Set<string>): PackEvaluatorVerdict;
    /**
     * Flush the cache entry for a single tenant (break-glass, pack change).
     */
    flushTenant(tenantId: string): void;
    /**
     * Flush all tenant cache entries.
     */
    flushAll(): void;
    /**
     * Return the flattened classifier index for a tenant, resolving from the
     * registry on cache miss or TTL expiry.
     */
    private getClassifierIndex;
    /**
     * Build a flattened classifier index from a pack list.
     * For categories present in multiple packs, the strictest action wins.
     *
     * The classifierDef is taken from the strictest-action pack (or the first
     * pack declaring the category when actions tie). It is used in
     * categoryMatches() to run the real regex/function classifier instead of
     * falling back to keyword substring matching.
     *
     * Returns: Map<categoryId, { action: string; packIds: string[]; classifierDef?: CategoryClassifierDef }>
     */
    private buildClassifierIndex;
    /**
     * Map a dataPolicy categoryAction string to a verdict.
     * BLOCK -> DENY, WARN -> PENDING (human review), everything else -> ALLOW
     * (LOG and REQUIRE_APPROVAL are also mapped: REQUIRE_APPROVAL -> PENDING).
     */
    private actionToVerdict;
    /**
     * Determine whether a category fires for the given action context.
     *
     * Evaluation order (Task 2 fix, 2026-04-25):
     *   1. If the pack declares a CategoryClassifierDef with a `classifier` function,
     *      call it -- this is the authoritative runtime decision.
     *   2. If the pack declares a `pattern` regex, test it against the serialized input.
     *      Regex is precompiled at buildClassifierIndex time (not here) so no per-call
     *      compilation overhead. Satisfies GAP-S3-01 p99 <= 50ms latency budget.
     *   3. If neither classifier nor pattern is defined (pack declared the category
     *      but hasn't instrumented it), fall through to the legacy broad substring
     *      matching with a debug log so the gap is discoverable.
     *
     * Previously this method ran only keyword substring matching, meaning packs'
     * carefully crafted regex classifiers were NEVER called in the enforcement
     * hot path. This fix ensures SSNs, credit card numbers, and other regulated
     * data are caught by the actual pattern the pack author specified.
     *
     * False positives produce PENDING (human review) -- safe.
     * False negatives produce ALLOW -- unsafe. Err toward PENDING.
     */
    private categoryMatches;
    /** Set of category IDs already warned about missing classifierDef (de-dupe per process). */
    private static _warnedUninstrumentedCategories;
    /**
     * Produce a single string from an ActionContext suitable for classifier matching.
     */
    private serializeActionForMatching;
}
//# sourceMappingURL=pack-evaluator.d.ts.map