/**
 * jwksIdentity — verify the caller's bearer token against a published key set.
 *
 * Pattern: Adapter (GoF) over `jose`, behind the vendor-neutral
 *          {@link IdentityVerifier} port.
 * Role:    the ONE identity verifier this release ships. It covers cloud IdPs
 *          and on-prem ones with the same code, because JWKS is the same
 *          protocol in both: a URL that publishes signing keys, and tokens
 *          signed by one of them.
 * Emits:   nothing. The door that called it reports the refusal — by CLASS.
 *
 * **Status: field-validated — an independent field trial, 2026-08-13.** The
 * trial pointed this adapter at a remote JWKS endpoint during a live,
 * cloud-backed host run (a real `nodeHost` in a live Google Cloud project,
 * sessions in a real Firestore) and verified an RS256 token end to end: issuer,
 * audience, expiry, subject and roles. A valid token paired with a CLAIMED
 * other identity was rejected; missing, expired and wrong-audience tokens each
 * answered 401; four different bearer tokens appeared in no captured response
 * body or error; and the remote key set was fetched once over the network, then
 * served from the cache below.
 *
 * Two bounds on that rung, so nobody reads more into it than happened. The
 * finding does not name the identity provider, so what is field-proven is the
 * PROTOCOL path — a real fetch, a real `jose` verification, a real cache — and
 * not interop with any particular commercial IdP. And the provider behind that
 * door was a deterministic mock: "401 before any model call" was measured as
 * *rejected requests made zero provider calls*, which is the cheapest-refusal
 * claim and not a statement about a real completion's cost.
 *
 * ── What it checks, and what it refuses to pretend to check ─────────────────
 * Signature (against the key the token's `kid` names, fetched and cached from
 * `jwksUrl`), `iss`, `aud`, `exp` and `nbf`. `exp` is REQUIRED: a signed token
 * with no lifetime is refused as `unverifiable` rather than honoured forever.
 * That is the whole list, and it is the whole list on purpose:
 *
 *   • **It is not an authorization decision.** A verified token proves WHO, not
 *     WHAT-THEY-MAY-DO. Roles and claims come back on the result so your own
 *     policy can decide; this adapter never reads them.
 *   • **It does not ask whether the token stands for a PERSON.** An app's own
 *     client-credentials token verifies here like a person's. When that
 *     matters — any IdP where every registered app can obtain a token for your
 *     API, which includes Entra ID — use `oidcIdentity`, whose person test
 *     refuses app-only tokens by name.
 *   • **It does not check revocation.** A JWT is valid until it expires, and no
 *     amount of key fetching changes that. Short lifetimes are the answer; an
 *     adapter that implied otherwise would be selling a guarantee the protocol
 *     does not make.
 *   • **`alg: none` cannot get through**, because a JWKS resolver has no key for
 *     it — verified against the real library rather than assumed (see the pin
 *     test). Neither can a token signed with an algorithm outside `algorithms`.
 *
 * ── The token never comes back out ──────────────────────────────────────────
 * Every failure is re-raised as {@link IdentityNotVerifiedError} carrying only
 * the CLASS — `expired`, `wrong-audience`, `wrong-issuer`, `not-yet-valid`,
 * `unverifiable`. The library's own message is dropped, and the original is
 * deliberately NOT attached as `cause`: a cause travels into every serializer
 * that walks own properties, and one `JSON.stringify` would undo all of this.
 * (The `sdkFailure` law, applied to a credential rather than to a cloud SDK.)
 *
 * A key set this adapter could not FETCH is a different fact and gets a
 * different class: {@link VerifierUnavailableError}, which the host answers 503
 * rather than 401. Your IdP being down is not the caller presenting a bad
 * token, and telling every client to re-authenticate against an unreachable
 * provider is the wrong instruction at the worst moment.
 *
 * @example
 *   const host = await standingAgent({
 *     agent, sessions, host: nodeHost({ port: 8080 }),
 *     identity: { verify: jwksIdentity({
 *       jwksUrl:  'https://idp.example.com/.well-known/jwks.json',
 *       issuer:   'https://idp.example.com/',
 *       audience: 'my-api',
 *     }).verify },
 *   });
 */
import type { IdentityVerifier } from '../../hosting/identityVerification.js';
import { type ClaimPath, type RolesFormat } from './verify/claims.js';
import { type JoseBackend } from './verify/jwtCore.js';
export { MissingJwksSupportError } from './verify/jwtCore.js';
export type { JoseBackend } from './verify/jwtCore.js';
export type { ClaimPath, RolesFormat } from './verify/claims.js';
export interface JwksIdentityOptions {
    /** Where the signing keys are published — an IdP's
     *  `.../.well-known/jwks.json`. */
    readonly jwksUrl: string;
    /** The `iss` every accepted token must carry. Required: a verifier that
     *  accepted any issuer would accept a token minted by anybody who publishes
     *  a key set. */
    readonly issuer: string | readonly string[];
    /** The `aud` every accepted token must carry — THIS API's name at the IdP.
     *  Required for the same reason: a token minted for a different service is
     *  a valid token, and honouring it is confused-deputy by construction. */
    readonly audience: string | readonly string[];
    /**
     * Which claim names the user. Default `'sub'` — the subject, which is what
     * `sub` means. Point it at `'email'`, `'oid'` or a namespaced claim when your
     * IdP's stable id lives elsewhere; a token whose chosen claim is missing or
     * blank is `unverifiable`, never silently anonymous.
     */
    readonly userIdClaim?: string;
    /**
     * Which claim carries roles. Default `'roles'`. A top-level name — a full
     * URI is fine, and a dotted name is never split — or a PATH into nested
     * objects: `['realm_access', 'roles']` for Keycloak's realm roles. ABSENT
     * on the result when the claim is absent. Never invented.
     */
    readonly rolesClaim?: ClaimPath;
    /**
     * How a roles claim holding a single STRING is read.
     *
     *  - `'list'` (default): the string is ONE role. `"Not bot-users"` is the
     *    role `Not bot-users`, so it can never satisfy a check for `bot-users`.
     *    An array contributes each string entry as one role.
     *  - `'space-delimited'`: the string is split on whitespace — the reading
     *    every release before this one used. Choose it only for a claim that
     *    really is a space-delimited list (an OAuth `scope` read as roles).
     */
    readonly rolesFormat?: RolesFormat;
    /**
     * Signature algorithms to accept. Default: the RSA and ECDSA families
     * (`RS256/384/512`, `PS256/384/512`, `ES256/384/512`).
     *
     * Symmetric algorithms (`HS*`) are deliberately NOT in the default: with a
     * JWKS the key is public, and a verifier that accepts an HMAC alg over a
     * published key is the classic algorithm-confusion forgery. Name them
     * explicitly if a deployment genuinely needs one and you know why.
     */
    readonly algorithms?: readonly string[];
    /** Seconds of clock skew tolerated on `exp`/`nbf`. Default 0 — the library
     *  does not decide how much drift your fleet has. */
    readonly clockToleranceSeconds?: number;
    /** How long a fetched key set is reused before re-fetching, in ms. Default
     *  is `jose`'s own (10 minutes). */
    readonly cacheMaxAgeMs?: number;
    /** Timeout for the key-set fetch, in ms. Default is `jose`'s own (5s). */
    readonly fetchTimeoutMs?: number;
    /**
     * An ALREADY-IMPORTED `jose`. Supply it and the lazy load never happens —
     * which is what makes this work in a BUNDLED app, where a bare specifier
     * reaches the runtime unresolved:
     *
     * ```ts
     * import * as jose from 'jose';
     * jwksIdentity({ jwksUrl, issuer, audience, backend: jose });
     * ```
     */
    readonly backend?: JoseBackend;
}
export declare function jwksIdentity(options: JwksIdentityOptions): IdentityVerifier;
