/**
 * Web-boundary utilities every agent app's routes hand-roll: JSON body parsing
 * + narrowing, request-context extraction (real client IP behind Cloudflare),
 * a KV-backed sliding-window rate limiter, and security response headers. Pure
 * mechanism — no DB, no domain. The KV is a structural interface so this needs
 * no `@cloudflare/workers-types` dependency.
 */
type JsonObject = Record<string, unknown>;
/** Parse + object-narrow a Request body. `[body, null]` on success, `[null,
 *  errorResponse]` on a non-object body (callers `if (err) return err`). */
declare function parseJsonObjectBody(request: Request): Promise<[JsonObject, null] | [null, Response]>;
/** Narrow one required string field, 400 if missing/empty. */
declare function requireString(body: JsonObject, field: string): string | Response;
interface RequestContext {
    ipAddress: string;
    userAgent: string;
    timestamp: string;
    requestId: string;
}
/** Extract request context for audit trails. Uses `CF-Connecting-IP` for the
 *  real client IP behind Cloudflare. */
declare function extractRequestContext(request: Request): RequestContext;
/** Minimal KV contract (Cloudflare `KVNamespace` satisfies it structurally). */
interface KvLike {
    get(key: string): Promise<string | null>;
    put(key: string, value: string, options?: {
        expirationTtl?: number;
    }): Promise<void>;
}
interface RateLimitResult {
    allowed: boolean;
    remaining: number;
    resetAt: number;
}
/** KV-backed sliding-window rate limit. Stores recent timestamps per key,
 *  prunes the window, allows until `limit` is hit.
 *
 *  Read-modify-write is best-effort, NOT atomic: KV has no compare-and-swap, so
 *  two requests racing on the same key can each read the same pre-state and both
 *  write — a concurrent burst can momentarily admit up to one extra request per
 *  racing writer. This is acceptable for coarse abuse limiting; it is NOT a hard
 *  quota gate.
 *
 *  Fail-CLOSED on unreadable state: corrupt/non-array KV (a poisoned or
 *  truncated value) is treated as a full window, so a tampered key cannot reset
 *  the count and bypass the limiter. A bare `JSON.parse` here would throw and
 *  abort the request handler, silently disabling the limit (fail-open). */
declare function checkRateLimit(kv: KvLike, key: string, limit: number, windowSeconds: number): Promise<RateLimitResult>;
interface CookieOptions {
    name: string;
    /** Default '/'. */
    path?: string;
    /** Default true. */
    httpOnly?: boolean;
    /** Adds the `Secure` attribute. Default false. */
    secure?: boolean;
    /** Default 'Lax'. */
    sameSite?: 'Lax' | 'Strict' | 'None';
    maxAgeSeconds?: number;
}
/** Serialize a Set-Cookie header value: `name=encodeURIComponent(value)` plus
 *  attributes in Path / HttpOnly / SameSite / Max-Age / Secure order.
 *  Throws on `SameSite=None` without `secure` — browsers silently drop that
 *  combination, which would otherwise fail invisibly. */
declare function serializeCookie(value: string, opts: CookieOptions): string;
/** Set-Cookie header value that deletes the cookie (empty value, Max-Age=0). */
declare function clearCookieHeader(opts: Omit<CookieOptions, 'maxAgeSeconds'>): string;
/** Read + decode one cookie from a Cookie request header; null when absent. */
declare function readCookieValue(cookieHeader: string | null, name: string): string | null;
interface SecurityHeaderOptions {
    /** Product disclaimer (e.g. "AI-powered tool. Not legal advice."). Omitted if absent. */
    disclaimer?: string;
    /** Data-retention label (e.g. "7-years"). Omitted if absent. */
    retention?: string;
    /** Extra headers to set. */
    extra?: Record<string, string>;
}
/** Set standard security headers on a response (HSTS, nosniff, frame-options,
 *  referrer-policy, XSS) + optional product disclaimer/retention. The security
 *  set is generic; the disclaimer/retention are the product's. */
declare function addSecurityHeaders(response: Response, opts?: SecurityHeaderOptions): Response;
/**
 * Canonical media-reference boundary shared by every surface that persists a
 * media url (sequences clips, design-canvas image/video src). The ONE rule:
 * remote `http(s)` or a rooted `/api/` path are allowed; everything else is
 * rejected, with a named reason for known-bad local/inline schemes so the
 * thrown message is actionable for an LLM planner. The url is trimmed before
 * the scheme check so leading whitespace cannot smuggle a rejected scheme past
 * a naive `startsWith`.
 *
 * @param what - noun for the error message (e.g. 'media url', 'src').
 */
declare function assertMediaUrl(url: string, what?: string): void;

export { type CookieOptions, type JsonObject, type KvLike, type RateLimitResult, type RequestContext, type SecurityHeaderOptions, addSecurityHeaders, assertMediaUrl, checkRateLimit, clearCookieHeader, extractRequestContext, parseJsonObjectBody, readCookieValue, requireString, serializeCookie };
