import type { SelectOption } from "./pretty.js"; /** The auth families init detects in package.json (09-vendo §2.1). */ export type AuthPresetName = "authJs" | "clerk" | "supabase" | "auth0"; /** Every answer "How do your users sign in?" accepts, which is also every `--auth` value. `jwt` and `custom` are wired answers like the four vendor presets — both fill the identity seams, oauth half included — and `none` is the honest "not yet". */ export type AuthAnswer = AuthPresetName | "jwt" | "custom" | "none"; /** The env variable the scaffolded `jwt({ secret })` reads, and the name init writes into `.env.local`. A host-generic JWT scheme has no vendor-owned variable to inherit (jwt.ts), so init picks ONE name and both halves — the composition line and the env entry — spell it the same way. */ export declare const JWT_SECRET_ENV = "HOST_API_JWT_SECRET"; /** Each preset function ships on its own subpath — not `@vendoai/vendo/server` — so importing one preset never resolves the others' optional peer deps (corpus-triage Task 9: a shared barrel meant ANY host importing the server entry statically re-resolved every preset's optional peer, e.g. @auth/core, even unused). Scaffolded code imports the preset from here and createVendo/nextVendoHandler from "@vendoai/vendo/server" separately. */ export declare const AUTH_PRESET_SPECIFIER: Record; /** What a composition ALREADY on disk wires into the `auth`/`oauth` seams, or * null. * * Read from the file's own source, because a re-run over an existing * composition never asks the auth question — so the run's `authWired` is null * even for a host whose `lib/vendo.ts` says `auth: authJs()`, and the MCP * planner used to refuse such a host with "wire an auth preset". * * Both spellings of each preset's subpath (an aliased host is wired too), * comments stripped like every other source probe here, and the call has to be * there as well — an import on its own is not a wiring. Either spelling of the * call counts: `auth: preset()` inline, or the `const auth = preset()` the * agent-loop arm hoists so its exported resolver shares the instance. * * `jwt()` counts: it composes through the same `composeHostAuthPreset` every * vendor preset does (identity.ts:228-246), so it carries the oauth half too. * So does a hand-written seam — `oauth` is the DOOR's own config key, so its * presence in the composition is the wiring, whatever the object is called. */ export declare function composedAuthPreset(compositionPath: string): Promise; /** One auth family the package.json scan found. */ export interface AuthMatch { preset: AuthPresetName; dependency: string; /** A version-shaped caveat the wiring paths must surface (today: next-auth v4, whose sessions the v5-speaking authJs() preset cannot read). */ advisory?: string; } /** What the auth answer WIRES, in the shape the scaffolds render: one of the four vendor presets (with the dependency detection cited it, where it was detected rather than chosen), the host's own JWT scheme, or the seam init writes for a host that has none of the above. */ export type AuthWire = { kind: "preset"; preset: AuthPresetName; dependency?: string; } | { kind: "jwt"; } | { kind: "custom"; }; export interface AuthDetection { /** Exactly one family matched — the answer the question pre-selects, and the one an unwatched run takes without asking. */ wired: AuthMatch | null; /** Every family that matched (for the ambiguity advisory). */ matches: AuthMatch[]; } export declare const AUTH_FAMILIES: ReadonlyArray<{ preset: AuthPresetName; test: (dependency: string) => boolean; }>; export declare function supabaseServerEnvSatisfied(root: string, env: Record): Promise; export declare function clerkServerEnvSatisfied(root: string, env: Record): Promise; /** The wire's own remediation copy, verbatim-adjacent: doctor and the first failing turn teach the same fix. */ export declare const SUPABASE_ENV_GUIDANCE: string; /** Same shape for clerk — and the same wording the keyless wire warns with (#1338): the preset reads server-side keys, not the publishable key detection saw. */ export declare const CLERK_ENV_GUIDANCE: string; /** Auth-preset detection from the host's package.json: one unambiguous family becomes the pre-selected answer; none or several leave the question with no honest default (`scannedAuthDefault`) and, where nothing is chosen, one advisory line. */ export declare function detectAuthPreset(root: string, env?: Record): Promise; /** The one calm auth line for the none/ambiguous cases — names the exact line to add, never asks a question. Emitted only when init scaffolds the composition (a hand-wired host may already have auth). */ export declare function authAdvisory(detection: AuthDetection, compositionPath: string): string | null; /** The chose-nothing advisory when a family WAS detected: anonymous composition, exact line in hand. */ export declare function declinedAuthAdvisory(match: AuthMatch, compositionPath: string): string; export type SelectAuth = (question: string, options: SelectOption[], defaultIndex?: number) => Promise; /** Display name + the runtime package each vendor preset lazy-loads (the install hint when the chosen family's SDK is absent; the preset's own lazy-load error already guards runtime). Key order is the answer order. */ export declare const AUTH_FAMILY_INFO: Record; /** The one auth question, asked on EVERY interactive run. It asks about the host's users, not about Vendo's mechanism, because "which auth should Vendo wire?" is only answerable by someone who already knows what Vendo wires. */ export declare const AUTH_QUESTION = "How do your users sign in?"; /** The answers, in one fixed order. Detection moves the CURSOR (see `scannedAuthDefault`), never the order — a list that reshuffles per host is a list nobody learns — and rides along as the hint on the row it found. */ export declare function authAnswerOptions(detection: AuthDetection): SelectOption[]; /** The answer the cursor starts on — and, verbatim, the answer a run nobody is watching takes. Exactly one family in package.json is a default worth pre-selecting; anything else (several families, or none) has no honest guess, so it lands on "None yet" — the same anonymous composition non-interactive runs have always written. */ export declare function scannedAuthDefault(detection: AuthDetection): AuthAnswer; /** What one answer wires, and the one advisory line (if any) it owes. */ export declare function wireAuthAnswer(detection: AuthDetection, compositionPath: string, answer: AuthAnswer): { wired: AuthWire | null; advice: string | null; }; /** Scan, then ASK — always, on every interactive run that creates the * composition. The scan no longer decides in silence for someone who is * sitting there: it pre-selects, so the one-family host still answers with * Enter, and the ambiguous and empty hosts get the SAME question instead of * an anonymous composition they never chose. * * Without the seam — non-interactive, no TTY, CI, `--yes`, `--agent` — the * scanned default is taken SILENTLY. A run nobody is watching must never hang * on a question, and that answer is exactly the one the cursor sits on. */ export declare function resolveScaffoldAuth(root: string, compositionPath: string, authAnswer: AuthAnswer | undefined, selectAuth: SelectAuth | undefined, env?: Record): Promise<{ wired: AuthWire | null; advice: string | null; }>;