/**
 * SentinelDestination -- Microsoft Sentinel audit output adapters.
 *
 * Delivers governance events to Microsoft Sentinel via two API variants,
 * selectable at construction time via `apiVariant`:
 *
 *   'log-analytics-collector'
 *     Legacy Log Analytics Data Collector API (2016-04-01).
 *     Auth: HMAC-SHA256 signed with workspace shared key.
 *     Endpoint: https://<workspaceId>.ods.opinsights.azure.com/api/logs?api-version=2016-04-01
 *     Max body: 30 MB (hard Azure limit). Default: gzip compressed.
 *     Returns 200 on accept.
 *
 *   'logs-ingestion'
 *     Logs Ingestion API (2023-01-01). Azure AD / managed-identity auth.
 *     Auth: Bearer token from caller-supplied tokenProvider callback.
 *     This adapter does NOT implement the Azure AD OAuth flow -- the caller
 *     supplies a token via tokenProvider(() => Promise<string>).
 *     Endpoint: https://<dceEndpoint>/dataCollectionRules/<dcrImmutableId>/streams/<streamName>?api-version=2023-01-01
 *     Max body: 1 MB (hard Azure limit). Default: gzip compressed.
 *     Returns 204 No Content on success.
 *
 * Design decisions:
 *   - No Azure SDK. Plain HTTPS POST via Node built-ins (no supply-chain risk).
 *   - Workspace shared key is NEVER stored in plaintext. Only a KMS reference
 *     (sharedKeyRef) is held; resolved at send-time via the injected SecretResolver.
 *   - Retry semantics mirror datadog-logs.ts and splunk-hec.ts:
 *     429 (rate-limited) + 5xx = retryable. Retry-After honored on 429.
 *     4xx other than 429 = non-retryable; DLQ immediately.
 *   - Gzip compression applied by default. Configurable.
 *   - packBinding is mandatory. Empty binding throws UnboundDataError before any
 *     HTTP request (pack-binding primacy, Thomas Directive 2026-04-22).
 *   - Workspace shared key and bearer token are NEVER emitted to any log stream,
 *     error message, or DLQ entry (PT-SENTINEL-1, PT-SENTINEL-2).
 *   - Body chunking by byte size:
 *     Log Analytics: 30 MB max per request.
 *     Logs Ingestion: 1 MB max per request.
 *     Events larger than a single-request max are individually DLQ'd with
 *     an explicit error; no silent truncation.
 *
 * HMAC-SHA256 signing (Log Analytics variant):
 *   String-to-sign: METHOD + "\n" + CONTENT-LENGTH + "\n" + "application/json" + "\n" +
 *                   "x-ms-date:" + RFC1123-date + "\n" + RESOURCE
 *   RESOURCE: "/api/logs"
 *   Header: Authorization: SharedKey <workspaceId>:<base64(hmac)>
 *
 * @connexum/ai-governance
 */
import type { EventPayload } from '../event-bus';
/**
 * Resolves a KMS/secret-manager reference to the actual plaintext secret.
 * Injected at construction time. The resolved bytes never live in config state.
 */
export type SecretResolver = (secretRef: string) => Promise<string>;
/**
 * Caller-supplied callback that returns a valid Azure AD Bearer token.
 * The adapter does NOT implement the Azure AD OAuth flow.
 * This is intentional: OAuth flows require tenant IDs, client IDs, and client
 * secrets which are caller-managed and out of scope for the adapter layer.
 */
export type TokenProvider = () => Promise<string>;
/** Log Analytics Data Collector API configuration. */
export interface SentinelLogAnalyticsConfig {
    /** Discriminator for discriminated-union destination registries. */
    kind: 'sentinel-log-analytics';
    /**
     * Azure Log Analytics workspace ID (GUID).
     * Example: "12345678-1234-1234-1234-123456789012"
     */
    workspaceId: string;
    /**
     * KMS/secret-manager reference for the workspace shared key.
     * NEVER the raw key. Resolved at send-time via SecretResolver.
     * The resolved key is NEVER logged or stored (PT-SENTINEL-1).
     */
    sharedKeyRef: string;
    /**
     * Custom log type name. Written to Sentinel as <logType>_CL.
     * Max 100 chars, alphanumeric + underscore, must start with a letter.
     * Required.
     */
    logType: string;
    /**
     * Optional field name that holds the time the event was generated.
     * Passed as the time-generated-field header.
     */
    timeGeneratedField?: string;
    /**
     * Maximum uncompressed body size in bytes per request.
     * Azure hard limit is 30 MB. Default: 28_000_000 (safety margin).
     */
    maxBytesPerRequest?: number;
    /**
     * Enable gzip compression. Default: true.
     * Sends Content-Encoding: gzip.
     */
    compress?: boolean;
    /**
     * Compliance pack IDs governing this destination.
     * MANDATORY -- empty array throws UnboundDataError at construction.
     * Invariant: Thomas Directive 2026-04-22 (pack-binding primacy).
     */
    packBinding: string[];
    /** Directory for dead-letter queue. Required. */
    dlqDir: string;
    /**
     * Allow HTTP (non-TLS) endpoints.
     * Default: false. Set true ONLY in test environments.
     */
    allowInsecure?: boolean;
    /** Request timeout in ms. Default: 10000. */
    timeoutMs?: number;
    /** Maximum retry attempts on retryable errors. Default: 3. */
    maxRetries?: number;
    /** Base retry delay in ms. Doubles each attempt with +25% jitter. Default: 1000. */
    retryDelayMs?: number;
    /**
     * Override the endpoint base URL entirely (useful for tests or proxies).
     * When provided, workspaceId is still used for HMAC signing but NOT for
     * constructing the endpoint hostname.
     * Must be HTTPS unless allowInsecure is true.
     */
    baseUrl?: string;
}
/** Logs Ingestion API configuration. */
export interface SentinelLogsIngestionConfig {
    /** Discriminator for discriminated-union destination registries. */
    kind: 'sentinel-logs-ingestion';
    /**
     * Data Collection Endpoint (DCE) hostname or full base URL.
     * Example: "https://my-dce-abc123.eastus-1.ingest.monitor.azure.com"
     */
    dceEndpoint: string;
    /**
     * Immutable ID of the Data Collection Rule (DCR).
     * Example: "dcr-1234567890abcdef1234567890abcdef"
     */
    dcrImmutableId: string;
    /**
     * Stream name defined in the DCR schema.
     * Example: "Custom-GovernanceEvents_CL"
     */
    streamName: string;
    /**
     * Caller-supplied Bearer token provider.
     * The adapter calls this function once per deliver() to obtain a valid
     * Azure AD access token. Token caching and refresh are the caller's
     * responsibility. The token is NEVER logged or stored (PT-SENTINEL-2).
     */
    tokenProvider: TokenProvider;
    /**
     * Maximum uncompressed body size in bytes per request.
     * Azure hard limit is 1 MB. Default: 900_000 (safety margin).
     */
    maxBytesPerRequest?: number;
    /**
     * Enable gzip compression. Default: true.
     * Sends Content-Encoding: gzip.
     */
    compress?: boolean;
    /**
     * Compliance pack IDs governing this destination.
     * MANDATORY -- empty array throws UnboundDataError at construction.
     * Invariant: Thomas Directive 2026-04-22 (pack-binding primacy).
     */
    packBinding: string[];
    /** Directory for dead-letter queue. Required. */
    dlqDir: string;
    /**
     * Allow HTTP (non-TLS) endpoints.
     * Default: false. Set true ONLY in test environments.
     */
    allowInsecure?: boolean;
    /** Request timeout in ms. Default: 10000. */
    timeoutMs?: number;
    /** Maximum retry attempts on retryable errors. Default: 3. */
    maxRetries?: number;
    /** Base retry delay in ms. Doubles each attempt with +25% jitter. Default: 1000. */
    retryDelayMs?: number;
}
/** Discriminated union of both Sentinel config variants. */
export type SentinelConfig = SentinelLogAnalyticsConfig | SentinelLogsIngestionConfig;
export interface DeliveryResult {
    success: boolean;
    eventCount: number;
    statusCode?: number;
    attempts: number;
    error?: string;
    deliveredAt?: string;
    /** true = caller may retry later; false = permanent failure. */
    retryable?: boolean;
}
export interface DeadLetterEntry {
    events: EventPayload[];
    error: string;
    attempts: number;
    failedAt: string;
    retryable: boolean;
}
/**
 * Validate a Log-Type header value per Azure requirements:
 *   - 1 to 100 characters
 *   - Alphanumeric characters and underscores only
 *   - Must start with a letter
 */
export declare function validateLogType(logType: string): void;
/**
 * Validate that a URL is HTTPS unless allowInsecure is explicitly set.
 * Throws a descriptive error on failure.
 */
export declare function validateEndpointUrl(url: string, allowInsecure: boolean, label: string): void;
/**
 * Compute the RFC1123 date string required by Azure Log Analytics.
 * Format: "Thu, 30 Apr 2026 12:00:00 GMT"
 */
export declare function toRFC1123(date: Date): string;
/**
 * Build the canonical string-to-sign for Log Analytics HMAC-SHA256.
 *
 * Per Azure documentation:
 *   METHOD + "\n" + CONTENT-LENGTH + "\n" + "application/json" + "\n" +
 *   "x-ms-date:" + rfc1123date + "\n" + RESOURCE
 *
 * Where RESOURCE is "/api/logs".
 */
export declare function buildStringToSign(method: string, contentLength: number, rfc1123date: string): string;
/**
 * Compute the Authorization header value for the Log Analytics Data Collector API.
 *
 * Authorization: SharedKey <workspaceId>:<base64(HMAC-SHA256(stringToSign, sharedKey))>
 *
 * The sharedKey parameter is the decoded raw bytes (Buffer from base64).
 * This function is exported for test fixture verification only.
 * It must never be called with a key sourced from config state directly.
 */
export declare function buildLogAnalyticsAuthHeader(workspaceId: string, stringToSign: string, sharedKeyBytes: Buffer): string;
/**
 * Chunk an array of EventPayload objects into sub-arrays that respect
 * the per-request byte size limit.
 *
 * Events larger than maxBytesPerRequest are separated into a 'rejects' array
 * (they will be DLQ'd individually with an explicit oversized error).
 * No silent truncation occurs.
 */
export declare function chunkEventsByBytes(events: EventPayload[], maxBytesPerRequest: number): {
    chunks: EventPayload[][];
    oversized: EventPayload[];
};
/**
 * Compute exponential backoff with 25% jitter.
 *   delay = base * 2^(attempt-1) + random(0, base * 0.25)
 */
export declare function exponentialDelay(attempt: number, baseMs: number): number;
/**
 * Parse the Retry-After header value.
 * Accepts: integer seconds ("30") or HTTP-date ("Wed, 21 Oct 2015 07:28:00 GMT").
 * Returns milliseconds to wait, or undefined if unparseable.
 */
export declare function parseRetryAfter(headerValue: string | undefined): number | undefined;
export declare class SentinelLogAnalyticsDestination {
    private readonly cfg;
    private readonly resolver;
    private readonly dlqFile;
    private readonly endpointUrl;
    constructor(config: SentinelLogAnalyticsConfig, resolver: SecretResolver);
    /**
     * Deliver one or more governance events to Sentinel via Log Analytics API.
     *
     * Chunks events by byte size (max 30 MB per request by default).
     * Events that individually exceed the max are DLQ'd with an explicit error.
     * The workspace shared key is resolved per-call and never cached on the instance.
     */
    deliver(events: EventPayload[]): Promise<DeliveryResult>;
    /**
     * Flush alias for API symmetry. Log Analytics destination does not internally
     * buffer; deliver is always immediate. flush() is a no-op that returns success.
     */
    flush(): Promise<DeliveryResult>;
    /** Retrieve dead-letter queue entries (most recent `limit` entries). */
    getDLQ(limit?: number): DeadLetterEntry[];
    /**
     * POST one chunk of events to the Log Analytics Data Collector API.
     *
     * The shared key is accepted as a parameter and only used for HMAC signing.
     * It is never stored in instance state or written to any log (PT-SENTINEL-1).
     */
    private postChunk;
    /**
     * Execute the HTTPS POST to the Log Analytics Data Collector API.
     *
     * The Authorization header contains the HMAC signature derived from the
     * shared key. The raw shared key bytes are accepted as a parameter and
     * are NEVER logged or persisted in any way (PT-SENTINEL-1).
     */
    private httpPost;
    private writeDLQ;
}
export declare class SentinelLogsIngestionDestination {
    private readonly cfg;
    private readonly dlqFile;
    private readonly endpointUrl;
    constructor(config: SentinelLogsIngestionConfig);
    /**
     * Deliver one or more governance events to Sentinel via Logs Ingestion API.
     *
     * Chunks events by byte size (max 1 MB per request by default).
     * Events that individually exceed the max are DLQ'd with an explicit error.
     * The Bearer token is obtained per-call via tokenProvider and never cached
     * on the instance (PT-SENTINEL-2).
     */
    deliver(events: EventPayload[]): Promise<DeliveryResult>;
    /**
     * Flush alias for API symmetry. Logs Ingestion destination does not internally
     * buffer; deliver is always immediate. flush() is a no-op that returns success.
     */
    flush(): Promise<DeliveryResult>;
    /** Retrieve dead-letter queue entries (most recent `limit` entries). */
    getDLQ(limit?: number): DeadLetterEntry[];
    /**
     * POST one chunk of events to the Logs Ingestion API.
     *
     * The Bearer token is accepted as a parameter and used only in the
     * Authorization header. It is NEVER stored in instance state or logged
     * (PT-SENTINEL-2).
     */
    private postChunk;
    /**
     * Execute the HTTPS POST to the Logs Ingestion API.
     *
     * The Bearer token is accepted as a parameter and used only in the
     * Authorization header. It is NEVER logged or persisted (PT-SENTINEL-2).
     */
    private httpPost;
    private writeDLQ;
}
//# sourceMappingURL=sentinel.d.ts.map