/** * Generator for the `/.well-known/api-catalog` RFC 9264 linkset document. * * @module server/api-catalog */ export type ApiCatalogOptions = { /** Absolute server origin, e.g. `https://api.example.com` */ readonly origin: string; }; type LinksetLink = { href: string; type: string; }; type LinksetEntry = { anchor: string; 'service-desc': LinksetLink[]; }; type LinksetDocument = { linkset: LinksetEntry[]; }; /** * Generate an RFC 9264 linkset document describing the API discovery endpoints. * * All hrefs are absolute URLs built from `options.origin`. Links are sorted * alphabetically by href for deterministic output. */ export declare function generateApiCatalog(options: ApiCatalogOptions): LinksetDocument; /** * One-shot "publicOrigin not set" warner with private state. Tests can * construct an isolated warner so they don't depend on a process-wide * boolean — that was a maintainability smell flagged in review (test * order could change, new test files could exercise the route without * resetting, etc.). */ export type PublicOriginWarner = { /** Emit the warning if it hasn't fired on this warner yet. */ warn(): void; /** Re-arm the warner; primarily useful in tests. */ reset(): void; }; /** * Build a fresh `PublicOriginWarner`. State is captured in the closure; * each instance is independent. */ export declare function createPublicOriginWarner(): PublicOriginWarner; /** * Reset the default process-wide warning gate. **Test-only.** * Production code never calls this; exported so tests can re-arm the * warning between cases. */ export declare function resetPublicOriginWarningForTesting(): void; /** * Called by the route handler when `publicOrigin` was not configured. Emits * a one-shot warning so production deployments are nudged toward the * `publicOrigin` option that bypasses header-derived origins entirely. */ export declare function warnIfPublicOriginUnset(): void; /** * Extract the origin (scheme + host) from a `Request` object, validating * each header before trusting it. * * **Security note.** Both `Host` and `X-Forwarded-Proto` are * client-controllable (the latter via a misconfigured reverse proxy). * Without validation, an attacker can poison `/.well-known/api-catalog` * service-desc URLs by injecting a malicious `Host: evil.example` or a * non-network protocol (`X-Forwarded-Proto: javascript`). * * Operators in production are strongly encouraged to set * `serve({ publicOrigin: 'https://api.example.com' })` so this header path * is never used. When `publicOrigin` is unset, this function falls back to * the request URL's origin (which is the actual incoming connection's * scheme/host pair as Bun resolved them, not header-derived) and only * upgrades to header-derived values when the request URL does not include * an authoritative origin (e.g. unit tests using relative URLs). * * Validation rules: * - `X-Forwarded-Proto` must be exactly `http` or `https`; anything else * is dropped. * - `Host` must match a conservative reg-name / IP-literal pattern with * optional port; anything else is dropped. * - When neither header is trustworthy, falls back to `localhost` over * `https` so the function never returns an attacker-controlled value. */ export declare function originFromRequest(request: Request): string; export {};