/**
 * AAuth verification middleware for Neotoma's MCP endpoint.
 *
 * Implements RFC 9421 HTTP Message Signatures verification with the AAuth
 * profile (agent-token JWT carried in the `Signature-Key` header). The
 * middleware is **non-blocking**: requests without AAuth headers are passed
 * through untouched so existing OAuth / bearer-token clients keep working.
 *
 * When AAuth headers *are* present and verification succeeds, the request is
 * annotated with an {@link AAuthRequestContext} at `req.aauth` for downstream
 * code (the MCP handler threads it into {@link NeotomaServer} and write-path
 * services stamp it into provenance).
 *
 * When verification fails (bad signature, expired JWT, JWKS fetch error),
 * the middleware logs a warning and — in the default (non-strict) mode —
 * treats the request as unauthenticated; it does NOT reject with 401.
 * Rationale: Phase 1 rolls AAuth out alongside existing auth; failing closed
 * would break every OAuth client the moment a misbehaving agent sends a
 * malformed signature. Set `NEOTOMA_AAUTH_STRICT=1` (or `options.strict`) to
 * reject signed-but-invalid requests with 401. Unsigned requests continue
 * to flow through even in strict mode so OAuth / Bearer clients keep
 * working. See docs/reports/security_audit_2026_04_22.md S-6.
 *
 * See the AAuth Neotoma integration plan and
 * docs/proposals/agent-trust-framework.md.
 */
import type { NextFunction, Request, Response } from "express";
import type { AAuthRequestContext, AttributionDecisionDiagnostics } from "../crypto/agent_identity.js";
/**
 * Options for {@link aauthVerify}.
 *
 * - `authority` is mandatory per AAuth §10.3.1 — the canonical host the
 *   server accepts signatures for. Using the request's own Host header is
 *   explicitly unsafe (an attacker could smuggle `@authority` via
 *   `Host: attacker.example`).
 * - `jwksCacheTtlMs` defaults to the httpsig library's 1h.
 * - `maxClockSkewSec` defaults to 60s.
 * - `strict` (docs/reports/security_audit_2026_04_22.md S-6): when true,
 *   signed requests that fail verification are rejected with 401 instead of
 *   falling through as unauthenticated. Unsigned requests are still passed
 *   through so OAuth / bearer clients keep working. Controlled at runtime by
 *   `NEOTOMA_AAUTH_STRICT=1` when the caller does not set this explicitly.
 */
export interface AAuthVerifyOptions {
    /** Canonical authority, e.g. `"neotoma.io"` or `"localhost:3080"`. */
    authority: string;
    jwksCacheTtlMs?: number;
    maxClockSkewSec?: number;
    /**
     * When true, log the extracted thumbprint / subject at info level. Defaults
     * to false to keep production logs quiet; useful for local debugging.
     */
    verbose?: boolean;
    /**
     * Reject signed-but-invalid requests with 401 (see S-6 above). Defaults
     * to the value of `NEOTOMA_AAUTH_STRICT` at middleware-build time.
     */
    strict?: boolean;
}
/**
 * Validate the agent-token JWT when `keyType === 'jwt'`. The httpsig library
 * intentionally does NOT validate the JWT — per the RFC 9421 spec it is the
 * caller's responsibility to check issuer / expiration / audience.
 *
 * Phase 1 policy (intentionally permissive, tightened in Phase 2):
 * - Decode the JWT without signature verification (signature is already
 *   validated transitively via the HTTP signature, which covers the
 *   `signature-key` header containing the JWT).
 * - Confirm the JWT header declares `typ: "aa-agent+jwt"` (AAuth profile
 *   marker) — unrecognised typ values are still accepted with a warning so
 *   early-stage clients are not locked out.
 * - Enforce `exp` if present; ignore otherwise.
 * - Surface `sub` / `iss` for attribution.
 */
/** Shape of a single external actor claim from the agent_token. */
export interface ExternalActorTokenClaim {
    provider: string;
    id: number;
    login: string;
    linked_at?: string;
}
/**
 * Build the Express middleware. Call at app-bootstrap time:
 *
 * ```ts
 * app.use("/mcp", aauthVerify({ authority: canonicalAuthority() }));
 * ```
 *
 * The middleware requires raw request bodies to be available — either via
 * `express.raw()` or via `express.json({ verify: (req,_,buf) => (req as any).rawBody = buf })`.
 * If neither is set, signatures that cover `content-digest` will fail to
 * verify.
 */
export declare function aauthVerify(options: AAuthVerifyOptions): (req: Request, res: Response, next: NextFunction) => Promise<void>;
/**
 * Helper for session-introspection to retrieve the stashed decision
 * without a cast dance.
 */
export declare function getAttributionDecisionFromRequest(req: Request): AttributionDecisionDiagnostics | null;
/**
 * Export for tests — they assert the normalised shape of the stable
 * `attribution_decision` log line.
 */
export declare const ATTRIBUTION_DECISION_EVENT: "attribution_decision";
export type { ClientNameNormalisationReason } from "../crypto/agent_identity.js";
/**
 * Fetch the AAuth context stamped on a request by {@link aauthVerify}.
 * Returns `null` when the request is unsigned or failed verification.
 */
export declare function getAAuthContextFromRequest(req: Request): AAuthRequestContext | null;
//# sourceMappingURL=aauth_verify.d.ts.map