/**
 * remote/dpop — minimal RFC 9449 DPoP primitives for device-bound sub-tokens (P1b).
 *
 * The default sub-token (T6f) is a bearer : whoever holds the string can use
 * it until expiry. That is acceptable for paste-and-go handoff but unsafe
 * when the QR is captured (clipboard hostile, screen capture, photo of
 * laptop). P1b binds a sub-token to a specific device's keypair via a `cnf`
 * (confirmation) claim — RFC 9449 §6.1 + RFC 7800. The server then requires
 * every request to carry a fresh DPoP proof JWT signed by that device's key.
 *
 * Stolen sub-token alone → useless. Stolen sub-token + stolen private key →
 * still attacker would need physical access to the device's secure storage
 * (IndexedDB-backed P-256 in the PWA, OS keychain elsewhere).
 *
 * Scope of this module
 * --------------------
 *   - `computeJwkThumbprint(jwk)` : RFC 7638 thumbprint (sha256 over the
 *     canonical members of the JWK, base64url). The `jkt` claim value.
 *   - `validateDpopProof(dpopJwt, opts)` : verifies a DPoP JWT against
 *     `expectedJkt`, expected HTTP method (`htm`), expected URL (`htu`),
 *     iat freshness, jti uniqueness, and the embedded JWK signature.
 *   - `DpopReplayStore` : in-process jti deny-list with TTL ; the host
 *     plugs its own store (Redis, SQLite) when scaled out.
 *
 * Crypto choice
 * -------------
 * P-256 / ES256 only for v1. WebCrypto exposes `ECDSA` verify with
 * `namedCurve: P-256` in both Node 20+ (`globalThis.crypto.subtle`) AND
 * every modern browser without a polyfill. The SDK stays free of `jose`
 * (which the legacy CC backend uses) so the bundle stays small enough
 * for the PWA. RFC 9449 also permits RS256/PS256/ES384/ES512 ; those are
 * out of scope for v1 (no observed need + each adds an algorithm branch
 * to the verifier).
 *
 * @public @since 2.24.0 — preste P1b (DPoP device-binding primitives)
 */
/**
 * JWK for an ECDSA P-256 key (RFC 7517 §3 + RFC 7518 §6.2).
 * Only the public-key members are required at the verifier side ; `d`
 * (private scalar) is rejected if present (a DPoP header MUST carry a
 * public key only).
 */
export interface EcP256Jwk {
    kty: "EC";
    crv: "P-256";
    /** x coordinate, base64url. */
    x: string;
    /** y coordinate, base64url. */
    y: string;
    /** Algorithm hint. Optional in spec ; when present, MUST be "ES256". */
    alg?: "ES256";
    use?: "sig";
    /** Private scalar — MUST NOT be present in a DPoP header. */
    d?: never;
}
/** Decoded DPoP proof claims (RFC 9449 §4.2). */
export interface DpopClaims {
    /** HTTP method (uppercase). */
    htm: string;
    /** HTTP URL — scheme + host + path, no query / fragment. */
    htu: string;
    /** Issued-at, Unix seconds. */
    iat: number;
    /** Unique proof id (replay protection). */
    jti: string;
    /**
     * Optional hash of the access token (RFC 9449 §4.3) — sha256 of the
     * token, base64url. When present, validators MUST cross-check the
     * presented sub-token against this hash.
     */
    ath?: string;
}
/**
 * Compute the SHA-256 JWK thumbprint of an EC P-256 public key per
 * RFC 7638. The canonical members for `kty:EC` are `{crv, kty, x, y}`,
 * sorted lexicographically, JSON-serialised with no whitespace.
 *
 * The resulting base64url-encoded digest is the `jkt` claim value
 * embedded in a sub-token's `cnf` field and the `jkt` attribute on
 * `validateDpopProof` calls.
 *
 * Exported for clients that need to compute their own device's jkt
 * (e.g. the PWA at first launch, to send up to the server during the
 * device-bind handshake).
 */
export declare function computeJwkThumbprint(jwk: EcP256Jwk): string;
/** Options for `validateDpopProof`. */
export interface ValidateDpopOptions {
    /**
     * Expected JWK thumbprint (the `jkt` from the sub-token's `cnf` claim).
     * The DPoP header's embedded JWK MUST thumbprint to this value.
     */
    expectedJkt: string;
    /** Expected HTTP method (uppercase). */
    expectedHtm: string;
    /**
     * Expected HTTP URL — scheme + host + path. Query string + fragment
     * stripped before compare (htu has no query/fragment per spec).
     */
    expectedHtu: string;
    /** Optional access token to cross-check via `ath`. */
    accessToken?: string;
    /**
     * Maximum clock skew + age in seconds. Default 60. Proofs older than
     * `now - maxAgeSec` are rejected (replay window).
     */
    maxAgeSec?: number;
    /** Optional clock injection (defaults to Date.now()). */
    now?: () => number;
    /**
     * Replay-protection callback. Returns true if the jti has been seen
     * within the maxAge window. The validator throws when the callback
     * returns true ; the host is expected to call back with `false` AND
     * persist the jti when the proof is otherwise valid.
     */
    isReplayed?: (jti: string) => boolean;
    /** Callback to record a freshly-validated jti for future replay checks. */
    recordJti?: (jti: string, expiresAtMs: number) => void;
}
/** Validated DPoP proof outcome. */
export interface ValidatedDpop {
    valid: true;
    /** Confirmed thumbprint (matches expectedJkt). */
    jkt: string;
    /** Confirmed claims. */
    claims: DpopClaims;
}
/** Failure outcome. Brief reason for logs ; never throws on bad input. */
export interface DpopValidationFailure {
    valid: false;
    reason: string;
}
export type DpopValidationResult = ValidatedDpop | DpopValidationFailure;
/**
 * Validate a DPoP proof JWT. Returns the resolved jkt + claims on success
 * or a typed failure with a brief reason ; NEVER throws (the caller
 * decides whether to log, deny, or surface to the user). Mirrors the
 * `verifySubToken` contract.
 *
 * Validation steps (RFC 9449 §4.3 subset) :
 *   1. Three-segment JWT structure.
 *   2. Header : `typ === "dpop+jwt"`, `alg` allowlisted, `jwk` present
 *      and EC P-256 (no `d` claim allowed).
 *   3. Computed thumbprint matches `expectedJkt`.
 *   4. Payload : `htm` matches, `htu` matches, `iat` not in the future,
 *      `iat` not older than `maxAgeSec`, `jti` present.
 *   5. Optional : `ath` matches sha256(accessToken).
 *   6. Optional : `isReplayed(jti)` returns false.
 *   7. Signature : `subtle.verify('ECDSA', publicKey, sig, data)` over
 *      `header.payload` bytes with `hash: SHA-256`.
 *
 * On success, calls `recordJti(jti, exp)` if supplied so the host can
 * persist the proof for future replay detection.
 */
export declare function validateDpopProof(dpopJwt: string, opts: ValidateDpopOptions): Promise<DpopValidationResult>;
/**
 * Bounded in-process jti deny-list. Entries auto-expire after their
 * `maxAge` window. The host plugs in a shared store (Redis, SQLite via
 * `PersistencePort`) when scaled out — the SDK only ships the local
 * impl as a starting point.
 */
export declare class DpopReplayStore {
    private readonly seen;
    private readonly maxSize;
    constructor(opts?: {
        maxSize?: number;
    });
    /** Returns true if `jti` is within an unexpired window. */
    isReplayed(jti: string, nowMs?: number): boolean;
    /** Record a jti as seen with its expiry timestamp. */
    record(jti: string, expiresAtMs: number): void;
    /** Wipe — test helper. */
    reset(): void;
    /** Current size — test / observability helper. */
    get size(): number;
    private gcExpired;
}
//# sourceMappingURL=dpop.d.ts.map