/**
 * @beignet/core/idempotency
 *
 * Idempotency primitives for retry-safe commands, webhooks, and jobs.
 */
/**
 * Value or promise of that value.
 */
export type MaybePromise<T> = T | Promise<T>;
/**
 * Primitive value accepted inside an idempotency scope object.
 */
export type IdempotencyScopeValue = string | number | boolean | null | undefined;
/**
 * Logical scope for idempotency keys.
 *
 * String scopes and object scopes are normalized with type tags so adapters can
 * build stable storage keys without primitive or delimiter collisions.
 */
export type IdempotencyScope = string | Record<string, IdempotencyScopeValue>;
/**
 * Scope mode that HTTP hooks can use when deriving an idempotency scope.
 */
export type IdempotencyScopeMode = "global" | "actor" | "tenant" | "actor-tenant";
/** Default lifetime for unfinished idempotency reservations. */
export declare const DEFAULT_IDEMPOTENCY_RESERVATION_TTL_SEC = 300;
/**
 * Contract metadata for idempotency-aware routes.
 *
 * This metadata is enforced at the HTTP boundary by
 * `createIdempotencyHooks(...)` from `@beignet/core/server`.
 * `runIdempotently(...)` remains the primitive for non-HTTP workflows such as
 * jobs, listeners, webhooks, and schedules.
 */
export interface IdempotencyMeta {
    /**
     * Whether this operation requires an idempotency key at the HTTP boundary.
     */
    required?: boolean;
    /**
     * Header that carries the idempotency key.
     *
     * Default: "idempotency-key".
     */
    header?: string;
    /**
     * How to scope idempotency keys when an HTTP hook derives the scope.
     *
     * By default the HTTP hook scopes to the actor and includes the tenant when
     * one is present. Use "global" explicitly only when every caller should
     * share one idempotency-key namespace for the operation.
     */
    scope?: IdempotencyScopeMode;
    /**
     * Time-to-live for completed replay results.
     */
    ttlSec?: number;
    /**
     * Time-to-live for unfinished reservations.
     *
     * @default 300
     */
    reservationTtlSec?: number;
}
/**
 * Input for reserving an idempotency key.
 */
export interface IdempotencyReserveInput {
    /**
     * Operation namespace, usually a use-case or route name.
     */
    namespace: string;
    /**
     * Client-provided idempotency key.
     */
    key: string;
    /**
     * Logical scope for this key.
     */
    scope?: IdempotencyScope;
    /**
     * Fingerprint of the logical command payload.
     */
    fingerprint: string;
    /**
     * Optional time-to-live for the completed replay result.
     */
    ttlSec?: number;
    /**
     * Time-to-live for unfinished work before a successor may reserve the key.
     *
     * @default 300
     */
    reservationTtlSec?: number;
}
/**
 * Result of reserving an idempotency key.
 */
export type IdempotencyReservation = {
    status: "reserved";
    namespace: string;
    key: string;
    scopeKey: string;
    fingerprint: string;
    reservationToken: string;
    reservedAt: Date;
    expiresAt: Date | null;
} | {
    status: "replay";
    namespace: string;
    key: string;
    scopeKey: string;
    fingerprint: string;
    result: unknown;
    reservedAt: Date;
    completedAt: Date;
    expiresAt: Date | null;
} | {
    status: "inProgress";
    namespace: string;
    key: string;
    scopeKey: string;
    fingerprint: string;
    reservedAt: Date;
    expiresAt: Date | null;
} | {
    status: "conflict";
    namespace: string;
    key: string;
    scopeKey: string;
    storedFingerprint: string;
    receivedFingerprint: string;
    reservedAt: Date;
    completedAt?: Date;
    expiresAt: Date | null;
};
/**
 * Input for marking an idempotency key complete.
 */
export interface IdempotencyCompleteInput {
    /**
     * Operation namespace.
     */
    namespace: string;
    /**
     * Client-provided idempotency key.
     */
    key: string;
    /**
     * Logical scope for this key.
     */
    scope?: IdempotencyScope;
    /**
     * Fingerprint that must match the reserved operation.
     */
    fingerprint: string;
    /** Opaque identity returned by the matching reserved result. */
    reservationToken: string;
    /**
     * Result to replay for future matching requests.
     */
    result?: unknown;
}
/**
 * Input for releasing or marking a failed idempotency reservation.
 */
export interface IdempotencyFailInput {
    /**
     * Operation namespace.
     */
    namespace: string;
    /**
     * Client-provided idempotency key.
     */
    key: string;
    /**
     * Logical scope for this key.
     */
    scope?: IdempotencyScope;
    /**
     * Fingerprint that must match the reserved operation.
     */
    fingerprint: string;
    /** Opaque identity returned by the matching reserved result. */
    reservationToken: string;
    /**
     * Error that caused the protected operation to fail.
     */
    error?: unknown;
}
/**
 * App-facing idempotency port.
 */
export interface IdempotencyPort {
    /**
     * Atomically reserve a key for work, replay an already completed result, or
     * report that the key is in progress/conflicting.
     */
    reserve(input: IdempotencyReserveInput): Promise<IdempotencyReservation>;
    /**
     * Mark a reserved key as complete and store the result that may be replayed.
     *
     * Implementations must reject when the fingerprint, reservation token, or
     * in-progress state no longer matches the current reservation.
     */
    complete(input: IdempotencyCompleteInput): Promise<void>;
    /**
     * Release or mark a reserved key after the protected work fails.
     *
     * Implementations must reject when the fingerprint, reservation token, or
     * in-progress state no longer matches the current reservation.
     */
    fail(input: IdempotencyFailInput): Promise<void>;
}
/**
 * Options for reserving an idempotency key around a protected operation.
 */
export interface RunIdempotentlyOptions<Result> extends IdempotencyReserveInput {
    /**
     * Protected operation to run after the key is reserved.
     */
    run: () => MaybePromise<Result>;
    /**
     * Replay behavior for completed matching reservations.
     *
     * Defaults to returning the stored result. Use `"error"` when callers need to
     * distinguish replay from first execution.
     */
    replay?: "return" | "error";
}
/**
 * Options for `createIdempotencyFingerprint(...)`.
 */
export interface CreateIdempotencyFingerprintOptions {
    /**
     * Omit values from the fingerprint input. Use this for the idempotency key
     * itself or other request metadata that does not define the logical command.
     *
     * String paths can be top-level keys (`"idempotencyKey"`) or dotted paths
     * (`"metadata.requestId"`). Array paths avoid ambiguity when keys contain
     * dots.
     */
    omit?: readonly (string | readonly string[])[];
}
/**
 * In-memory idempotency store for tests and local examples.
 */
export interface MemoryIdempotencyStore extends IdempotencyPort {
    /**
     * Current store entries.
     */
    readonly entries: readonly MemoryIdempotencyEntry[];
    /**
     * Remove all entries.
     */
    clear(): void;
}
/**
 * Snapshot entry from the memory idempotency store.
 */
export interface MemoryIdempotencyEntry {
    /**
     * Operation namespace.
     */
    namespace: string;
    /**
     * Client-provided idempotency key.
     */
    key: string;
    /**
     * Normalized scope key.
     */
    scopeKey: string;
    /**
     * Fingerprint of the logical command payload.
     */
    fingerprint: string;
    /** Opaque identity of the current in-progress reservation. */
    reservationToken: string;
    /**
     * Memory store status.
     */
    status: "in-progress" | "completed";
    /**
     * Stored result for completed entries.
     */
    result?: unknown;
    /**
     * Reservation timestamp.
     */
    reservedAt: Date;
    /**
     * Completion timestamp.
     */
    completedAt?: Date;
    /**
     * Expiration timestamp, or null for no expiration.
     */
    expiresAt: Date | null;
}
/**
 * Error thrown when an idempotency key is reused with a different fingerprint.
 */
export declare class IdempotencyConflictError extends Error {
    readonly namespace: string;
    readonly key: string;
    readonly scopeKey: string;
    readonly storedFingerprint: string;
    readonly receivedFingerprint: string;
    constructor(args: {
        namespace: string;
        key: string;
        scopeKey: string;
        storedFingerprint: string;
        receivedFingerprint: string;
    });
}
/**
 * Error thrown when an idempotency key is already reserved by in-progress work.
 */
export declare class IdempotencyInProgressError extends Error {
    readonly namespace: string;
    readonly key: string;
    readonly scopeKey: string;
    constructor(args: {
        namespace: string;
        key: string;
        scopeKey: string;
    });
}
/**
 * Error thrown when replay is disabled for a completed idempotency key.
 */
export declare class IdempotencyReplayError extends Error {
    readonly namespace: string;
    readonly key: string;
    readonly scopeKey: string;
    constructor(args: {
        namespace: string;
        key: string;
        scopeKey: string;
    });
}
/**
 * Error thrown when fingerprint input cannot be canonicalized.
 */
export declare class IdempotencyFingerprintError extends Error {
    constructor(message: string);
}
/**
 * Error thrown when a completion or failure mutation no longer owns the
 * matching in-progress reservation.
 */
export declare class IdempotencyMutationError extends Error {
    /** Mutation that failed to match the current reservation. */
    readonly action: "complete" | "fail";
    /** Operation namespace supplied to the failed mutation. */
    readonly namespace: string;
    /** Client-provided idempotency key supplied to the failed mutation. */
    readonly key: string;
    /** Normalized logical scope key supplied to the failed mutation. */
    readonly scopeKey: string;
    constructor(args: {
        action: "complete" | "fail";
        namespace: string;
        key: string;
        scope?: IdempotencyScope;
    });
}
/**
 * Normalize an idempotency scope into a stable string.
 */
export declare function normalizeIdempotencyScope(scope: IdempotencyScope | undefined): string;
/**
 * Create the stable storage key for an idempotency operation.
 */
export declare function createIdempotencyStorageKey(input: {
    namespace: string;
    key: string;
    scope?: IdempotencyScope;
}): string;
/**
 * Options for `createMemoryIdempotencyStore(...)`.
 */
export interface MemoryIdempotencyStoreOptions {
    /**
     * Clock used for reservation and completion timestamps. Defaults to the
     * system clock.
     */
    now?: () => Date;
    /** Token factory used for deterministic tests. */
    createReservationToken?: () => string;
}
/**
 * Create an in-memory idempotency store for tests and local examples.
 *
 * The memory store is process-local and not suitable for multi-process
 * production deployments.
 */
export declare function createMemoryIdempotencyStore(options?: MemoryIdempotencyStoreOptions): MemoryIdempotencyStore;
/**
 * Run an operation behind an idempotency reservation.
 *
 * The flow is: reserve the key, replay completed matching results, reject
 * in-progress/conflicting keys, run the operation for new reservations, then
 * complete or fail the reservation. Callers are responsible for choosing a
 * namespace, scope, key, and fingerprint that match their business operation.
 */
export declare function runIdempotently<Result>(idempotency: IdempotencyPort, options: RunIdempotentlyOptions<Result>): Promise<Result>;
/**
 * Create a SHA-256 fingerprint from a canonicalized value.
 *
 * Object keys are sorted, `undefined` and functions are omitted, `Date` values
 * become ISO strings, BigInts become strings, and circular or non-finite values
 * throw. Exact omit paths may be supplied as dotted strings or string arrays.
 */
export declare function createIdempotencyFingerprint(value: unknown, options?: CreateIdempotencyFingerprintOptions): Promise<string>;
//# sourceMappingURL=index.d.ts.map