type MaybePromise<T> = T | Promise<T>;
/**
 * A policy decision that allows the requested ability.
 */
export type GateAllowedDecision = {
    allowed: true;
};
/**
 * A policy decision that denies the requested ability.
 *
 * Use `reason`, `code`, and `details` to preserve structured denial context for
 * errors, audit logs, and tests.
 */
export type GateDeniedDecision = {
    allowed: false;
    reason?: string;
    code?: string;
    details?: unknown;
};
/**
 * Normalized authorization decision returned by gate inspection.
 */
export type GateDecision = GateAllowedDecision | GateDeniedDecision;
/**
 * Value a policy resolver may return.
 *
 * Returning `true`/`false` is convenient for simple policies. Return
 * `allow()`/`deny(...)` when the caller needs a denial reason, code, or
 * structured details.
 */
export type GatePolicyResult = boolean | GateDecision;
/**
 * Function that decides whether a context can perform an ability.
 *
 * The first argument is always the application context. Policies that operate
 * on a record receive that record as their second argument.
 */
export type PolicyResolver = (...args: never[]) => MaybePromise<GatePolicyResult>;
/**
 * Typed collection of ability resolvers created by `definePolicy(...)`.
 */
export type PolicyDefinition<TPolicies extends Record<string, PolicyResolver> = Record<string, PolicyResolver>> = {
    policies: TPolicies;
};
/**
 * Infer the application context type from a policy resolver.
 */
export type PolicyContext<TResolver> = TResolver extends (ctx: infer Ctx, ...args: never[]) => MaybePromise<GatePolicyResult> ? Ctx : never;
/**
 * Infer whether an ability needs a subject argument.
 */
export type PolicySubjectArgs<TResolver> = TResolver extends (...args: infer TArgs) => MaybePromise<GatePolicyResult> ? TArgs extends [unknown, infer Subject] ? [subject: Subject] : [] : [];
/**
 * One authorization check accepted by batch gate APIs.
 */
export type PolicyBatchCheck<TPolicies extends readonly PolicyDefinition[]> = {
    [TAbility in keyof PolicyMapFromDefinitions<TPolicies> & string]: readonly [
        ability: TAbility,
        ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>
    ];
}[keyof PolicyMapFromDefinitions<TPolicies> & string];
/**
 * Keyed authorization checks accepted by `inspectMany(...)` and `canMany(...)`.
 */
export type PolicyBatch<TPolicies extends readonly PolicyDefinition[]> = Record<string, PolicyBatchCheck<TPolicies>>;
/**
 * Full decision map returned by `inspectMany(...)`.
 */
export type PolicyBatchDecisionMap<TBatch extends PolicyBatch<readonly PolicyDefinition[]>> = {
    [TKey in keyof TBatch]: GateDecision;
};
/**
 * Boolean decision map returned by `canMany(...)`.
 */
export type PolicyBatchBooleanMap<TBatch extends PolicyBatch<readonly PolicyDefinition[]>> = {
    [TKey in keyof TBatch]: boolean;
};
/**
 * Gate method that produced a policy decision observation.
 */
export type GateDecisionSource = "can" | "inspect" | "authorize" | "canMany" | "inspectMany";
type UnionToIntersection<T> = (T extends unknown ? (value: T) => void : never) extends (value: infer U) => void ? U : never;
/**
 * Merge the ability maps from multiple policy definitions.
 */
export type PolicyMapFromDefinitions<TPolicies extends readonly PolicyDefinition[]> = UnionToIntersection<TPolicies[number] extends PolicyDefinition<infer TPolicyMap> ? TPolicyMap : never>;
/**
 * Infer the application context type shared by a list of policy definitions.
 */
export type PolicyContextFromDefinitions<TPolicies extends readonly PolicyDefinition[]> = PolicyContext<PolicyMapFromDefinitions<TPolicies>[keyof PolicyMapFromDefinitions<TPolicies>]>;
/**
 * Gate bound to a specific application context.
 *
 * Apps commonly attach this to request context as `ctx.gate` so use cases can
 * call `ctx.gate.authorize("posts.update", post)` without passing `ctx` back
 * into every authorization call.
 */
export type BoundGate<TPolicies extends readonly PolicyDefinition[]> = {
    /**
     * Type-only marker that keeps `TPolicies` inferable from a bound gate.
     * Runtime bound gates never implement this method. Method syntax keeps the
     * marker bivariant so readonly and mutable policy tuples stay compatible.
     */
    __policies?(policies: TPolicies): void;
    /**
     * Return only whether the ability is allowed.
     */
    can<TAbility extends keyof PolicyMapFromDefinitions<TPolicies> & string>(ability: TAbility, ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>): Promise<boolean>;
    /**
     * Return keyed boolean decisions for several abilities.
     */
    canMany<const TBatch extends PolicyBatch<TPolicies>>(checks: TBatch): Promise<PolicyBatchBooleanMap<TBatch>>;
    /**
     * Return the full allow/deny decision without throwing.
     */
    inspect<TAbility extends keyof PolicyMapFromDefinitions<TPolicies> & string>(ability: TAbility, ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>): Promise<GateDecision>;
    /**
     * Return keyed allow/deny decisions for several abilities.
     */
    inspectMany<const TBatch extends PolicyBatch<TPolicies>>(checks: TBatch): Promise<PolicyBatchDecisionMap<TBatch>>;
    /**
     * Return an allowed decision or throw for denied abilities.
     */
    authorize<TAbility extends keyof PolicyMapFromDefinitions<TPolicies> & string>(ability: TAbility, ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>): Promise<GateAllowedDecision>;
};
/**
 * Context shape contributed by `gate.attach(...)`.
 */
export type GateContext<TPolicies extends readonly PolicyDefinition[] = readonly PolicyDefinition[]> = {
    /**
     * Gate bound to the context that carries it.
     */
    gate: BoundGate<TPolicies>;
};
/**
 * App-facing authorization gate.
 *
 * The gate evaluates app-owned policies. It is not an authentication provider:
 * authenticate at the HTTP boundary first, then pass the resulting actor/user
 * data into policy context.
 */
export type GatePort<TContext, TPolicies extends readonly PolicyDefinition[] = readonly PolicyDefinition[]> = {
    /**
     * Bind this gate to a fixed context snapshot.
     *
     * This is the low-level primitive: the returned gate keeps evaluating
     * against the exact object it was bound to. Prefer `attach(...)` for app
     * context assembly so identity changes can never go stale.
     */
    bind(ctx: TContext): BoundGate<TPolicies>;
    /**
     * Attach a live `gate` property to a context object.
     *
     * The gate is exposed through a getter that re-binds against the receiving
     * object on every access, so in-place updates to fields such as `actor` or
     * `tenant` are always observed. The property is non-enumerable on purpose:
     * spreading the context (`{ ...ctx }`) drops the gate instead of silently
     * carrying a stale identity, and the next `ctx.gate` access fails loudly.
     */
    attach<C extends TContext & object>(ctx: C): C & GateContext<TPolicies>;
    /**
     * Return only whether the ability is allowed for a context.
     */
    can<TAbility extends keyof PolicyMapFromDefinitions<TPolicies> & string>(ctx: TContext, ability: TAbility, ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>): Promise<boolean>;
    /**
     * Return keyed boolean decisions for several abilities.
     */
    canMany<const TBatch extends PolicyBatch<TPolicies>>(ctx: TContext, checks: TBatch): Promise<PolicyBatchBooleanMap<TBatch>>;
    /**
     * Return the full allow/deny decision for a context without throwing.
     */
    inspect<TAbility extends keyof PolicyMapFromDefinitions<TPolicies> & string>(ctx: TContext, ability: TAbility, ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>): Promise<GateDecision>;
    /**
     * Return keyed allow/deny decisions for several abilities.
     */
    inspectMany<const TBatch extends PolicyBatch<TPolicies>>(ctx: TContext, checks: TBatch): Promise<PolicyBatchDecisionMap<TBatch>>;
    /**
     * Return an allowed decision or throw for denied abilities.
     */
    authorize<TAbility extends keyof PolicyMapFromDefinitions<TPolicies> & string>(ctx: TContext, ability: TAbility, ...subject: PolicySubjectArgs<PolicyMapFromDefinitions<TPolicies>[TAbility]>): Promise<GateAllowedDecision>;
};
/**
 * Hook used to convert a denied decision into an application-specific error.
 */
export type GateDenyHandler<TContext> = (decision: GateDeniedDecision, params: {
    ctx: TContext;
    ability: string;
    subject?: unknown;
}) => MaybePromise<Error | undefined>;
/**
 * Best-effort policy decision observation emitted by a gate.
 *
 * Observers are for diagnostics and audit-style integrations only. They do not
 * participate in authorization control flow and thrown/rejected observer errors
 * are ignored.
 */
export type GateDecisionObservation<TContext> = {
    /**
     * Gate method that produced the decision.
     */
    source: GateDecisionSource;
    /**
     * Key from a batch input object, when the decision came from a batch call.
     */
    batchKey?: string;
    /**
     * Application context used for policy evaluation.
     */
    ctx: TContext;
    /**
     * Ability being evaluated.
     */
    ability: string;
    /**
     * Optional subject passed to the policy.
     */
    subject?: unknown;
    /**
     * Normalized decision, when policy evaluation returned normally.
     */
    decision?: GateDecision;
    /**
     * Error thrown by the policy resolver, when evaluation failed.
     */
    error?: unknown;
    /**
     * Policy evaluation duration, excluding observer work.
     */
    durationMs: number;
    /**
     * Correlation fields copied from the context when present.
     */
    requestId?: string;
    traceId?: string;
    spanId?: string;
    parentSpanId?: string;
    traceparent?: string;
};
/**
 * Best-effort observer called after each gate decision or resolver error.
 */
export type GateDecisionObserver<TContext> = (observation: GateDecisionObservation<TContext>) => MaybePromise<void>;
/**
 * Options for `createGate(...)`.
 */
export type CreateGateOptions<TContext, TPolicies extends readonly PolicyDefinition[]> = {
    /**
     * Policy definitions to register.
     */
    policies: TPolicies;
    /**
     * Optional mapper for denied authorization decisions.
     */
    onDeny?: GateDenyHandler<TContext>;
    /**
     * Optional best-effort observer for policy decisions.
     *
     * This hook is diagnostic only: it cannot change decisions or thrown errors.
     */
    onDecision?: GateDecisionObserver<TContext>;
};
/**
 * Default error thrown by `authorize(...)` when a policy denies access.
 */
export declare class GateAuthorizationError extends Error {
    readonly code: string;
    readonly status = 403;
    readonly details?: unknown;
    constructor(decision?: GateDeniedDecision);
}
/**
 * Create an explicit allow decision.
 *
 * @returns A normalized gate decision with `allowed: true`.
 */
export declare function allow(): GateAllowedDecision;
/**
 * Create an explicit deny decision.
 *
 * @example
 * ```ts
 * return deny("Only owners can edit this post");
 * ```
 *
 * @param reasonOrDecision - Optional reason string or structured denial data.
 * @returns A normalized gate decision with `allowed: false`.
 */
export declare function deny(reasonOrDecision?: string | Omit<GateDeniedDecision, "allowed">): GateDeniedDecision;
/**
 * Define a typed group of authorization policies.
 *
 * Keep policy definitions near the feature that owns the business rule. The
 * returned definition is registered with `createGate(...)`.
 *
 * @example
 * ```ts
 * export const postPolicy = definePolicy({
 *   "posts.update": (ctx, post: Post) => post.authorId === ctx.actor.id,
 * });
 * ```
 *
 * @param policies - Ability resolver map keyed by stable ability names.
 * @returns A typed policy definition for registration with `createGate(...)`.
 */
export declare function definePolicy<const TPolicies extends Record<string, PolicyResolver>>(policies: TPolicies): PolicyDefinition<TPolicies>;
/**
 * Create an authorization gate from app-owned policy definitions.
 *
 * Register the gate as a port, then let the server context blueprint attach
 * it: `context: { gate: (ports) => ports.gate, ... }`. Use cases can then call
 * `ctx.gate.authorize(...)` for business authorization.
 *
 * @param options - Policy definitions and optional denial mapper.
 * @returns A gate port that can evaluate registered abilities.
 */
export declare function createGate<TContext, const TPolicies extends readonly PolicyDefinition[]>(options: CreateGateOptions<TContext, TPolicies>): GatePort<TContext, TPolicies>;
export {};
//# sourceMappingURL=policy.d.ts.map