import { type TopLevelConfig } from '@cloud-copilot/iam-collect';
import { type ClientFactoryPlugin } from '../collect/collect.js';
import { type S3AbacOverride } from '../utils/s3Abac.js';
import { type LightRequestAnalysis } from './requestAnalysis.js';
import { type WhoCanPrincipalScope, type WhoCanResponse } from './whoCan.js';
import { type WorkerBootstrapPlugin } from './workerBootstrapPlugin.js';
export type { WorkerBootstrapPlugin } from './workerBootstrapPlugin.js';
/**
 * Configuration for creating a WhoCanProcessor. These settings are fixed
 * for the lifetime of the processor and baked into worker threads at creation time.
 */
export interface WhoCanProcessorConfig {
    /** The collect configurations for loading IAM data. */
    collectConfigs: TopLevelConfig[];
    /** The AWS partition to use (e.g. 'aws', 'aws-cn'). */
    partition: string;
    tuning?: {
        /**
         * The number of worker threads to use beyond the main thread. Defaults to number of CPUs - 1.
         */
        workerThreads?: number;
        /**
         * The concurrency level for processing simulations on the main thread. Defaults to 50.
         */
        mainThreadConcurrency?: number;
        /**
         * The concurrency level for processing simulations on worker threads.
         * This is the value for EACH worker.
         * Defaults to 50.
         */
        perWorkerConcurrency?: number;
        /**
         * The concurrency level for the shared preparation queue (account/principal fetches
         * across all active requests). Defaults to min(50, max(1, number of CPUs * 2)).
         */
        preparationConcurrency?: number;
        /**
         * The maximum number of requests that may be actively expanded into scenarios
         * at once. Later requests remain as lightweight entries in pendingRequests.
         * Defaults to 30.
         */
        maxRequestsInProgress?: number;
    };
    /** Optional plugin to wrap the collect client with a custom implementation. */
    clientFactoryPlugin?: ClientFactoryPlugin;
    /**
     * Optional plugin that runs once per worker thread at startup before any work
     * is processed. Use this for loading instrumentation, initializing logging
     * context, or other worker-lifetime setup. If the bootstrap function throws,
     * the worker fails and the processor surfaces the error.
     */
    workerBootstrapPlugin?: WorkerBootstrapPlugin;
    /** An override for S3 ABAC being enabled when checking access to S3 Bucket resources. */
    s3AbacOverride?: S3AbacOverride;
    /** Whether workers should collect grant details for allowed simulations. */
    collectGrantDetails?: boolean;
    /**
     * Async callback invoked when a request settles (succeeds or fails). The processor
     * awaits this callback before removing the request from active state and admitting
     * the next pending request. This allows consumers to perform async work with backpressure.
     *
     * @param event - The settlement event containing the request ID, original request,
     *   status, and either the result or the error.
     */
    onRequestSettled: (event: WhoCanSettledEvent) => Promise<void>;
    /**
     * Optional async callback invoked when an `onRequestSettled` callback throws or rejects.
     * If this callback itself throws, the error is silently ignored. If not provided, a
     * warning is logged indicating that a settlement callback failed with no handler defined.
     *
     * @param event - The settlement event that was being delivered when the error occurred.
     * @param error - The error thrown by the `onRequestSettled` callback.
     */
    onSettlementFailure?: (event: WhoCanSettledEvent, error: Error) => Promise<void>;
    /**
     * Whether the processor should ignore an existing principal index. Use this with testing.
     */
    ignorePrincipalIndex?: boolean;
}
/**
 * Request parameters that vary per whoCan call on a processor.
 */
export interface WhoCanProcessorRequest {
    /** The ARN of the resource to check access for. */
    resource?: string;
    /** The account ID the resource belongs to. */
    resourceAccount?: string;
    /** The actions to check access for. */
    actions: string[];
    /** Whether to sort the results for consistent output. */
    sort?: boolean;
    /**
     * Optional callback to filter which denied simulations should include detailed
     * denial analysis. If provided, deny details are collected for this request.
     * If the callback returns true for a given denial, the full deny details are
     * included in the response. If omitted, no deny details are collected for this request.
     *
     * @param details - A lightweight summary of the denied simulation.
     * @returns true to include full deny details for this denial.
     */
    denyDetailsCallback?: (details: LightRequestAnalysis) => boolean;
    /** Optional scope to limit the set of principals tested. */
    principalScope?: WhoCanPrincipalScope;
    /** Optional context keys to consider strict when running simulations. */
    strictContextKeys?: string[];
}
/**
 * Event delivered to the onRequestSettled callback when a request completes
 * (either successfully or with an error).
 */
export type WhoCanSettledEvent = WhoCanSettledSuccess | WhoCanSettledError;
/**
 * Settlement event for a successfully completed request.
 */
export interface WhoCanSettledSuccess {
    /** Discriminator for the settlement outcome. */
    status: 'fulfilled';
    /** The unique ID assigned when the request was enqueued. */
    requestId: string;
    /** The original request that was enqueued. */
    request: WhoCanProcessorRequest;
    /** The whoCan result for this request. */
    result: WhoCanResponse;
}
/**
 * Settlement event for a request that failed during preparation or simulation.
 */
export interface WhoCanSettledError {
    /** Discriminator for the settlement outcome. */
    status: 'rejected';
    /** The unique ID assigned when the request was enqueued. */
    requestId: string;
    /** The original request that was enqueued. */
    request: WhoCanProcessorRequest;
    /** The error that caused the request to fail. */
    error: Error;
}
/**
 * A queue-first bulk processor that accepts many whoCan requests, expands
 * scenarios on the main thread, and feeds a shared simulation scheduler used
 * by worker threads and an optional main-thread runner.
 *
 * Results are delivered through the {@link WhoCanProcessorConfig.onRequestSettled}
 * callback as each request completes — they are not stored inside the processor.
 *
 * Use {@link enqueueWhoCan} to submit requests, then {@link waitForIdle} to
 * wait for all work to complete. Call {@link shutdown} when done to terminate
 * worker threads.
 */
export declare class WhoCanProcessor {
    private workers;
    private collectClient;
    private config;
    private isShutdown;
    private workersDead;
    private pendingRequests;
    private activeRequestOrder;
    private requestStates;
    private admissionPumpRunning;
    private draining;
    private preparationQueue;
    private idleWaiters;
    private mainThreadWorker;
    private fatalError?;
    private shutdownPromise?;
    private constructor();
    /**
     * Waits for every worker to post a `{ type: 'ready' }` message. If any
     * worker fails (error, non-zero exit, or explicit `startupError` message)
     * the remaining workers are terminated and the returned promise rejects.
     *
     * @param workers - The worker instances to wait on.
     */
    private static awaitWorkersReady;
    /**
     * Creates a new WhoCanProcessor with worker threads, a shared cache, and
     * lifetime-scoped message routing. The processor is ready to accept requests
     * immediately after creation.
     *
     * @param config - The configuration for the processor, including collect configs,
     *   partition, simulation options, tuning, and the onRequestSettled callback.
     * @returns a new WhoCanProcessor instance
     */
    static create(config: WhoCanProcessorConfig): Promise<WhoCanProcessor>;
    /**
     * Enqueues a whoCan request for processing. Returns a unique request ID
     * that will appear in the corresponding {@link WhoCanSettledEvent}.
     *
     * This method never activates a request directly — it appends to
     * pendingRequests and signals the admission pump.
     *
     * @param request - The whoCan request parameters.
     * @returns the unique request ID assigned to this request.
     * @throws if the processor is shut down or draining via waitForIdle.
     */
    enqueueWhoCan(request: WhoCanProcessorRequest): string;
    /**
     * Returns a promise that resolves when all pending and active work has
     * completed and all onRequestSettled callbacks have finished.
     *
     * While draining, new calls to {@link enqueueWhoCan} will throw. Once
     * the drain completes, the processor re-opens for new enqueues.
     *
     * @returns a promise that resolves when idle, or rejects if a worker crashes.
     */
    waitForIdle(): Promise<void>;
    /**
     * Shuts down the processor by rejecting all pending requests, waiting for
     * active requests to settle, and terminating all worker threads.
     *
     * This method is idempotent — calling it multiple times is safe.
     */
    shutdown(): Promise<void>;
    /**
     * Internal shutdown implementation. Rejects pending requests, waits for
     * active requests to drain, then terminates workers.
     */
    private executeShutdown;
    /**
     * Installs lifetime-scoped message, error, and exit listeners on all workers.
     * Message listeners route simulation results and deny-detail checks to the
     * correct request state using requestId. Error/exit listeners detect crashes
     * and mark the processor as fatally failed.
     */
    private installLifetimeWorkerListeners;
    /**
     * Routes a message from a worker thread to the appropriate handler based
     * on message type and requestId.
     *
     * @param msg - The message received from the worker.
     * @param worker - The worker that sent the message.
     */
    private handleWorkerMessage;
    /**
     * Creates the main-thread simulation runner if mainThreadConcurrency > 0.
     * The runner pulls from the FIFO scheduler and routes results by requestId.
     */
    private createMainThreadRunner;
    /**
     * Dequeues the next simulation scenario using FIFO request priority.
     * Prefers the oldest active request that has ready scenarios. If the oldest
     * is temporarily empty (still preparing), falls back to the next request
     * with ready scenarios so cores do not idle.
     *
     * @returns the next work item, or undefined if no scenarios are ready.
     */
    private dequeueNextScenario;
    /**
     * Notifies all simulation consumers (workers and main thread) that new
     * work may be available in the scheduler.
     */
    private notifySimulationConsumers;
    /**
     * Wakes the admission pump to process pending requests. If the pump is
     * already running, this is a no-op — the running pump will pick up new
     * pending requests on its next iteration.
     */
    private wakeAdmissionPump;
    /**
     * The admission pump loop. Drains pendingRequests into active processing
     * up to maxRequestsInProgress. Only one instance of this loop runs at a time,
     * guarded by admissionPumpRunning.
     */
    private runAdmissionPump;
    /**
     * Creates a fresh RequestState for an admitted request.
     *
     * @param submitted - The submitted request to create state for.
     * @returns the new RequestState.
     */
    private createRequestState;
    /**
     * Enqueues the root preparation job for a request. This job performs resource
     * account resolution, resource policy lookup, action expansion, principal scope
     * handling, and then enqueues follow-up preparation jobs to enumerate principals.
     *
     * @param state - The request state to prepare.
     */
    private enqueueRootPreparation;
    /**
     * Executes the root preparation for a request: resolves the resource account,
     * fetches the resource policy, expands actions, determines which accounts and
     * principals to check, and enqueues follow-up preparation jobs.
     *
     * @param state - The request state to prepare.
     */
    private executeRootPreparation;
    /**
     * Handles a simulation result from a worker or the main thread runner.
     * Routes the result to the correct request state and checks for completion.
     *
     * @param requestId - The ID of the request this result belongs to.
     * @param result - The simulation job result.
     */
    private handleSimulationResult;
    /**
     * Handles a checkDenyDetails request from a worker thread. Looks up the
     * request's denyDetailsCallback and responds.
     *
     * @param requestId - The ID of the request.
     * @param checkId - The unique check ID for this deny-details round trip.
     * @param lightAnalysis - The light analysis to pass to the callback.
     * @param worker - The worker to respond to.
     */
    private handleCheckDenyDetails;
    /**
     * Handles a deny details result from a worker thread. Decrements the
     * pending deny-details counter and checks for request completion.
     *
     * @param requestId - The ID of the request.
     * @param denyDetail - The deny detail to store.
     */
    private handleDenyDetailsResult;
    /**
     * Checks whether a request has completed all preparation and simulation work.
     * If so, settles the request as successful.
     *
     * @param state - The request state to check.
     */
    private checkRequestCompletion;
    /**
     * Settles a request as successful: builds the WhoCanResponse, awaits
     * onRequestSettled, removes the request from active state, and wakes
     * the admission pump.
     *
     * @param state - The request state to settle.
     */
    private settleRequestAsSuccess;
    /**
     * Settles a request as failed: invokes onRequestSettled with the error
     * immediately, but keeps the request in active state until all in-flight
     * work drains (created === completed). Late results for settled requests
     * are discarded but still counted so the drain completes.
     *
     * @param state - The request state to settle.
     * @param error - The error that caused the failure.
     */
    private settleRequestAsError;
    /**
     * Invokes the onRequestSettled callback and routes any errors through
     * {@link handleSettlementFailure}.
     *
     * @param event - The settlement event to deliver.
     */
    private invokeSettledCallback;
    /**
     * Awaits the onRequestSettled callback, then removes the request from
     * active state and wakes the admission pump. Used for successful settlements
     * where all work is already complete.
     *
     * @param state - The request state being settled.
     * @param event - The settlement event to deliver.
     */
    private invokeSettledCallbackAndCleanup;
    /**
     * Checks whether a settled request has fully drained: the onRequestSettled
     * callback has been awaited, all preparation jobs have finished, all
     * simulation results have been received, and all deny-detail round trips
     * have completed. Only then is the request removed from active state.
     *
     * @param state - The request state to check.
     */
    private checkRequestDrain;
    /**
     * Removes a request from active state, wakes the admission pump to fill
     * the freed slot, and checks if the processor is now idle.
     *
     * @param state - The request state to remove.
     */
    private removeFromActiveState;
    /**
     * Returns true if the processor has no pending, active, or in-flight work.
     *
     * @returns true if fully idle.
     */
    private isIdle;
    /**
     * Checks whether the processor has become idle and resolves or rejects the
     * waitForIdle promise if so.
     */
    private checkIdle;
    /**
     * Handles an error thrown by the `onRequestSettled` callback. If the
     * `onSettlementFailure` callback is defined, it is invoked with the event
     * and error; any error it throws is silently ignored. If not defined, a
     * warning is logged.
     *
     * @param event - The settlement event that was being delivered.
     * @param err - The raw error thrown by the `onRequestSettled` callback.
     */
    private handleSettlementFailure;
    /**
     * Handles an unexpected worker failure by marking the processor as dead,
     * terminating remaining workers, and rejecting all active and pending requests.
     *
     * @param error - The error that caused the worker failure.
     */
    private handleWorkerFailure;
}
//# sourceMappingURL=WhoCanProcessor.d.ts.map