/** A per-run server session: the secret token + the adopt allowlist. */ export interface ServeSession { /** Crypto-random hex; embedded in the HTML, required on every mutating POST. */ readonly token: string; /** The loopback port the server is bound to (for the Origin check). */ readonly port: number; /** * The adoptable surfaces, keyed by their repo-relative path. A POST names a * path; we resolve it HERE against this set, so an off-list path is refused. */ readonly surfaces: ReadonlySet; } /** The salient, transport-agnostic fields of an incoming request. */ export interface RequestView { readonly method: string; /** The URL path (no query string). */ readonly path: string; /** The `X-Vigiles-Token` header, if any. */ readonly token: string | null; /** The `Origin` header, if any. */ readonly origin: string | null; /** `body.target` for an adopt POST, if any. */ readonly target: string | null; } /** What the server should do with a request — a pure, testable verdict. */ export type ServeDecision = { readonly kind: "report"; } | { readonly kind: "adopt"; readonly target: string; } | { readonly kind: "adopt-all"; } | { readonly kind: "shutdown"; } | { readonly kind: "reject"; readonly status: number; readonly reason: string; }; /** * Constant-time token comparison (avoids a timing side-channel). Returns false * for a missing/short token rather than throwing. */ export declare function tokenOk(provided: string | null, expected: string): boolean; /** * A mutating POST's Origin must be the loopback server itself (or absent — some * same-origin fetches omit it, and the token already guards those). A foreign * site's Origin never matches, so a cross-site POST is refused even before the * token check. */ export declare function originOk(origin: string | null, port: number): boolean; /** * Resolve a client-supplied surface path against the allowlist. Returns the path * only if it's a known adoptable surface — never trusts a raw path (no traversal). */ export declare function resolveSurface(target: string | null, surfaces: ReadonlySet): string | null; /** * The pure router: given a request and the session, decide what to do. Every * MUTATING route (adopt / adopt-all / shutdown) requires POST + a valid Origin + * a valid token; GET / serves the report page (its body is CORS-protected, so a * foreign site can't read it even if it requests it). */ export declare function decideServe(req: RequestView, session: ServeSession): ServeDecision; /** A fresh crypto-random session token (32 hex chars = 16 bytes). */ export declare function newToken(): string; /** Whether `audit` should start the live adoption server. */ export type ServeGate = "serve" | "skip" | "ask"; /** * The pure serve-gate decision (option B). A plain `audit` stays a terminating, * headless-safe read; the live server is only ever offered/started INTERACTIVELY * and OWN-REPO (it writes specs — never into a stranger's dir): * - `--no-serve`, a foreign repo, or `--json`/headless → skip (never serve). * - `--serve` → serve (force, skip the prompt). * - a TTY with adoptable surfaces → ask once ("open the live report?"). * - a TTY with nothing to adopt → skip (no point). */ export declare function decideServeGate(o: { serveFlag: boolean; noServeFlag: boolean; json: boolean; isTTY: boolean; ownRepo: boolean; adoptableCount: number; }): ServeGate; /** The outcome of running an adopt action, reported back to the report UI. */ export interface AdoptOutcome { readonly ok: boolean; readonly message: string; } export interface ServeOptions { /** The per-run secret token (already injected into `html`). */ readonly token: string; /** The adopt allowlist (repo-relative surface paths). */ readonly surfaces: ReadonlySet; /** The rendered report HTML (with the token already injected). */ readonly html: string; /** Adopt ONE surface (the CLI passes a closure over `init --target=`). */ readonly runAdopt: (target: string) => Promise; /** Adopt every surface (bare `init`). */ readonly runAdoptAll: () => Promise; /** Called once the server is listening, with the URL to open. */ readonly onListening?: (url: string) => void; } /** * Start the loopback adoption server. Resolves when the server shuts down (via * the /shutdown route or SIGINT). Bound to 127.0.0.1 only. */ export declare function serveAudit(opts: ServeOptions): Promise; //# sourceMappingURL=audit-serve.d.ts.map