/**
 * Route-level HTTP authentication primitives.
 *
 * Strategy helpers return an {@link AuthFn} for route factories. Verifier
 * helpers are lower-level pure functions for custom `fetch` handlers.
 */
import type { SessionAuthContext } from "#channel/types.js";
import { type RuntimeIpAllowList } from "#runtime/governance/network/ip-allow-list.js";
/**
 * Result returned by the verifier helpers below. On success, `sessionAuth`
 * is a fully-constructed {@link SessionAuthContext}; on failure no detail is
 * returned so routes do not leak which credential check failed.
 */
export type VerifyResult = {
    readonly ok: true;
    readonly sessionAuth: SessionAuthContext;
} | {
    readonly ok: false;
};
/**
 * Credentials accepted by {@link verifyHttpBasic}.
 */
export interface HttpBasicCredentials {
    readonly username: string;
    readonly password: string;
}
/**
 * Verifies an HTTP Basic credential against the supplied username and
 * password. Returns `{ ok: true, sessionAuth }` on success or `{ ok: false }`
 * on a missing or mismatched credential. The password is compared with
 * constant-time hash equality so a timing side channel cannot leak it; the
 * username is compared directly.
 */
export declare function verifyHttpBasic(authorizationHeader: string | null, credentials: HttpBasicCredentials): VerifyResult;
/**
 * Configuration for {@link verifyJwtHmac}. Optional fields have defaults so
 * adapters can omit unused matchers. `secret` is read by the adapter from its
 * secret store (e.g. `process.env`) and passed in directly.
 */
export interface VerifyJwtHmacConfig {
    readonly algorithm: "HS256" | "HS384" | "HS512";
    readonly audiences: readonly string[];
    readonly issuer: string;
    readonly secret: string;
    /**
     * Tolerance in seconds for the `exp` and `nbf` claims. Defaults to 30.
     */
    readonly clockSkewSeconds?: number;
    /**
     * AWS IAM-style `*`-wildcard patterns matched against the token `sub`.
     * When supplied, the token is rejected unless one matches.
     */
    readonly subjects?: readonly string[];
    /**
     * Per-claim membership matcher: each named claim must contain at least one
     * of the listed values, or the token is rejected.
     */
    readonly claims?: Readonly<Record<string, readonly string[]>>;
}
/**
 * Verifies a bearer JWT signed with an HMAC secret. Pass the token without
 * the `Bearer ` prefix (see {@link extractBearerToken}). Returns
 * `{ ok: true, sessionAuth }` on success or `{ ok: false }` when verification
 * fails or the token's claims don't match the supplied matchers.
 */
export declare function verifyJwtHmac(token: string | null, config: VerifyJwtHmacConfig): Promise<VerifyResult>;
/**
 * Configuration for {@link verifyJwtEcdsa}.
 */
export interface VerifyJwtEcdsaConfig {
    readonly algorithm: "ES256" | "ES384" | "ES512";
    readonly audiences: readonly string[];
    readonly issuer: string;
    /**
     * PEM-encoded ECDSA public key (`-----BEGIN PUBLIC KEY-----` ...).
     */
    readonly publicKey: string;
    /**
     * Tolerance in seconds for the `exp` and `nbf` claims. Defaults to 30.
     */
    readonly clockSkewSeconds?: number;
    /**
     * AWS IAM-style `*`-wildcard patterns matched against the token `sub`.
     * When supplied, the token is rejected unless one matches.
     */
    readonly subjects?: readonly string[];
    /**
     * Per-claim membership matcher: each named claim must contain at least one
     * of the listed values, or the token is rejected.
     */
    readonly claims?: Readonly<Record<string, readonly string[]>>;
}
/**
 * Verifies a bearer JWT signed with an ECDSA private key against the supplied
 * PEM public key. Pass the token without the `Bearer ` prefix (see
 * {@link extractBearerToken}). Returns `{ ok: true, sessionAuth }` on success
 * or `{ ok: false }` when verification fails or the token's claims do not
 * match the configured `subjects`/`claims`.
 */
export declare function verifyJwtEcdsa(token: string | null, config: VerifyJwtEcdsaConfig): Promise<VerifyResult>;
/**
 * Configuration for {@link verifyOidc}.
 */
export interface VerifyOidcConfig {
    readonly audiences: readonly string[];
    readonly issuer: string;
    /**
     * OIDC discovery URL. Defaults to
     * `${issuer}/.well-known/openid-configuration` (any trailing slash on
     * `issuer` is stripped first).
     */
    readonly discoveryUrl?: string;
    /**
     * Tolerance in seconds for the `exp` and `nbf` claims. Defaults to 30.
     */
    readonly clockSkewSeconds?: number;
    /**
     * AWS IAM-style `*`-wildcard patterns matched against the token `sub`.
     * When supplied, the token is rejected unless one matches.
     */
    readonly subjects?: readonly string[];
    /**
     * Per-claim membership matcher: each named claim must contain at least one
     * of the listed values, or the token is rejected.
     */
    readonly claims?: Readonly<Record<string, readonly string[]>>;
}
/**
 * Verifies a bearer OIDC token against an issuer's discovery URL. Pass the
 * token without the `Bearer ` prefix (see {@link extractBearerToken}). The
 * token must satisfy the configured `subjects`/`claims` matchers; on success
 * the principal is tagged `principalType: "service"`. Unlike
 * {@link verifyVercelOidc}, this never grants the Vercel current-project
 * bypass. Returns `{ ok: false }` on failed verification or matchers.
 */
export declare function verifyOidc(token: string | null, config: VerifyOidcConfig): Promise<VerifyResult>;
/**
 * Extracts the bearer token from an `Authorization: Bearer <token>` header.
 * Returns `null` if the header is missing, the scheme isn't `Bearer`, or the
 * value after `Bearer ` is empty.
 */
export declare function extractBearerToken(authorizationHeader: string | null): string | null;
/**
 * Parsed IP allowlist for repeated checks. Construct once at module load,
 * then call {@link isIpAllowed} per request.
 */
export type IpAllowList = RuntimeIpAllowList;
/**
 * Parses exact IP addresses or CIDR blocks into a reusable
 * {@link IpAllowList}. Entries are trimmed; throws on an empty entry, a `*`
 * wildcard (use exact IP/CIDR syntax), or an invalid address or CIDR prefix.
 */
export declare function createIpAllowList(entries: readonly string[]): IpAllowList;
/**
 * Returns whether `ip` is permitted by `allowList`. `null` always returns
 * `false`. Adapters that need to allow unknown IPs should not call this.
 */
export declare function isIpAllowed(ip: string | null, allowList: IpAllowList): boolean;
/**
 * One challenge entry attached to the `www-authenticate` header on a failure
 * response. For a Basic+Bearer prompt, pass both:
 * `[{ scheme: "Basic", parameters: { realm: "agent" } }, { scheme: "Bearer" }]`
 */
export interface UnauthorizedChallenge {
    readonly scheme: "Basic" | "Bearer";
    readonly parameters?: Readonly<Record<string, string>>;
}
/**
 * Options accepted by {@link createUnauthorizedResponse}.
 */
export interface UnauthorizedResponseOptions {
    /**
     * HTTP status code. Defaults to `401`. Use `403` for "authenticated but
     * not allowed" outcomes.
     */
    readonly status?: 401 | 403;
    /**
     * Machine-readable error code returned in the JSON body. Defaults to
     * `"unauthorized"` (401) or `"forbidden"` (403).
     */
    readonly code?: string;
    /**
     * Human-readable error message returned in the JSON body. Defaults to a
     * generic prompt.
     */
    readonly message?: string;
    /**
     * Optional `www-authenticate` challenge entries.
     */
    readonly challenges?: readonly UnauthorizedChallenge[];
}
/**
 * Builds a JSON failure response shaped like the framework's other auth
 * failures: `cache-control: no-store`, one `www-authenticate` header per
 * challenge, and a `{ ok: false, code, error }` body.
 */
export declare function createUnauthorizedResponse(opts?: UnauthorizedResponseOptions): Response;
/**
 * Options accepted by auth error classes. The class chooses the HTTP status.
 */
export type AuthErrorOptions = Omit<UnauthorizedResponseOptions, "status">;
/**
 * Error thrown by auth callbacks to reject a route with a structured 401
 * response. `routeAuth` catches it and returns its response; other errors
 * propagate through the normal channel failure path.
 */
export declare class UnauthenticatedError extends Error {
    readonly response: Response;
    constructor(opts?: AuthErrorOptions);
}
/**
 * Error thrown by auth callbacks to reject a route with a structured 403
 * response. `routeAuth` catches it and returns its response; other errors
 * propagate through the normal channel failure path.
 */
export declare class ForbiddenError extends Error {
    readonly response: Response;
    constructor(opts?: AuthErrorOptions);
}
/**
 * Route auth callback. Returned value semantics inside {@link routeAuth}:
 *
 * - A {@link SessionAuthContext} accepts the request and halts the walk.
 * - `null` or `undefined` skips to the next entry.
 *
 * If every entry skips (including the empty `[]` case), the walker returns a
 * 401. To reject with a specific response, throw an
 * {@link UnauthenticatedError} or {@link ForbiddenError}. To accept anonymous
 * traffic, include {@link none} as the final entry.
 */
export type AuthFn<TEvent = Request> = (event: TEvent) => SessionAuthContext | null | undefined | Promise<SessionAuthContext | null | undefined>;
/**
 * Walks an `AuthFn` (or array) in order against `request`. The first entry
 * returning a {@link SessionAuthContext} wins; entries returning `null` or
 * `undefined` are skipped. If the walk exhausts without a winner (including
 * the empty-array case), returns a 401 {@link createUnauthorizedResponse}.
 *
 * Channel factories that share this resolution policy (e.g. `eveChannel`, or
 * a custom `defineChannel` route handler) should call `routeAuth` rather than
 * re-implement the walk.
 */
export declare function routeAuth(request: Request, auth: AuthFn<Request> | readonly AuthFn<Request>[]): Promise<SessionAuthContext | Response>;
/**
 * Returns an {@link AuthFn} for scaffolded apps that makes unfinished
 * production auth fail as an intentional 401 rather than an internal route
 * error. Replace it before serving real users:
 *
 * ```ts
 * eveChannel({ auth: [localDev(), vercelOidc(), placeholderAuth()] });
 * ```
 *
 * Outside production it returns `null`, so the auth walk keeps the same local
 * development behavior as any other skipped entry.
 */
export declare function placeholderAuth(): AuthFn<Request>;
/**
 * Returns an {@link AuthFn} that accepts any request anonymously, producing
 * a synthetic principal with `principalType: "anonymous"`. Use it as the
 * final entry in an `auth` array to opt routes into unauthenticated access:
 *
 * ```ts
 * eveChannel({ auth: [none()] }); // every request accepted anonymously
 * ```
 *
 * The returned `SessionAuthContext` halts the {@link routeAuth} walk, so
 * `none()` terminates whatever array it appears in. It ignores its event
 * argument, so `TEvent` is inferred from the surrounding array (defaulting
 * to `unknown`) and composes with `AuthFn<Request>` entries without a type
 * argument.
 */
export declare function none<TEvent = unknown>(): AuthFn<TEvent>;
/**
 * Returns an {@link AuthFn} that authenticates requests during local
 * development, keyed on the request URL's hostname (not the host process).
 * A hostname is treated as loopback when it is `localhost` or any
 * `*.localhost` subdomain (RFC 6761 routes the `.localhost` TLD to
 * loopback), any IPv4 in `127.0.0.0/8`, or the IPv6 loopback `::1`.
 *
 * Matching requests get a synthetic principal with `principalType:
 * "local-dev"`. Every other request returns `null`, skipping to the next
 * entry under {@link routeAuth}, which makes `[localDev(), vercelOidc()]`
 * the canonical "open on localhost, Vercel OIDC in prod" pattern.
 *
 * The check is not based on bare `process.env.VERCEL`: a deployment
 * outside Vercel (Fly, Railway, raw container) leaves `VERCEL` unset and
 * would then accept every public request. The one process-level exception
 * is `vercel dev`, detected by `VERCEL=1` and `VERCEL_ENV=development`
 * together. Only the local `vercel dev` server sets that pair (preview and
 * production report `VERCEL_ENV=preview`/`production`), so it opens the
 * dev server (which may serve over a non-loopback host) without opening a
 * real deployment.
 *
 * Caveat: this assumes a sane edge in front of public origins. An origin
 * that trusts an attacker-controlled `Host` header (no CDN, no normalizing
 * reverse proxy) lets an attacker spoof `Host: localhost` and reach
 * `localDev()`. Layer a real authenticator on such deployments.
 */
export declare function localDev(): AuthFn<Request>;
/**
 * Options for {@link verifyVercelOidc} and {@link vercelOidc}.
 */
export interface VerifyVercelOidcOptions {
    /**
     * Optional `sub` patterns granting callers access on top of the always-on
     * current-project bypass. Patterns use AWS IAM-style `*` wildcards and may
     * target tokens minted by other Vercel projects (e.g.
     * `"owner:acme:project:partner-agent:environment:*"`). The current project
     * is always accepted regardless of this list.
     */
    readonly subjects?: readonly string[];
}
/**
 * Verifies a bearer JWT minted by Vercel OIDC.
 *
 * Acceptance rule:
 *
 * - Tokens whose `project_id` matches `VERCEL_PROJECT_ID` are **always**
 *   accepted regardless of `subjects`, so the deployment's own runtime
 *   callers (subagent, internal fetches) authenticate without being
 *   enumerated.
 * - Tokens with an `external_sub` claim authenticate as
 *   `principalType: "user"` when they match the current `VERCEL_PROJECT_ID`
 *   (if set) and `VERCEL_TARGET_ENV` / `VERCEL_ENV` (if set). `external_sub`
 *   becomes the Eve subject, `external_iss` or `connector_id` the Eve issuer
 *   when present, and string-valued OIDC profile claims (`name`, `picture`,
 *   `email`) are exposed as auth attributes.
 * - Tokens from other Vercel projects are accepted **only** when their `sub`
 *   matches one of {@link VerifyVercelOidcOptions.subjects}.
 *
 * The `environment` claim is not constrained: production, preview, and
 * development tokens for the current project all authenticate. Non-user
 * principals are tagged `"runtime"` when the token's `environment` matches
 * the current deployment, otherwise `"service"`.
 */
export declare function verifyVercelOidc(token: string | null, opts?: VerifyVercelOidcOptions): Promise<VerifyResult>;
/**
 * Allowed values for {@link VercelSubjectInput.environment}. Use `"*"`
 * to match any of `production`, `preview`, and `development` for the
 * named project.
 */
export type VercelSubjectEnvironment = "production" | "preview" | "development" | "*";
/**
 * Strict input shape accepted by {@link vercelSubject}.
 *
 * The `sub` claim carries human-readable slugs/names, not IDs. Stable
 * project and team IDs (`prj_...`, `team_...`) live on the separate
 * `project_id` / `owner_id` claims, which `verifyVercelOidc` matches
 * against `VERCEL_PROJECT_ID` for the current-project bind. This helper
 * composes a `sub` matcher, so its inputs are slugs.
 */
export interface VercelSubjectInput {
    /**
     * Vercel team slug (a.k.a. "owner"; e.g. `"acme"`) as embedded in the
     * `sub` claim, **not** the stable team ID `team_...` (`VERCEL_TEAM_ID`).
     *
     * Must not contain `*` or `:` so authors cannot widen the matcher to
     * "any team with a project of this name". Hand-write the subject string
     * when cross-team federation is intentional.
     */
    readonly teamSlug: string;
    /**
     * Vercel project name (e.g. `"acme_website"`) as embedded in the `sub`
     * claim, **not** the stable project ID `prj_...` (`VERCEL_PROJECT_ID`).
     * Same constraints as {@link teamSlug}.
     */
    readonly projectName: string;
    /**
     * Vercel deployment environment, or `"*"` to match any environment for
     * the named project. Defaults to `"production"` so an unspecified
     * environment cannot silently accept preview/development tokens.
     */
    readonly environment?: VercelSubjectEnvironment;
}
/**
 * Builds a Vercel OIDC `sub` matcher pattern from a typed input.
 *
 * Vercel-issued tokens carry a `sub` of the form
 * `owner:[TEAM_SLUG]:project:[PROJECT_NAME]:environment:[ENVIRONMENT]`.
 * Hand-writing it invites two foot-guns: a misspelled slug (silently
 * rejecting all callers) and over-broad wildcards (silently accepting
 * unrelated callers). This helper rejects malformed inputs at construction
 * time and forces an explicit `environment`.
 *
 * Use it inside {@link VerifyVercelOidcOptions.subjects} to layer
 * additional Vercel-project callers on top of the current-project bypass:
 *
 * ```ts
 * vercelOidc({
 *   subjects: [vercelSubject({ teamSlug: "partner", projectName: "data" })],
 * });
 * ```
 *
 * The `sub` claim flips when a team or project name changes, so any policy
 * built on this helper must update with it; the stable team/project IDs are
 * not exposed in `sub`. See Vercel's OIDC reference for the token anatomy.
 */
export declare function vercelSubject(input: VercelSubjectInput): string;
/**
 * Returns an HTTP route auth callback backed by Vercel OIDC. See
 * {@link verifyVercelOidc} for the always-on current-project bypass and how
 * `subjects` extends acceptance to other Vercel projects.
 */
export declare function vercelOidc(opts?: VerifyVercelOidcOptions): AuthFn<Request>;
/** Returns an {@link AuthFn} that verifies HTTP Basic credentials via {@link verifyHttpBasic}. */
export declare function httpBasic(credentials: HttpBasicCredentials): AuthFn<Request>;
/** Returns an {@link AuthFn} that verifies an HMAC-signed bearer JWT via {@link verifyJwtHmac}. */
export declare function jwtHmac(config: VerifyJwtHmacConfig): AuthFn<Request>;
/** Returns an {@link AuthFn} that verifies an ECDSA-signed bearer JWT via {@link verifyJwtEcdsa}. */
export declare function jwtEcdsa(config: VerifyJwtEcdsaConfig): AuthFn<Request>;
/**
 * Returns an {@link AuthFn} that verifies an OIDC bearer token on the inbound
 * request via {@link verifyOidc}. Use {@link vercelOidc} instead for
 * Vercel-issued tokens: it preconfigures the issuer, audience, and runtime
 * principal flag.
 */
export declare function oidc(config: VerifyOidcConfig): AuthFn<Request>;
