import '../assert_dev_env.js';
/**
 * Stateless cross-process bootstrap.
 *
 * POSTs `{bootstrap_path}` against the running test binary with the
 * preconfigured token + username + password, parses the
 * `BootstrapOutput` envelope, captures the session `Set-Cookie` onto
 * the supplied `FetchTransport` (which carries it on every subsequent
 * call), and returns the keeper credentials.
 *
 * Fires exactly once per backend lifetime — `spawn_backend` calls it
 * inside vitest's `globalSetup`. Per-test fixtures re-use the captured
 * keeper credentials; fresh per-test accounts come from
 * `fixture.create_account()` (signup+login through production RPC),
 * not re-bootstrap. The hybrid reset model in `default_cross_process_setup`
 * depends on this — re-bootstrap would race the bootstrap lock and
 * in-memory caches.
 *
 * @module
 */
import { z } from 'zod';
import { Uuid } from '@fuzdev/fuz_util/id.js';
/**
 * The `BootstrapOutput` envelope shape the cross-process bootstrap call
 * cares about. Looser than the full `BootstrapOutput` Zod schema in
 * `auth/bootstrap_account.ts` — that schema is the canonical wire shape
 * on the server side, and this one is a structural subset the runner
 * uses to extract the keeper identity. Kept local so cross-process
 * testing doesn't pull the full auth-domain schema into its dep graph.
 */
const BootstrapResponse = z.object({
    account: z.object({ id: Uuid, username: z.string() }),
    actor: z.object({ id: Uuid }),
});
/**
 * Fire `POST {config.bootstrap_path}` and capture the keeper session.
 *
 * @throws Error when the binary refuses bootstrap (non-2xx response) or
 *   the body fails to parse as the expected `{account, actor}` envelope.
 *   The error carries the status + raw body so a mistyped token /
 *   username collision / boot-time DB drift surfaces with enough
 *   context to debug.
 */
export const bootstrap = async (options) => {
    const { transport, config } = options;
    const response = await transport(config.bootstrap_path, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            token: config.bootstrap.token,
            username: config.bootstrap.username,
            password: config.bootstrap.password,
        }),
    });
    if (!response.ok) {
        const body = await response.text().catch(() => '<unreadable>');
        throw new Error(`bootstrap(${config.name}) failed: status=${response.status} body=${body}`);
    }
    const raw = await response.json();
    const parsed = BootstrapResponse.safeParse(raw);
    if (!parsed.success) {
        throw new Error(`bootstrap(${config.name}) returned unexpected body: ${JSON.stringify(raw)} (${parsed.error.message})`);
    }
    return {
        transport,
        account: parsed.data.account,
        actor: parsed.data.actor,
        cookies: transport.cookies(),
    };
};
