create-op-node 0.10.12 → 0.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +39 -19
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cloudflare.ts","../src/lib/constants.ts","../src/lib/tfc.ts","../src/lib/exec.ts","../src/lib/keychain.ts","../src/lib/prompts.ts","../src/lib/github.ts","../src/lib/secrets.ts","../src/lib/polling.ts","../src/commands/init.ts","../src/lib/homebrew.ts","../src/lib/macos.ts","../src/lib/launchagent.ts","../src/lib/op-compose-script.ts","../src/lib/op-compose-install.ts","../src/lib/docker.ts","../src/lib/ollama.ts","../src/lib/noderepo.ts","../src/lib/assert.ts","../src/commands/bootstrap.ts","../src/commands/reset.ts","../src/lib/cosign.ts","../src/lib/http.ts","../src/lib/tls.ts","../src/commands/verify.ts","../src/lib/region-schema.json","../src/lib/region.ts","../src/commands/region.ts","../src/cli.ts"],"names":["result","password","p","p2","pc","fresh","v","mkdir","writeFile","chmod","text","join","homedir","Command","Option","resolveRegion","rm","save","REGION_RE","fileExists","access","p4","connect","resolve","DEFAULT_DEPS","tls","p5","phaseIcon","p6","dirname"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Cloudflare API helpers used by `create-op-node init`.\n *\n * The probe replicates what we built interactively on 2026-06-16: hit each of\n * the 5 endpoints we need so we know the token has every scope before going any\n * further. Failing early here saves a ~60-second Terraform plan that would fail\n * with a less useful error.\n *\n * Account-owned tokens (`cfat_…`) cannot use `/user/tokens/verify`. We hit\n * `/accounts/{id}/tokens/verify` for validity and the 5 resource endpoints for\n * scope coverage.\n */\n\nconst CF_API = 'https://api.cloudflare.com/client/v4';\n\ninterface ProbeInput {\n token: string;\n accountId: string;\n zoneId: string;\n}\n\nexport interface ProbeResult {\n ok: boolean;\n issues: string[];\n}\n\nasync function get(\n token: string,\n path: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<{ status: number; body: unknown }> {\n const res = await fetchImpl(`${CF_API}${path}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n let body: unknown = null;\n try {\n body = await res.json();\n } catch {\n /* non-JSON body — leave as null */\n }\n return { status: res.status, body };\n}\n\nfunction shortError(body: unknown): string {\n if (\n typeof body === 'object' &&\n body !== null &&\n 'errors' in body &&\n Array.isArray((body as { errors: unknown[] }).errors)\n ) {\n const errs = (body as { errors: Array<{ message?: string; code?: number }> }).errors;\n return errs\n .map((e) => {\n const prefix = e.code ? `CF ${e.code}: ` : '';\n return `${prefix}${e.message ?? 'unknown'}`;\n })\n .join('; ');\n }\n return 'no error message returned';\n}\n\ninterface ScopeCheck {\n name: string;\n path: string;\n /** Endpoints that 404 when the underlying feature isn't enabled but the scope\n * IS present (e.g. R2 before \"Enable R2\"). We treat those as passes with a\n * note rather than failures. */\n treat404AsPass?: boolean;\n}\n\nexport async function probeCloudflareToken(input: ProbeInput): Promise<ProbeResult> {\n const issues: string[] = [];\n\n // ---- Validity probe (Account-owned token endpoint) ----\n const verify = await get(input.token, `/accounts/${input.accountId}/tokens/verify`);\n if (verify.status !== 200) {\n issues.push(\n `Token verify failed (HTTP ${verify.status}): ${shortError(verify.body)}`,\n );\n return { ok: false, issues };\n }\n\n // ---- Scope probes ----\n const checks: ScopeCheck[] = [\n { name: 'Zone : Zone : Read', path: `/zones/${input.zoneId}` },\n { name: 'Zone : DNS : Edit', path: `/zones/${input.zoneId}/dns_records?per_page=1` },\n { name: 'Account : Cloudflare Tunnel : Edit', path: `/accounts/${input.accountId}/cfd_tunnel` },\n { name: 'Account : Workers R2 Storage : Edit', path: `/accounts/${input.accountId}/r2/buckets` },\n { name: 'Account : Cloudflare Pages : Edit', path: `/accounts/${input.accountId}/pages/projects` },\n ];\n\n for (const check of checks) {\n const res = await get(input.token, check.path);\n if (res.status === 200) continue;\n if (res.status === 404 && check.treat404AsPass) continue;\n if (res.status === 401 || res.status === 403) {\n issues.push(`Missing scope: ${check.name}`);\n } else if (\n res.status === 400 &&\n typeof res.body === 'object' &&\n res.body !== null &&\n 'errors' in res.body &&\n Array.isArray((res.body as { errors: Array<{ code?: number }> }).errors) &&\n (res.body as { errors: Array<{ code?: number }> }).errors.some((e) => e.code === 10042)\n ) {\n // R2 not enabled yet — actionable, not a scope problem.\n issues.push(\n `R2 not enabled on this account. ` +\n `Enable it once in Cloudflare dashboard → R2 → Get started, then re-run.`,\n );\n } else {\n issues.push(`${check.name} probe returned HTTP ${res.status}: ${shortError(res.body)}`);\n }\n }\n\n return { ok: issues.length === 0, issues };\n}\n\n/* ------------------------------------------------------------------ *\n * Tunnel-status probe (used by `verify`, not `init`) *\n * ------------------------------------------------------------------ */\n\nexport interface TunnelStatusInput {\n token: string;\n accountId: string;\n tunnelId: string;\n /** Injectable for tests. */\n fetchImpl?: typeof fetch;\n}\n\nexport interface TunnelStatusOk {\n ok: true;\n /** Active connector connections registered with Cloudflare's edge. Zero on\n * a freshly-created tunnel that hasn't been started, > 0 on a healthy one. */\n connections: number;\n /** Cloudflare's own status field — `healthy`, `degraded`, `inactive`, etc. */\n status: string;\n}\n\nexport interface TunnelStatusFailed {\n ok: false;\n reason: string;\n}\n\nexport type TunnelStatusResult = TunnelStatusOk | TunnelStatusFailed;\n\ninterface CfTunnelEnvelope {\n result?: {\n status?: string;\n connections?: Array<unknown>;\n };\n}\n\n/**\n * Look up a single tunnel's current edge-side status. The CF API endpoint\n * returns `connections: []` until at least one cloudflared connector\n * registers — useful as a verify signal that the Studio's cloudflared is\n * actually online.\n */\nexport async function tunnelStatus(input: TunnelStatusInput): Promise<TunnelStatusResult> {\n const fetchImpl = input.fetchImpl ?? fetch;\n try {\n const res = await get(\n input.token,\n `/accounts/${input.accountId}/cfd_tunnel/${input.tunnelId}`,\n fetchImpl,\n );\n if (res.status !== 200) {\n return {\n ok: false,\n reason: `tunnel lookup failed (HTTP ${res.status}): ${shortError(res.body)}`,\n };\n }\n const env = res.body as CfTunnelEnvelope;\n const status = env.result?.status ?? '<no status>';\n const connections = env.result?.connections?.length ?? 0;\n return { ok: true, connections, status };\n } catch (err) {\n return { ok: false, reason: `tunnel lookup threw: ${(err as Error).message}` };\n }\n}\n","/**\n * Shared invariants reused across libs + commands. Each constant has exactly\n * one definition so a format change can't drift between callers (which\n * happened during review: the pgsodium-key shape was hand-rolled in three\n * places).\n */\n\n/** A pgsodium master key is 32 bytes of CSPRNG output, encoded as 64\n * lowercase hex characters. Match it everywhere with this regex so an\n * uppercase-hex or wrong-length value gets a consistent reason. */\nexport const PGSODIUM_KEY_RE = /^[a-f0-9]{64}$/;\n\n/** Allowed character set for a Cloudflare Tunnel token before we\n * interpolate it into a launchd plist string. JWT-style tokens\n * (header.payload.signature) use base64-url — letters, digits, `-`,\n * `_`, `.`, `=`. We deliberately reject anything outside that set so\n * a crafted token can't inject XML attributes or break the plist\n * string content.\n *\n * Stricter than SAFE_LAUNCHCTL_VALUE_RE on purpose: Cloudflare Tunnel\n * tokens are guaranteed base64url by the issuer, so allowing `+` or `/`\n * here would silently accept malformed tokens that would later fail at\n * cloudflared startup with a less actionable error. Kept separate from\n * SAFE_LAUNCHCTL_VALUE_RE for that reason. */\nexport const TUNNEL_TOKEN_RE = /^[A-Za-z0-9_\\-.=]+$/;\n\n/** Operator-friendly path safety check used before interpolating a path\n * into a launchd `sh -c` command. Any shell metacharacter would let an\n * attacker-supplied path execute arbitrary code at every login. The set\n * permits everything macOS allows in a normal path (letters, digits,\n * `/`, `-`, `_`, `.`, space) — and rejects `;`, `$`, backticks, quotes,\n * newlines, etc. */\nexport const SAFE_PATH_RE = /^[A-Za-z0-9_\\-./ ]+$/;\n\n/** Character set allowed for any value we interpolate into the launchd\n * `sh -c` body as a `launchctl setenv VAR \"<value>\"` argument. Permits\n * every character that base64 (`+`, `/`, `=`), base64url (`-`, `_`), and\n * JWT (`.`) produce, plus alphanumerics — covers JWT_SECRET and the signed\n * Supabase tokens (which use JWT shape `xxx.yyy.zzz`). Rejects shell\n * metacharacters (`;`, `$`, backticks, quotes, spaces, newlines) that\n * would let a tampered value inject commands into the login session.\n *\n * POSTGRES_PASSWORD and DASHBOARD_PASSWORD use the stricter\n * URL_SAFE_PASSWORD_RE — they land in postgres:// URIs where `+`/`/`/`=`\n * cause parser ambiguity. */\nexport const SAFE_LAUNCHCTL_VALUE_RE = /^[A-Za-z0-9+/=._-]+$/;\n\n/** Subset of SAFE_LAUNCHCTL_VALUE_RE for values that ALSO land in URI\n * components (postgres:// connection strings, basic-auth headers).\n * base64url alphabet — no `+`, no `/`, no `=`. */\nexport const URL_SAFE_PASSWORD_RE = /^[A-Za-z0-9_-]+$/;\n\n/** Same shape as TUNNEL_TOKEN_RE but documented separately because the\n * SUPABASE_URL value also lands in the plist and we want to allow `://`\n * and `:` for the port. Letters, digits, `-`, `_`, `.`, `:`, `/`. */\nexport const SAFE_URL_RE = /^[A-Za-z0-9:/_.-]+$/;\n\n/** Default network timeout used by `verify`'s probes (TLS handshake, HTTP\n * GET /health, GraphQL POST). One number so tls.ts and http.ts don't drift. */\nexport const VERIFY_NETWORK_TIMEOUT_MS = 10_000;\n\n/** Per-request timeout for the Terraform Cloud + Cloudflare API helpers\n * (`tfc.ts`, `cloudflare.ts`). Deliberately separate from the `verify`\n * probe timeout: these are control-plane API calls, and the overall\n * apply-wait budget is governed by `polling.ts`, so each individual\n * request just needs a sane cap to fail fast on a stalled connection\n * instead of hanging `init` indefinitely. */\nexport const API_REQUEST_TIMEOUT_MS = 15_000;\n\n/** First N chars of a probe response body that get echoed back to the\n * operator for diagnostics. Capped low because the wizard renders this\n * inline; for the real body, use `curl -v` and friends. */\nexport const BODY_PREVIEW_MAX = 200;\n","/**\n * Terraform Cloud (HCP Terraform) API helpers used by `create-op-node init`.\n *\n * We hit a tiny subset of the TFC v2 API directly via native `fetch` — no\n * client library. Three needs:\n *\n * 1. Verify the operator's TFC token is valid and has access to the org\n * they typed.\n * 2. Resolve a workspace by tag set so we can poll its state for outputs.\n * 3. Fetch the Tunnel token output after `terraform apply` completes.\n *\n * The TFC API responds with JSON:API-shaped documents; helpers below narrow\n * each call to the minimal shape we actually consume.\n */\n\nimport { API_REQUEST_TIMEOUT_MS } from './constants.js';\n\nconst TFC_API = 'https://app.terraform.io/api/v2';\n\n/** TFC organization slug rules: alphanumerics, underscores, hyphens; the API\n * doesn't formally publish a max but slugs over 40 chars are rejected in\n * practice. We validate before any URL interpolation to neutralise typos\n * that would otherwise hit unintended endpoints (e.g. `?` or `/` in the\n * slug bouncing us into a different route). */\nconst ORG_SLUG_RE = /^[A-Za-z0-9_-]{1,40}$/;\n\nexport function isValidTfcOrgSlug(slug: string): boolean {\n return ORG_SLUG_RE.test(slug);\n}\n\ninterface TfcAuth {\n token: string;\n organization: string;\n}\n\ntype Headers = Record<string, string>;\n\nfunction authHeaders(token: string): Headers {\n return {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/vnd.api+json',\n };\n}\n\n/**\n * GET a TFC API path as JSON, with a hard per-request timeout.\n *\n * A stalled or half-open connection (native `fetch` has no default timeout)\n * would otherwise hang `init` — including the ~10-minute apply-wait in\n * `polling.ts` — forever. We wrap the call in an `AbortController` and, on\n * any throw (timeout / DNS blip / TLS reset / proxy error), return\n * `{ status: 0, body: null }`. Every caller already treats a non-200 status\n * as a soft failure, so a `0` degrades to `null` / a network-error message\n * instead of rejecting out of the poll loop and crashing the wizard.\n */\nasync function getJson(\n token: string,\n path: string,\n): Promise<{ status: number; body: unknown }> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), API_REQUEST_TIMEOUT_MS);\n try {\n const res = await fetch(`${TFC_API}${path}`, {\n headers: authHeaders(token),\n signal: ctrl.signal,\n });\n let body: unknown = null;\n try {\n body = await res.json();\n } catch {\n /* non-JSON body — leave as null */\n }\n return { status: res.status, body };\n } catch {\n // Timeout (AbortError) or any network-layer throw. status 0 = \"never got\n // a response\" — see the docstring above.\n return { status: 0, body: null };\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport interface TfcProbeResult {\n ok: boolean;\n /** TFC user's display name when the token belongs to a user (`null` when it's a team / org token). */\n userName?: string;\n issues: string[];\n}\n\n/**\n * Sanity-check the token + organization at the same time:\n *\n * - GET /account/details — confirms the token itself is valid.\n * - GET /organizations/{org} — confirms the org exists AND that the token\n * has the membership/permissions to see it.\n *\n * Both must pass before we let the wizard proceed; a token that's valid but\n * scoped to a different org would silently fail at the workspace step.\n */\nexport async function probeTfcToken(input: TfcAuth): Promise<TfcProbeResult> {\n const issues: string[] = [];\n\n if (!isValidTfcOrgSlug(input.organization)) {\n issues.push(\n `Organization \"${input.organization}\" isn't a valid TFC slug (letters, digits, hyphens, underscores; up to 40 chars).`,\n );\n return { ok: false, issues };\n }\n\n const account = await getJson(input.token, '/account/details');\n if (account.status === 0) {\n issues.push(\n \"Couldn't reach Terraform Cloud (network error or timeout). Check your connection and retry.\",\n );\n return { ok: false, issues };\n }\n if (account.status !== 200) {\n issues.push(\n `TFC token invalid (HTTP ${account.status}). Regenerate at https://app.terraform.io/app/settings/tokens.`,\n );\n return { ok: false, issues };\n }\n const userName = extractUserName(account.body);\n\n const org = await getJson(\n input.token,\n `/organizations/${encodeURIComponent(input.organization)}`,\n );\n if (org.status === 0) {\n issues.push(\n \"Couldn't reach Terraform Cloud while checking the organization (network error or timeout).\",\n );\n } else if (org.status === 404) {\n issues.push(\n `TFC organization \"${input.organization}\" not found, or this token lacks access. Check the org slug at https://app.terraform.io.`,\n );\n } else if (org.status === 401 || org.status === 403) {\n issues.push(\n `TFC token doesn't have permission to access org \"${input.organization}\".`,\n );\n } else if (org.status !== 200) {\n issues.push(`TFC org probe returned HTTP ${org.status}.`);\n }\n\n return {\n ok: issues.length === 0,\n issues,\n ...(userName ? { userName } : {}),\n };\n}\n\nfunction extractUserName(body: unknown): string | undefined {\n if (\n typeof body === 'object' &&\n body !== null &&\n 'data' in body &&\n typeof (body as { data: unknown }).data === 'object'\n ) {\n const data = (body as { data: { attributes?: { username?: string } } }).data;\n return data.attributes?.username;\n }\n return undefined;\n}\n\nexport interface FindWorkspaceInput extends TfcAuth {\n /** Tag set the workspace must carry. For our use case: `['opuspopuli', 'cloudflare']`. */\n tags: string[];\n /** Optional name to disambiguate when multiple workspaces share the tag set. */\n name?: string;\n}\n\nexport interface TfcWorkspace {\n id: string;\n name: string;\n /** Latest run id, used to poll for apply completion. */\n currentRunId: string | null;\n}\n\n/**\n * Find the workspace this region's Terraform code will run in.\n *\n * TFC's filter syntax for tags is `filter[tagged]=tag1,tag2`. We ask for all\n * matches and let the caller pick by `name` when there's ambiguity (one TFC\n * org can host many workspaces with the same tag set).\n */\nexport async function findWorkspace(input: FindWorkspaceInput): Promise<TfcWorkspace | null> {\n if (!isValidTfcOrgSlug(input.organization)) return null;\n const tagFilter = encodeURIComponent(input.tags.join(','));\n const res = await getJson(\n input.token,\n `/organizations/${encodeURIComponent(input.organization)}/workspaces?filter[tagged]=${tagFilter}&page[size]=100`,\n );\n if (res.status !== 200) return null;\n\n const items = extractWorkspaceList(res.body);\n if (items.length === 0) return null;\n\n const match = input.name ? items.find((w) => w.name === input.name) : items[0];\n return match ?? null;\n}\n\ninterface RawWorkspace {\n id: string;\n attributes?: { name?: string };\n relationships?: { 'current-run'?: { data?: { id?: string } | null } };\n}\n\nfunction extractWorkspaceList(body: unknown): TfcWorkspace[] {\n if (\n typeof body !== 'object' ||\n body === null ||\n !('data' in body) ||\n !Array.isArray((body as { data: unknown }).data)\n ) {\n return [];\n }\n const data = (body as { data: RawWorkspace[] }).data;\n return data.map((w) => ({\n id: w.id,\n name: w.attributes?.name ?? '',\n currentRunId: w.relationships?.['current-run']?.data?.id ?? null,\n }));\n}\n\nexport interface TfcRunStatus {\n id: string;\n status: string;\n /** `true` once the run reached a terminal state (applied / errored / canceled / discarded). */\n finished: boolean;\n /** `true` only when the run finished successfully (`applied`). */\n succeeded: boolean;\n}\n\nconst TERMINAL_STATUSES = new Set([\n 'applied',\n 'errored',\n 'canceled',\n 'discarded',\n 'policy_soft_failed',\n 'force_canceled',\n]);\n\n/**\n * Look up a single TFC run by id. Used while we're waiting for the first\n * `terraform apply` to finish.\n */\nexport async function getRunStatus(\n auth: TfcAuth,\n runId: string,\n): Promise<TfcRunStatus | null> {\n // runId comes from a previous TFC response — trusted shape — but\n // encodeURIComponent is cheap defense if it's ever sourced from elsewhere.\n const res = await getJson(auth.token, `/runs/${encodeURIComponent(runId)}`);\n if (res.status !== 200) return null;\n\n const body = res.body as {\n data?: { id?: string; attributes?: { status?: string } };\n };\n const id = body.data?.id;\n const status = body.data?.attributes?.status;\n if (!id || !status) return null;\n\n return {\n id,\n status,\n finished: TERMINAL_STATUSES.has(status),\n succeeded: status === 'applied',\n };\n}\n\n/**\n * Pull a named output value from a workspace's current state version.\n * Returns `null` when:\n *\n * - the workspace, token, or HTTP call fails (any non-200 status)\n * - the named output isn't present in the response\n * - the output value isn't a string (e.g. the operator changed the type)\n *\n * Caller should poll the matching run for `applied` status first; an\n * in-flight workspace returns a 404 / 425 here.\n */\nexport async function fetchOutput(\n auth: TfcAuth,\n workspaceId: string,\n outputName: string,\n): Promise<string | null> {\n const res = await getJson(\n auth.token,\n `/workspaces/${encodeURIComponent(workspaceId)}/current-state-version-outputs`,\n );\n if (res.status !== 200) return null;\n\n const body = res.body as {\n data?: Array<{ attributes?: { name?: string; value?: unknown; sensitive?: boolean } }>;\n };\n const match = body.data?.find((o) => o.attributes?.name === outputName);\n if (!match) return null;\n\n const value = match.attributes?.value;\n return typeof value === 'string' ? value : null;\n}\n","/**\n * Shared `execa` wrapper for the few CLIs the wizard shells out to (`op`, `gh`).\n *\n * Two patterns this exists to share:\n *\n * 1. `reject: false` is opt-out on every call, since we want to inspect the\n * exit code rather than have a thrown error fan out across the wizard.\n * 2. **ENOENT doesn't suppress** under `reject: false` — that's a spawn\n * error, not a child-process exit. Callers that don't catch it crash.\n * `safeExeca` traps `ENOENT` / `ENOTDIR` and returns `null` so callers\n * can branch on \"binary not installed at all\" cleanly.\n *\n * The shape kept narrow on purpose — adds nothing execa doesn't, just makes\n * the failure modes uniform across call sites.\n */\n\nimport { execa, ExecaError } from 'execa';\n\nexport interface SafeExecaResult {\n /** Exit code from the child. `undefined` when the child was killed by a\n * signal — we pass it through honestly so callers can distinguish\n * signal-killed from clean zero. */\n exitCode: number | undefined;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Run a command; return `null` when the binary isn't on PATH at all, an\n * object with exit code + output otherwise. Never throws on a missing\n * binary, never throws on a non-zero exit.\n */\nexport async function safeExeca(\n cmd: string,\n args: string[],\n options?: {\n input?: string;\n /** Working directory for the child. Defaults to the parent's cwd. */\n cwd?: string;\n /** Extra env vars merged into the child's env (execa's default\n * extendEnv: true means these add to process.env rather than\n * replace). Used by bootstrap's compose subprocess calls so the\n * Keychain-loaded secrets reach docker compose without first\n * being written to a plaintext .env file on disk. */\n env?: NodeJS.ProcessEnv;\n },\n): Promise<SafeExecaResult | null> {\n try {\n const result = await execa(cmd, args, { reject: false, ...options });\n return {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n };\n } catch (err) {\n const e = err as ExecaError & NodeJS.ErrnoException;\n if (e.code === 'ENOENT' || e.code === 'ENOTDIR') return null;\n throw err;\n }\n}\n","/**\n * macOS Keychain wrapper around the built-in `security` CLI.\n *\n * Replaces the 1Password integration as of v0.3.0: secrets live in the\n * operator's login keychain (FileVault-encrypted at rest, locked with\n * the user session). Generic-password items only — we don't need\n * internet-password semantics.\n *\n * **Cross-device caveat:** the `security` CLI cannot create iCloud-\n * Keychain-synchronizable items (no `kSecAttrSynchronizable` flag is\n * exposed). Items written here stay on the machine they were written\n * on. `init` writes on the laptop; `bootstrap` reads on the Studio.\n * On a Studio miss, bootstrap falls back to prompting the operator to\n * paste the value and persists it locally for re-runs.\n *\n * **Argv exposure caveat:** `security add-generic-password -w <value>`\n * passes the secret via argv. It's briefly visible to anyone running\n * `ps -E` while the child is alive. Same risk model as the\n * `op item create notesPlain=<value>` pattern we previously accepted.\n * If a future `security` release adds a stdin form, swap to it here.\n */\n\nimport { safeExeca } from './exec.js';\n\n/** Reverse-DNS prefix for all Opus Populi entries in Keychain Access. */\nconst SERVICE_PREFIX = 'org.opuspopuli';\n\nexport type SecretAccount =\n | 'pgsodium-root-key'\n | 'tunnel-token'\n | 'postgres-password'\n | 'jwt-secret'\n | 'supabase-anon-key'\n | 'supabase-service-role-key'\n | 'dashboard-password'\n | 'prompts-db-password'\n | 'prompt-service-api-key'\n | 'prompt-service-admin-api-key';\n\nexport interface SecretCoordinates {\n /** Region label, used to scope the service identifier. */\n region: string;\n /** Which secret within the region. */\n account: SecretAccount;\n}\n\nfunction serviceFor(region: string): string {\n return `${SERVICE_PREFIX}.${region}`;\n}\n\nconst FRIENDLY: Record<SecretAccount, string> = {\n 'pgsodium-root-key': 'pgsodium root key',\n 'tunnel-token': 'Cloudflare Tunnel token',\n 'postgres-password': 'Postgres password',\n 'jwt-secret': 'JWT signing secret',\n 'supabase-anon-key': 'Supabase anon key',\n 'supabase-service-role-key': 'Supabase service role key',\n 'dashboard-password': 'Supabase Studio dashboard password',\n 'prompts-db-password': 'prompt-service Postgres password',\n 'prompt-service-api-key': 'prompt-service HMAC API key',\n 'prompt-service-admin-api-key': 'prompt-service admin API key',\n};\n\nfunction labelFor(coords: SecretCoordinates): string {\n return `Opus Populi (${coords.region}) — ${FRIENDLY[coords.account]}`;\n}\n\nexport interface KeychainAvailability {\n /** True when the `security` CLI ran cleanly (macOS or compatible). On\n * non-macOS hosts this is false and callers should fall back to\n * prompt-only flows. */\n available: boolean;\n /** Free-text reason when unavailable. */\n reason?: string;\n}\n\nexport async function detectKeychain(): Promise<KeychainAvailability> {\n const res = await safeExeca('security', ['-h']);\n if (res === null) {\n return {\n available: false,\n reason: '`security` CLI not on PATH (Keychain requires macOS)',\n };\n }\n return { available: true };\n}\n\nexport interface SaveSecretResult {\n written: boolean;\n /** True when an item already existed and was updated (via -U upsert). */\n updated: boolean;\n reason?: string;\n}\n\n/**\n * Write a generic-password item, upserting if it already exists. Uses\n * `add-generic-password -U` so re-runs don't error on duplicates.\n */\nexport async function saveSecret(\n coords: SecretCoordinates,\n value: string,\n): Promise<SaveSecretResult> {\n const service = serviceFor(coords.region);\n const label = labelFor(coords);\n\n // Check whether the item exists ahead of the upsert so we can report\n // `updated: true` vs `written: true` to the caller (purely informational —\n // the operator sees a different message in the wizard).\n const existing = await safeExeca('security', [\n 'find-generic-password',\n '-s',\n service,\n '-a',\n coords.account,\n ]);\n const updated = existing !== null && existing.exitCode === 0;\n\n const res = await safeExeca('security', [\n 'add-generic-password',\n '-U', // upsert\n '-s', service,\n '-a', coords.account,\n '-l', label,\n '-D', 'Opus Populi secret',\n '-w', value, // argv-exposure caveat, see file header\n ]);\n if (res === null) {\n return { written: false, updated: false, reason: '`security` CLI not on PATH' };\n }\n if (res.exitCode !== 0) {\n return {\n written: false,\n updated,\n reason: `security add-generic-password failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}${formatKeychainHint(res.exitCode)}`,\n };\n }\n return { written: true, updated };\n}\n\n/**\n * Read a generic-password item by service + account. Returns `null` when\n * the item doesn't exist, `security` isn't available, or the value is\n * empty. Callers branch to a paste prompt on `null`.\n */\nexport async function readSecret(coords: SecretCoordinates): Promise<string | null> {\n const service = serviceFor(coords.region);\n\n const res = await safeExeca('security', [\n 'find-generic-password',\n '-s', service,\n '-a', coords.account,\n '-w', // print the password to stdout (final flag = read mode)\n ]);\n if (res === null || res.exitCode !== 0) return null;\n const value = res.stdout.trim();\n return value.length > 0 ? value : null;\n}\n\n/** Delete a generic-password item. Idempotent — missing items return ok. */\nexport async function deleteSecret(coords: SecretCoordinates): Promise<{ ok: boolean; reason?: string }> {\n const service = serviceFor(coords.region);\n\n const res = await safeExeca('security', [\n 'delete-generic-password',\n '-s', service,\n '-a', coords.account,\n ]);\n if (res === null) return { ok: false, reason: '`security` CLI not on PATH' };\n // Exit 44 (errSecItemNotFound) is fine — already gone.\n if (res.exitCode === 0 || res.exitCode === ERR_SEC_ITEM_NOT_FOUND) return { ok: true };\n return {\n ok: false,\n reason: `security delete-generic-password failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}${formatKeychainHint(res.exitCode)}`,\n };\n}\n\n/**\n * macOS `security` exit codes we care about. Defined as constants so callers\n * can reason about them without sprinkling magic numbers.\n * 36 = errSecInteractionNotAllowed — keychain is locked / no UI session\n * 44 = errSecItemNotFound — item doesn't exist (treated as \"ok\" for delete)\n */\nexport const ERR_SEC_INTERACTION_NOT_ALLOWED = 36;\nexport const ERR_SEC_ITEM_NOT_FOUND = 44;\n\n/** Append an operator-friendly remediation hint to a `security` error\n * message when the exit code maps to one we recognize. Returns empty\n * string when no hint applies, so the call site can safely concatenate. */\nfunction formatKeychainHint(exitCode: number | null | undefined): string {\n if (exitCode === ERR_SEC_INTERACTION_NOT_ALLOWED) {\n return (\n `\\n` +\n `Hint: the login keychain is locked (SSH sessions don't auto-unlock it).\\n` +\n `Run \\`security unlock-keychain ~/Library/Keychains/login.keychain-db\\` and re-run bootstrap.`\n );\n }\n return '';\n}\n\n/**\n * Probe whether the login keychain is currently locked. Implemented by\n * attempting a no-op `find-generic-password` against a service that won't\n * exist: exit 44 (errSecItemNotFound) → unlocked, exit 36 → locked.\n *\n * Used by bootstrap to proactively prompt SSH operators for their login\n * password before the first Keychain write — without this, the operator\n * gets nine identical failures (one per secret) before they figure out\n * the keychain is locked.\n */\nexport async function isKeychainLocked(): Promise<boolean> {\n const res = await safeExeca('security', [\n 'find-generic-password',\n '-s',\n `${SERVICE_PREFIX}.__op_node_lock_probe__`,\n '-a',\n '__nothing_here__',\n ]);\n if (res === null) return false; // no security CLI; can't be locked\n return res.exitCode === ERR_SEC_INTERACTION_NOT_ALLOWED;\n}\n\nexport interface UnlockResult {\n ok: boolean;\n reason?: string;\n}\n\n/**\n * Unlock the login keychain via `security unlock-keychain -p <password>`.\n *\n * argv-exposure caveat: the password is visible briefly to `ps -E` while\n * the security child is alive. Same risk model as `saveSecret` writing\n * the secret value via `-w`. The `security` CLI doesn't expose a stdin\n * password form for unlock, so this is the cleanest option available.\n *\n * Callers should prompt the operator via clack's `p.password()` (which\n * doesn't echo) and pass the value here.\n */\nexport async function unlockKeychain(password: string): Promise<UnlockResult> {\n const res = await safeExeca('security', [\n 'unlock-keychain',\n '-p',\n password,\n // Default keychain path — same as the operator's GUI login keychain\n // on a stock macOS install. Lets us avoid a homedir lookup here.\n `${process.env['HOME'] ?? ''}/Library/Keychains/login.keychain-db`,\n ]);\n if (res === null) return { ok: false, reason: '`security` CLI not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `security unlock-keychain failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\n/** Heuristic: are we running inside an SSH session?\n * `SSH_CONNECTION` is set by sshd on every interactive login. `SSH_TTY`\n * is set on TTY-allocated sessions; we check both. Process-env only —\n * no syscalls. */\nexport function isSshSession(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env['SSH_CONNECTION'] ?? env['SSH_TTY']);\n}\n\n/** Exported for tests + the rare caller that needs the raw service string. */\nexport const _internal = {\n serviceFor,\n labelFor,\n SERVICE_PREFIX,\n};\n","/**\n * Tiny shared helper around @clack/prompts' cancel sentinel.\n *\n * Every wizard subcommand wants the same shape: ask for a value, if the\n * operator hit Ctrl-C / Esc, exit cleanly with a \"Cancelled.\" note. Without\n * this helper each call site duplicates the `p.isCancel` check + `p.cancel`\n * + `process.exit(0)`.\n *\n * Keeping it dead-simple — no return-value transformation, no async, no\n * exit-code override. Subcommands that want a different exit policy\n * shouldn't use this helper.\n */\n\nimport * as p from '@clack/prompts';\n\nexport function unwrap<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n return value;\n}\n","/**\n * GitHub helpers used by `create-op-node init`.\n *\n * Mix of two clients on purpose:\n *\n * - Octokit (REST) for typed API calls — create-from-template, content\n * write, PR open. These return well-shaped data we care about (URLs,\n * SHAs).\n * - `gh` CLI shell-out for repository secret seeding. Secrets need to be\n * encrypted with the repo's libsodium public key before PUT — Octokit\n * doesn't bundle libsodium and the wrapper packages are ~800 KB.\n * `gh secret set` does the encryption transparently. The operator\n * already has `gh` (it's part of the runbook), so the dep is free.\n *\n * The Octokit instance is created lazily so a missing token surfaces as a\n * clear error rather than a cryptic auth failure inside a downstream call.\n */\n\nimport { Octokit } from '@octokit/rest';\n\nimport { safeExeca } from './exec.js';\n\nexport interface GhAuth {\n /** A GitHub Personal Access Token (Classic or Fine-grained) with at least\n * `repo` scope. */\n token: string;\n}\n\n// One Octokit per token — fine for a one-shot CLI. NOT safe to wire into a\n// long-running service that issues calls under different identities; the\n// memoization will hand out the wrong client. If that ever happens, key the\n// cache by (token, …other-dimensions) or drop the memoization.\nlet _client: Octokit | null = null;\nlet _clientToken: string | null = null;\n\nfunction client(token: string): Octokit {\n if (_client && _clientToken === token) return _client;\n _client = new Octokit({ auth: token });\n _clientToken = token;\n return _client;\n}\n\n// Test-only: reset the memoized client between cases. Not exported via\n// index, intentionally — tests reach into the module.\nexport function _resetClient(): void {\n _client = null;\n _clientToken = null;\n}\n\n// ----------------------------------------------------------------------------\n// Create from template\n// ----------------------------------------------------------------------------\n\nexport interface CreateFromTemplateInput extends GhAuth {\n /** `<owner>/<repo>` of the template repo, e.g. `OpusPopuli/opuspopuli-node`. */\n template: string;\n /** The new repo's owner (user or org). */\n owner: string;\n /** The new repo's name. */\n name: string;\n /** Optional repo description. */\n description?: string;\n /** When true, create the repo as private. Default: false (public). */\n private?: boolean;\n /** Include all template branches, not just default. Default: false. */\n includeAllBranches?: boolean;\n}\n\nexport interface CreatedRepo {\n fullName: string;\n htmlUrl: string;\n defaultBranch: string;\n}\n\n/**\n * Create a new repository from a template repository. Wraps\n * `POST /repos/{template_owner}/{template_repo}/generate`.\n *\n * Caller should handle \"repository already exists\" as a recoverable case —\n * the operator may have started + abandoned a previous run. We throw on the\n * 422 (already exists) so the caller can show a \"use existing? overwrite?\"\n * prompt.\n */\nexport async function createRepoFromTemplate(\n input: CreateFromTemplateInput,\n): Promise<CreatedRepo> {\n const [templateOwner, templateRepo] = input.template.split('/');\n if (!templateOwner || !templateRepo) {\n throw new Error(`Bad template spec \"${input.template}\" — expected <owner>/<repo>`);\n }\n\n const res = await client(input.token).request(\n 'POST /repos/{template_owner}/{template_repo}/generate',\n {\n template_owner: templateOwner,\n template_repo: templateRepo,\n owner: input.owner,\n name: input.name,\n private: input.private ?? false,\n include_all_branches: input.includeAllBranches ?? false,\n ...(input.description ? { description: input.description } : {}),\n },\n );\n\n return {\n fullName: res.data.full_name,\n htmlUrl: res.data.html_url,\n defaultBranch: res.data.default_branch ?? 'main',\n };\n}\n\n// ----------------------------------------------------------------------------\n// Seed secrets via gh CLI\n// ----------------------------------------------------------------------------\n\nexport interface SetRepoSecretInput {\n /** `<owner>/<repo>`. */\n repo: string;\n /** Secret name (e.g. `CLOUDFLARE_API_TOKEN`). */\n name: string;\n /** Secret value. Passed via stdin to `gh secret set` so it never lands in\n * argv or the shell history. */\n value: string;\n}\n\nexport interface SetSecretResult {\n written: boolean;\n reason?: string;\n}\n\n/**\n * Set a single repository Actions secret via `gh secret set`. Value is piped\n * on stdin — never on argv — so it doesn't land in process listing or any\n * shell history. Returns `written: false` with a clear reason when `gh`\n * isn't installed (B2 — required for the `--gh-token` escape hatch where the\n * operator supplies a PAT and may not have `gh` at all).\n */\nexport async function setRepoSecret(input: SetRepoSecretInput): Promise<SetSecretResult> {\n const res = await safeExeca(\n 'gh',\n ['secret', 'set', input.name, '--repo', input.repo, '--body', '-'],\n { input: input.value },\n );\n if (res === null) {\n return {\n written: false,\n reason: '`gh` CLI not installed — install from https://cli.github.com or seed secrets manually',\n };\n }\n if (res.exitCode !== 0) {\n return {\n written: false,\n reason: `gh secret set failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { written: true };\n}\n\n// ----------------------------------------------------------------------------\n// Content write + PR open\n// ----------------------------------------------------------------------------\n\nexport interface CommitFileInput extends GhAuth {\n /** `<owner>/<repo>`. */\n repo: string;\n /** Branch to commit on. The caller creates the branch first via\n * `createBranch` when committing to a non-default branch. */\n branch: string;\n /** Repo-relative path (e.g. `infra/cloudflare/environments/prod.tfvars`). */\n path: string;\n /** File contents, plain text. We base64-encode for the API. */\n content: string;\n /** Commit message. */\n message: string;\n}\n\nexport interface CommitFileResult {\n commitSha: string;\n contentSha: string;\n}\n\n/**\n * Create or update a file in a repo's branch via the Contents API. Handles\n * both cases transparently — looks up the existing file's SHA when present\n * and includes it in the update.\n */\nexport async function commitFile(input: CommitFileInput): Promise<CommitFileResult> {\n const [owner, repo] = input.repo.split('/');\n if (!owner || !repo) {\n throw new Error(`Bad repo \"${input.repo}\" — expected <owner>/<repo>`);\n }\n\n const octokit = client(input.token);\n\n let existingSha: string | undefined;\n try {\n const existing = await octokit.repos.getContent({\n owner,\n repo,\n path: input.path,\n ref: input.branch,\n });\n if (!Array.isArray(existing.data) && existing.data.type === 'file') {\n existingSha = existing.data.sha;\n }\n } catch (err: unknown) {\n // 404 is fine — file just doesn't exist yet. Re-throw anything else.\n if (!is404(err)) throw err;\n }\n\n const res = await octokit.repos.createOrUpdateFileContents({\n owner,\n repo,\n path: input.path,\n branch: input.branch,\n message: input.message,\n content: Buffer.from(input.content, 'utf8').toString('base64'),\n ...(existingSha ? { sha: existingSha } : {}),\n });\n\n return {\n commitSha: res.data.commit.sha ?? '',\n contentSha: res.data.content?.sha ?? '',\n };\n}\n\nfunction is404(err: unknown): boolean {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'status' in err &&\n (err as { status: number }).status === 404\n );\n}\n\nexport interface CreateBranchInput extends GhAuth {\n repo: string;\n /** Name of the new branch. */\n branch: string;\n /** Name of the branch to fork from. */\n fromBranch: string;\n}\n\n/** Create a new branch by copying the head commit of `fromBranch`. */\nexport async function createBranch(input: CreateBranchInput): Promise<void> {\n const [owner, repo] = input.repo.split('/');\n if (!owner || !repo) {\n throw new Error(`Bad repo \"${input.repo}\" — expected <owner>/<repo>`);\n }\n const octokit = client(input.token);\n\n const ref = await octokit.git.getRef({\n owner,\n repo,\n ref: `heads/${input.fromBranch}`,\n });\n await octokit.git.createRef({\n owner,\n repo,\n ref: `refs/heads/${input.branch}`,\n sha: ref.data.object.sha,\n });\n}\n\nexport interface OpenPrInput extends GhAuth {\n repo: string;\n /** Branch to merge from. */\n head: string;\n /** Branch to merge into. */\n base: string;\n title: string;\n body: string;\n}\n\nexport interface OpenedPr {\n number: number;\n htmlUrl: string;\n}\n\n/** Open a pull request. Returns the PR number + URL so the caller can show\n * it to the operator. */\nexport async function openPullRequest(input: OpenPrInput): Promise<OpenedPr> {\n const [owner, repo] = input.repo.split('/');\n if (!owner || !repo) {\n throw new Error(`Bad repo \"${input.repo}\" — expected <owner>/<repo>`);\n }\n const octokit = client(input.token);\n\n const res = await octokit.pulls.create({\n owner,\n repo,\n head: input.head,\n base: input.base,\n title: input.title,\n body: input.body,\n });\n\n return { number: res.data.number, htmlUrl: res.data.html_url };\n}\n","/**\n * Small pure helpers for the local-state-only bits of `create-op-node init`:\n * generating a fresh pgsodium master key, and rendering a region's\n * `prod.tfvars` file.\n *\n * Both are side-effect free — they produce strings the caller decides what to\n * do with. Tests exercise them in isolation.\n */\n\nimport { createHmac, randomBytes } from 'node:crypto';\n\n/**\n * Generate a 32-byte (256-bit) key encoded as 64 lowercase hex characters —\n * the format `pgsodium` expects in `PGSODIUM_ROOT_KEY` and what the runbook\n * documents. The bytes come from Node's CSPRNG.\n */\nexport function generatePgsodiumRootKey(): string {\n return randomBytes(32).toString('hex');\n}\n\n/**\n * url-safe base64 helper (RFC 4648 §5) — the JWT spec mandates this variant\n * (no `+`, no `/`, no padding). `Buffer#toString('base64url')` exists on\n * Node ≥ 16 but expressing it locally keeps the dependency surface tiny and\n * avoids type-coverage games across older `@types/node`.\n */\nfunction base64url(input: Buffer | string): string {\n const buf = typeof input === 'string' ? Buffer.from(input) : input;\n return buf\n .toString('base64')\n // base64 padding `=` only ever appears at the end, so stripping every `=`\n // is equivalent to `/=+$/` and avoids the anchored-quantifier backtracking.\n .replace(/=/g, '')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_');\n}\n\n/**\n * 32-byte CSPRNG password rendered as base64url (no `+`, no `/`, no `=`).\n * Used for POSTGRES_PASSWORD — every Supabase admin user (supabase_admin,\n * authenticator, pgbouncer, supabase_auth_admin, supabase_functions_admin,\n * supabase_storage_admin) shares this one password by design of the\n * upstream init scripts.\n *\n * MUST be URL-safe: the value lands in postgres:// connection-string URIs\n * inside docker-compose env vars (gotrue, postgrest, storage). libpq parses\n * those as RFC 3986 URIs, so `/` would terminate the password component and\n * `+`/`=` are reserved sub-delims that can confuse some URI parsers. base64url\n * keeps the alphabet to `[A-Za-z0-9_-]` which is unambiguously safe in every\n * URI component.\n *\n * 32 bytes → 256 bits of entropy. The base64url encoding is ~43 chars (no\n * padding) — well above what any offline attack on a bcrypt store could\n * threaten.\n */\nexport function generatePostgresPassword(): string {\n return base64url(randomBytes(32));\n}\n\n/** Alias for clarity at the call site. Also base64url so it composes safely\n * into kong's declarative config (where DASHBOARD_PASSWORD is interpolated). */\nexport function generateDashboardPassword(): string {\n return base64url(randomBytes(24));\n}\n\n/**\n * 32-byte CSPRNG HMAC key rendered as base64url. Used for the prompt-service\n * client HMAC: prompt-service's `API_KEYS` env is a comma-separated list of\n * `<region>:<key>` pairs, and the consuming backend sends the same `<key>`\n * value in its HMAC header.\n *\n * Base64url alphabet ensures the value survives the `<region>:<key>` join\n * and any URL-component embedding without ambiguity.\n */\nexport function generateHmacApiKey(): string {\n return base64url(randomBytes(32));\n}\n\n/**\n * 48-byte (384-bit) base64 secret used to sign every Supabase-issued JWT.\n *\n * gotrue, postgrest, storage, and studio all verify tokens against this\n * value, so it must stay identical across the stack and across restarts.\n * Treat it like a master key — rotating it invalidates every session and\n * every long-lived ANON/SERVICE_ROLE token derived from it.\n */\nexport function generateJwtSecret(): string {\n return randomBytes(48).toString('base64');\n}\n\nexport type SupabaseRole = 'anon' | 'service_role';\n\nexport interface SupabaseJwtInput {\n role: SupabaseRole;\n /** HS256 signing key — same JWT_SECRET that gotrue/postgrest verify with. */\n secret: string;\n /** `iat` claim, seconds since epoch. Defaults to 1700000000 (2023-11-14)\n * — a stable past timestamp. This is deliberate, not a test artifact:\n * bootstrap re-runs generate the SAME token shape so we don't churn\n * the cached Keychain entry on every invocation. Pass `Date.now()/1000`\n * if you need a fresh `iat` (e.g. tests that exercise expiry handling). */\n issuedAtSeconds?: number;\n /** Token lifetime in seconds. Default: 10 years — Supabase's own\n * self-hosting docs ship `exp = iat + 10y` for the long-lived\n * anon + service_role keys. */\n ttlSeconds?: number;\n /** `iss` claim. Default: `supabase`. */\n issuer?: string;\n}\n\n/**\n * Verify that a stored JWT's signature was produced by the given secret.\n *\n * Constant-time-ish compare via Buffer length + manual byte loop — the\n * tokens are short and rare enough that the timing channel here doesn't\n * meaningfully advantage an attacker (and the attacker would need to be\n * able to feed bootstrap arbitrary candidate tokens, which they can't).\n *\n * Use case: bootstrap loaded supabase-anon-key from Keychain, but JWT_SECRET\n * may have rotated since. If the cached token's signature doesn't match the\n * current secret, we treat it as stale and regenerate. Without this check,\n * a partial Keychain wipe (e.g. operator deletes only jwt-secret) leaves\n * the derived tokens looking valid by shape but useless against gotrue/\n * postgrest, and every auth call silently fails 401.\n */\nexport function verifySupabaseJwt(token: string, secret: string): boolean {\n const parts = token.split('.');\n if (parts.length !== 3) return false;\n const [h, p, sig] = parts as [string, string, string];\n const expected = base64url(createHmac('sha256', secret).update(`${h}.${p}`).digest());\n if (sig.length !== expected.length) return false;\n let mismatch = 0;\n for (let i = 0; i < sig.length; i++) {\n mismatch |= sig.charCodeAt(i) ^ expected.charCodeAt(i);\n }\n return mismatch === 0;\n}\n\n/**\n * Mint a Supabase-shaped HS256 JWT for the `anon` or `service_role` claim.\n *\n * Shape matches what the official `supabase` CLI / hosted-Supabase docs\n * produce, so the token works with @supabase/supabase-js, postgrest's\n * `Authorization: Bearer …`, storage-api, and Studio out of the box.\n *\n * No third-party JWT lib — we'd have to add `jsonwebtoken` (+ its CVE\n * history) for ~30 lines of HMAC code. Implementing it here keeps the\n * dep tree clean and the algorithm pinned to HS256 by construction.\n */\nexport function signSupabaseJwt(input: SupabaseJwtInput): string {\n const iat = input.issuedAtSeconds ?? 1_700_000_000;\n const ttl = input.ttlSeconds ?? 10 * 365 * 24 * 60 * 60;\n const issuer = input.issuer ?? 'supabase';\n\n const header = { alg: 'HS256', typ: 'JWT' };\n const payload = {\n role: input.role,\n iss: issuer,\n iat,\n exp: iat + ttl,\n };\n\n const encodedHeader = base64url(JSON.stringify(header));\n const encodedPayload = base64url(JSON.stringify(payload));\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signature = base64url(\n createHmac('sha256', input.secret).update(signingInput).digest(),\n );\n return `${signingInput}.${signature}`;\n}\n\nexport interface ProdTfvarsInput {\n /** Resource-name prefix used across the Terraform module\n * (e.g. `<project>-tunnel-prod`). Defaults to `opuspopuli`. */\n project?: string;\n /** Operator's registered domain in Cloudflare (e.g. `civicfeed.tx`). */\n domain: string;\n /** Subdomain for the API tunnel (e.g. `api`). Default: `api`. */\n apiSubdomain?: string;\n /** Subdomain for the Cloudflare Pages frontend (e.g. `app`). Default: `app`. */\n appSubdomain?: string;\n /** Local port the API Gateway listens on inside the Studio. Default: 8080. */\n tunnelApiPort?: number;\n /** R2 region hint. Default: `WNAM` (Western North America). */\n r2LocationHint?: string;\n}\n\n/**\n * Render a region operator's `prod.tfvars` from their answers. Mirrors the\n * shape of `opuspopuli-node/infra/cloudflare/environments/prod.tfvars.example`\n * so the file lands ready for the cloudflare-infra workflow without any\n * post-processing.\n *\n * The output is the literal file contents — caller writes it to the repo via\n * the GitHub Contents API (`commitFile`).\n */\nexport function renderProdTfvars(input: ProdTfvarsInput): string {\n const project = input.project ?? 'opuspopuli';\n const api = input.apiSubdomain ?? 'api';\n const app = input.appSubdomain ?? 'app';\n const port = input.tunnelApiPort ?? 8080;\n const r2 = input.r2LocationHint ?? 'WNAM';\n\n return `# =============================================================================\n# Production environment — generated by create-op-node init\n# =============================================================================\n# Region-specific values for the OpusPopuli/opuspopuli-node template's\n# infra/cloudflare/ Terraform. Edit by hand to tweak.\n\nproject = ${JSON.stringify(project)}\n\ndomain_name = ${JSON.stringify(input.domain)}\n\napi_subdomain = ${JSON.stringify(api)}\napp_subdomain = ${JSON.stringify(app)}\n\ntunnel_api_port = ${port}\n\nr2_location_hint = ${JSON.stringify(r2)}\n\nenable_tunnel = true\nenable_frontend = true\nenable_r2 = true\n`;\n}\n","/**\n * Generic two-phase TFC apply-and-output wait. Two independent clocks:\n *\n * 1. **Discovery phase** — wait for the workspace to have a current run.\n * The cloudflare-infra workflow takes a few seconds to dispatch to TFC\n * after the operator merges the PR, so we re-poll the workspace until\n * a run id appears or the discovery budget elapses.\n * 2. **Run phase** — wait for that run to reach a terminal state. Sharing\n * one clock with discovery would let slow discovery eat the run-wait\n * budget; two independent clocks isolate them.\n *\n * Dependencies are injected so unit tests can drive the loop without real\n * timers or HTTP. `sleep` is a parameter; tests pass a no-op.\n */\n\nimport { fetchOutput, findWorkspace, getRunStatus } from './tfc.js';\n\nexport interface WaitInput {\n token: string;\n organization: string;\n workspaceId: string;\n /** Last-known run id when starting. `null` triggers the discovery phase. */\n runId: string | null;\n /** Tags used to re-discover the workspace's current run id. */\n workspaceTags: string[];\n /** Output to pull once the run is `applied`. */\n outputName: string;\n}\n\nexport interface WaitBudgets {\n discoveryMs: number;\n runMs: number;\n pollMs: number;\n}\n\nexport const DEFAULT_BUDGETS: WaitBudgets = {\n discoveryMs: 60 * 1000,\n runMs: 10 * 60 * 1000,\n pollMs: 10 * 1000,\n};\n\nexport type WaitOutcome =\n | { kind: 'success'; value: string }\n | { kind: 'output-missing' }\n | { kind: 'no-run-started' }\n | { kind: 'run-failed'; status: string }\n | { kind: 'timeout' };\n\n/** Test seam: lets tests inject fake findWorkspace / getRunStatus / fetchOutput. */\nexport interface WaitDeps {\n findWorkspace: typeof findWorkspace;\n getRunStatus: typeof getRunStatus;\n fetchOutput: typeof fetchOutput;\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n /** Optional progress callback for UI integration (spinner messages, etc.). */\n onProgress?: (phase: 'discovery' | 'run' | 'fetching' | 'retry') => void;\n}\n\nexport const realDeps: WaitDeps = {\n findWorkspace,\n getRunStatus,\n fetchOutput,\n sleep: (ms) => new Promise((res) => setTimeout(res, ms)),\n now: () => Date.now(),\n};\n\n/**\n * Pure polling implementation. Returns a discriminated outcome so the caller\n * can render the right message for each terminal state.\n */\nexport async function waitForApply(\n input: WaitInput,\n budgets: WaitBudgets = DEFAULT_BUDGETS,\n deps: WaitDeps = realDeps,\n): Promise<WaitOutcome> {\n let runId = input.runId;\n if (!runId) {\n runId = await discoverRunId(input, budgets, deps);\n if (!runId) return { kind: 'no-run-started' };\n }\n return waitForRunOutput(input, budgets, deps, runId);\n}\n\n// Run a single poll attempt, degrading any throw to `null` (treated as \"no\n// result this interval, try again\"). Keeps a transient network failure from\n// rejecting out of the multi-minute wait loops. `onRetry` fires on a swallowed\n// throw so the caller can surface the hiccup instead of retrying in silence.\nasync function safePoll<T>(\n fn: () => Promise<T | null>,\n onRetry?: () => void,\n): Promise<T | null> {\n try {\n return await fn();\n } catch {\n onRetry?.();\n return null;\n }\n}\n\n// Phase 1: discovery — poll the workspace until it has a current run, or the\n// discovery budget expires. Returns the run id, or null on timeout.\nasync function discoverRunId(\n input: WaitInput,\n budgets: WaitBudgets,\n deps: WaitDeps,\n): Promise<string | null> {\n deps.onProgress?.('discovery');\n const discoveryStart = deps.now();\n while (deps.now() - discoveryStart < budgets.discoveryMs) {\n await deps.sleep(budgets.pollMs);\n // A transient failure is not fatal to a multi-minute discovery window —\n // swallow it and retry on the next poll rather than rejecting the wait.\n // (The tfc helpers already degrade throws to null, so this is\n // belt-and-suspenders against any future throwing dep.)\n const ws = await safePoll(\n () =>\n deps.findWorkspace({\n token: input.token,\n organization: input.organization,\n tags: input.workspaceTags,\n }),\n () => deps.onProgress?.('retry'),\n );\n if (ws?.currentRunId) return ws.currentRunId;\n }\n return null;\n}\n\n// Phase 2: run wait — poll the run until it finishes (fetching the output on\n// success), or the run budget expires.\nasync function waitForRunOutput(\n input: WaitInput,\n budgets: WaitBudgets,\n deps: WaitDeps,\n runId: string,\n): Promise<WaitOutcome> {\n deps.onProgress?.('run');\n const runStart = deps.now();\n while (deps.now() - runStart < budgets.runMs) {\n // Transient status-poll failure → retry next interval, don't abort the\n // ~10-minute run wait on a single bad packet.\n const r = await safePoll(\n () => deps.getRunStatus({ token: input.token, organization: input.organization }, runId),\n () => deps.onProgress?.('retry'),\n );\n if (r?.finished) {\n if (!r.succeeded) return { kind: 'run-failed', status: r.status };\n deps.onProgress?.('fetching');\n const value = await safePoll(\n () =>\n deps.fetchOutput(\n { token: input.token, organization: input.organization },\n input.workspaceId,\n input.outputName,\n ),\n () => deps.onProgress?.('retry'),\n );\n return value !== null ? { kind: 'success', value } : { kind: 'output-missing' };\n }\n await deps.sleep(budgets.pollMs);\n }\n\n return { kind: 'timeout' };\n}\n","import { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport { probeCloudflareToken } from '../lib/cloudflare.js';\nimport { probeTfcToken } from '../lib/tfc.js';\nimport { detectKeychain, readSecret, saveSecret } from '../lib/keychain.js';\nimport { safeExeca } from '../lib/exec.js';\nimport { unwrap } from '../lib/prompts.js';\nimport {\n commitFile,\n createBranch,\n createRepoFromTemplate,\n openPullRequest,\n setRepoSecret,\n} from '../lib/github.js';\nimport { generatePgsodiumRootKey, renderProdTfvars } from '../lib/secrets.js';\nimport { findWorkspace } from '../lib/tfc.js';\nimport { waitForApply, realDeps as realWaitDeps } from '../lib/polling.js';\n\nexport interface InitOptions {\n domain?: string;\n region?: string;\n owner?: string;\n template?: string;\n project?: string;\n cfToken?: string;\n cfAccount?: string;\n cfZone?: string;\n tfToken?: string;\n tfOrg?: string;\n ghToken?: string;\n overwrite?: boolean;\n useExistingRepo?: boolean;\n skipWait?: boolean;\n localOnly?: boolean;\n yes?: boolean;\n}\n\n/** Pull the GitHub token from `gh auth token` if the CLI is signed in. Lets\n * operators who use `gh` skip pasting their PAT. Returns null cleanly when\n * `gh` isn't installed or isn't signed in. */\nasync function ghTokenFromCli(): Promise<string | null> {\n const r = await safeExeca('gh', ['auth', 'token']);\n if (r === null || r.exitCode !== 0) return null;\n const token = r.stdout.trim();\n return token.length > 0 ? token : null;\n}\n\nexport const initCommand = new Command('init')\n .description(\n 'Stand up the node repo + Cloudflare infrastructure for a new region. Run this on your laptop.',\n )\n .addOption(new Option('--domain <domain>', 'Your registered domain (e.g. example.org)'))\n .addOption(new Option('--region <slug>', 'Short label for your region (e.g. us-ca)'))\n .addOption(new Option('--owner <owner>', 'GitHub owner for the new node repo').default('OpusPopuli'))\n .addOption(\n new Option('--template <owner/repo>', 'Template repo to clone from').default(\n 'OpusPopuli/opuspopuli-node',\n ),\n )\n .addOption(new Option('--project <name>', 'tfvars project prefix').default('opuspopuli'))\n .addOption(new Option('--cf-token <token>', 'Cloudflare Account API token').env('CF_TOKEN'))\n .addOption(new Option('--cf-account <id>', 'Cloudflare account ID').env('CF_ACCOUNT'))\n .addOption(new Option('--cf-zone <id>', 'Cloudflare zone ID for your domain').env('CF_ZONE'))\n .addOption(new Option('--tf-token <token>', 'Terraform Cloud user/team token').env('TF_API_TOKEN'))\n .addOption(new Option('--tf-org <org>', 'Terraform Cloud organization').env('TF_CLOUD_ORGANIZATION'))\n .addOption(new Option('--gh-token <token>', 'GitHub Personal Access Token (else gh CLI)').env('GH_TOKEN'))\n .addOption(\n new Option(\n '--overwrite',\n 'Overwrite existing Keychain items (pgsodium key, Tunnel token) on a re-run',\n ).default(false),\n )\n .addOption(\n new Option(\n '--use-existing-repo',\n \"Continue using a previously-created node repo (don't fail on 'already exists')\",\n ).default(false),\n )\n .addOption(new Option('--skip-wait', \"Don't poll for Terraform apply; exit after PR open\").default(false))\n .addOption(\n new Option(\n '--local-only',\n 'Skip the Cloudflare/TFC/PR/tunnel phases. Creates the region repo from template + stores a pgsodium key — enough for `bootstrap --local-only` to work.',\n ).default(false),\n )\n .addOption(new Option('-y, --yes', 'Skip the final confirmation').default(false))\n .action(async (opts: InitOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node init ')));\n printWelcomeNote(opts);\n\n const region = await resolveRegion(opts);\n const owner = opts.owner ?? 'OpusPopuli';\n const newRepoName = `opuspopuli-node-${region}`;\n const newRepoFull = `${owner}/${newRepoName}`;\n warnIgnoredLocalOnlyFlags(opts);\n\n // Collect domain + Cloudflare + TFC creds when running in production mode.\n // Returns null in --local-only — downstream branches on this once and the\n // typed presence carries through (no non-null assertions). (S1)\n const publicConfig = opts.localOnly ? null : await collectPublicConfig(opts);\n const ghToken = await resolveGhToken(opts);\n const keychain = await detectKeychain();\n printSecretStoreNote(keychain);\n\n await confirmPlan({ opts, region, owner, newRepoFull, publicConfig });\n\n const created = await createRegionRepo({ opts, ghToken, owner, newRepoName, newRepoFull, region });\n if (publicConfig) {\n await seedRepoSecrets({ publicConfig, newRepoFull });\n }\n const pr = publicConfig\n ? await openInfraPr({ opts, ghToken, region, newRepoFull, publicConfig, created })\n : null;\n\n await persistPgsodiumKey({ keychain, opts, region });\n\n // Local-only flow ends here. Gating on publicConfig (not opts.localOnly)\n // lets TS narrow it to non-null for the TFC poll block below.\n if (!publicConfig) {\n printLocalOnlyOutro({ region, newRepoFull });\n return;\n }\n if (!pr) {\n throw new Error('init: PR creation step did not run despite publicConfig present');\n }\n\n const proceed = await pauseForMerge({ pr, opts });\n if (!proceed) return;\n\n const tunnelToken = await fetchTunnelToken({ publicConfig });\n await persistTunnelToken({ keychain, region, tunnelToken });\n printDoneOutro(region);\n });\n\n// ----------------------------------------------------------------------------\n// Init phases\n// ----------------------------------------------------------------------------\n// The command action delegates to these phase helpers so no single function\n// exceeds the cognitive-complexity budget. Each is behavior-preserving — the\n// interactive prompts, spinners, and process.exit calls are relocated\n// verbatim, restructured only with early returns to flatten nesting.\n\nfunction printWelcomeNote(opts: InitOptions): void {\n p.note(\n opts.localOnly\n ? [\n 'Local-only setup — creates the region repo from template + a pgsodium key.',\n 'No Cloudflare, no Terraform Cloud, no public exposure.',\n '',\n pc.dim('Phase 1: laptop side (now) — GitHub repo from template + Keychain.'),\n pc.dim('Phase 2: Studio side — `create-op-node bootstrap --local-only`.'),\n '',\n pc.dim('When you\\'re ready to expose publicly, re-run `init` without --local-only.'),\n ].join('\\n')\n : [\n 'This walks you from a sealed Mac Studio + a Cloudflare account to a',\n 'live federation node serving traffic at api.<your-domain>.',\n '',\n pc.dim('Phase 1: laptop side (now) — Cloudflare, GitHub, Terraform Cloud.'),\n pc.dim('Phase 2: Studio side — run `create-op-node bootstrap` on the Mac.'),\n ].join('\\n'),\n 'Welcome',\n );\n}\n\n// Region label (used as the Keychain service suffix + R2 prefix).\nasync function resolveRegion(opts: InitOptions): Promise<string> {\n return opts.region\n ? opts.region\n : unwrap(\n await p.text({\n message: 'Short region label (used as the Keychain service suffix + R2 prefix)?',\n placeholder: 'us-ca',\n validate: (v) =>\n /^[a-z0-9-]{2,32}$/.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens; 2–32 chars',\n }),\n );\n}\n\n// Warn if the operator passed flags that don't apply to --local-only. They'd\n// otherwise be silently ignored and the operator would wonder why their\n// token/domain/etc. seemed to do nothing. (S2/S3)\nfunction warnIgnoredLocalOnlyFlags(opts: InitOptions): void {\n if (!opts.localOnly) return;\n const ignored = listIgnoredLocalOnlyFlags(opts);\n if (ignored.length === 0) return;\n p.note(\n pc.yellow(\n `⚠ The following ${ignored.length === 1 ? 'flag is' : 'flags are'} ignored with --local-only:\\n` +\n ` ${ignored.join(', ')}\\n` +\n pc.dim('These configure Cloudflare / TFC / PR-merge flow, which --local-only skips.'),\n ),\n 'Notice',\n );\n}\n\n// ---- GitHub auth: flag > signed-in gh CLI > paste prompt ----\nasync function resolveGhToken(opts: InitOptions): Promise<string> {\n let ghToken = opts.ghToken;\n if (!ghToken) {\n const fromCli = await ghTokenFromCli();\n if (fromCli) {\n const useCli = unwrap(\n await p.confirm({\n message: 'Found a signed-in `gh` CLI — use its token?',\n initialValue: true,\n }),\n );\n if (useCli) ghToken = fromCli;\n }\n }\n if (!ghToken) {\n ghToken = await collectSecret(\n undefined,\n 'GitHub Personal Access Token (repo scope)',\n 'github',\n );\n }\n return ghToken;\n}\n\nfunction printSecretStoreNote(keychain: Awaited<ReturnType<typeof detectKeychain>>): void {\n const kcNote = keychain.available\n ? `✓ macOS Keychain available — pgsodium key + Tunnel token will be saved to your login keychain.\\n` +\n pc.dim('Note: items don\\'t sync to iCloud Keychain via the security CLI.\\n') +\n pc.dim('On the Studio, bootstrap will read locally and prompt you to paste if missing.')\n : `⚠ ${keychain.reason ?? 'Keychain unavailable'}. Secrets will be printed for manual stash.`;\n p.note(kcNote, 'Secret store');\n}\n\n// ---- Plan summary + confirm ----\nasync function confirmPlan(args: {\n opts: InitOptions;\n region: string;\n owner: string;\n newRepoFull: string;\n publicConfig: PublicConfig | null;\n}): Promise<void> {\n const { opts, region, owner, newRepoFull, publicConfig } = args;\n const orgWriteAccess = pc.dim(`required for ${owner}`);\n p.note(\n opts.localOnly\n ? [\n `Region label: ${pc.cyan(region)}`,\n `New node repo: ${pc.cyan(newRepoFull)}`,\n `Template: ${pc.dim(opts.template ?? 'OpusPopuli/opuspopuli-node')}`,\n `GH org write access: ${orgWriteAccess}`,\n ``,\n `Will create the repo from template (private, no Cloudflare),`,\n `and store a fresh pgsodium key in Keychain. That's it — no PR,`,\n `no terraform, no tunnel token. Bootstrap on the Studio with`,\n `\\`bootstrap --local-only --region ${region}\\` next.`,\n ].join('\\n')\n : [\n `Region label: ${pc.cyan(region)}`,\n `Domain: ${pc.cyan(publicConfig?.domain ?? '')}`,\n `New node repo: ${pc.cyan(newRepoFull)}`,\n `Template: ${pc.dim(opts.template ?? 'OpusPopuli/opuspopuli-node')}`,\n `TFC organization: ${pc.cyan(publicConfig?.tfOrg ?? '')}`,\n `GH org write access: ${orgWriteAccess}`,\n ``,\n `Will create the repo, seed 5 secrets, write prod.tfvars on a branch,`,\n `open a PR, generate a fresh pgsodium key, and (after you merge) wait`,\n `for terraform apply to finish and retrieve the Tunnel token.`,\n ].join('\\n'),\n 'Plan',\n );\n\n if (opts.yes) return;\n const go = unwrap(await p.confirm({ message: 'Proceed?', initialValue: true }));\n if (!go) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n}\n\n// ---- Execute: create repo (idempotent on HTTP 422 already-exists) ----\nasync function createRegionRepo(args: {\n opts: InitOptions;\n ghToken: string;\n owner: string;\n newRepoName: string;\n newRepoFull: string;\n region: string;\n}): Promise<{ fullName: string; defaultBranch: string }> {\n const { opts, ghToken, owner, newRepoName, newRepoFull, region } = args;\n const repoSpin = p.spinner();\n repoSpin.start(`Creating ${newRepoFull} from ${opts.template}…`);\n try {\n const created = await createRepoFromTemplate({\n token: ghToken,\n template: opts.template ?? 'OpusPopuli/opuspopuli-node',\n owner,\n name: newRepoName,\n description: `Opus Populi node deployment for ${region}`,\n });\n repoSpin.stop(pc.green(`✓ Created ${created.fullName}`));\n return { fullName: created.fullName, defaultBranch: created.defaultBranch };\n } catch (err) {\n // The most likely re-run failure mode: the repo already exists from a\n // previous partial run. The GitHub API responds with HTTP 422 for that\n // case — status code is the API contract, message text isn't. Don't\n // regex on the message; it can change.\n const status =\n typeof err === 'object' && err !== null && 'status' in err\n ? (err as { status: number }).status\n : 0;\n const message = (err as Error).message ?? 'unknown error';\n\n if (status !== 422) {\n repoSpin.stop(pc.red(`✗ Couldn't create repo: ${message}`));\n p.cancel('Fix the issue and re-run.');\n process.exit(1);\n }\n\n repoSpin.stop(pc.yellow(`⚠ ${newRepoFull} already exists.`));\n const reuse =\n opts.useExistingRepo ||\n unwrap(\n await p.confirm({\n message: `Continue with the existing ${newRepoFull}? (Re-seeds secrets + re-commits prod.tfvars on a fresh branch.)`,\n initialValue: true,\n }),\n );\n if (!reuse) {\n p.cancel(\n `Delete ${newRepoFull} on GitHub and re-run, or pass --use-existing-repo to skip this prompt.`,\n );\n process.exit(0);\n }\n // Synthesize the same shape `createRepoFromTemplate` returns so the rest\n // of the flow doesn't care which path got us here.\n // Deferred (#41): query the actual default branch via gh API instead of\n // assuming `main` — a pre-existing repo could have been initialized with\n // a different default (older operator habit, organization defaults).\n return { fullName: newRepoFull, defaultBranch: 'main' };\n }\n}\n\n// ---- Execute: seed 5 repo secrets (production mode only) ----\nasync function seedRepoSecrets(args: {\n publicConfig: PublicConfig;\n newRepoFull: string;\n}): Promise<void> {\n const { publicConfig, newRepoFull } = args;\n const secrets: Array<{ name: string; value: string }> = [\n { name: 'CLOUDFLARE_API_TOKEN', value: publicConfig.cfToken },\n { name: 'CLOUDFLARE_ACCOUNT_ID', value: publicConfig.cfAccount },\n { name: 'CLOUDFLARE_ZONE_ID', value: publicConfig.cfZone },\n { name: 'TF_API_TOKEN', value: publicConfig.tfToken },\n { name: 'TF_CLOUD_ORGANIZATION', value: publicConfig.tfOrg },\n ];\n const secSpin = p.spinner();\n secSpin.start(`Seeding ${secrets.length} repo secrets…`);\n const seeded: string[] = [];\n for (const s of secrets) {\n const r = await setRepoSecret({ repo: newRepoFull, name: s.name, value: s.value });\n if (!r.written) {\n secSpin.stop(pc.red(`✗ Failed to set ${s.name}: ${r.reason ?? 'unknown'}`));\n const remaining = secrets\n .slice(secrets.findIndex((x) => x.name === s.name))\n .map((x) => x.name);\n p.cancel(\n [\n seeded.length > 0\n ? `Already seeded on ${newRepoFull}: ${seeded.join(', ')}.`\n : `Nothing seeded yet on ${newRepoFull}.`,\n `Still pending: ${remaining.join(', ')}.`,\n '',\n `Make sure \\`gh\\` is installed and signed in (\\`gh auth login\\`).`,\n `Re-run with --use-existing-repo to retry (GitHub will overwrite the already-set secrets idempotently).`,\n ].join('\\n'),\n );\n process.exit(1);\n }\n seeded.push(s.name);\n }\n secSpin.stop(pc.green(`✓ Seeded ${secrets.length} secrets on ${newRepoFull}`));\n}\n\n// ---- Execute: branch + tfvars + PR (production mode only) ----\n// Branch name is timestamped (ISO compact, UTC) so re-runs don't collide\n// with a leftover branch from a previous partial run.\nasync function openInfraPr(args: {\n opts: InitOptions;\n ghToken: string;\n region: string;\n newRepoFull: string;\n publicConfig: PublicConfig;\n created: { defaultBranch: string };\n}): Promise<Awaited<ReturnType<typeof openPullRequest>>> {\n const { opts, ghToken, region, newRepoFull, publicConfig, created } = args;\n const branch = `init/region-${region}-${isoStampUtc(new Date())}`;\n const setupSpin = p.spinner();\n setupSpin.start(`Writing prod.tfvars on branch ${branch}…`);\n try {\n await createBranch({\n token: ghToken,\n repo: newRepoFull,\n branch,\n fromBranch: created.defaultBranch,\n });\n const tfvars = renderProdTfvars({\n project: opts.project ?? 'opuspopuli',\n domain: publicConfig.domain,\n });\n await commitFile({\n token: ghToken,\n repo: newRepoFull,\n branch,\n path: 'infra/cloudflare/environments/prod.tfvars',\n content: tfvars,\n message: `init: prod.tfvars for ${region}`,\n });\n } catch (err) {\n setupSpin.stop(pc.red(`✗ Couldn't write tfvars: ${(err as Error).message}`));\n p.cancel('The repo exists but the branch / commit failed. Open it on GitHub and inspect.');\n process.exit(1);\n }\n setupSpin.stop(pc.green('✓ Wrote prod.tfvars'));\n\n const prSpin = p.spinner();\n prSpin.start('Opening pull request…');\n try {\n const pr = await openPullRequest({\n token: ghToken,\n repo: newRepoFull,\n head: branch,\n base: created.defaultBranch,\n title: `init: bring up region ${region}`,\n body: [\n `Initial region deployment for **${region}** (${publicConfig.domain}).`,\n '',\n 'Adds `infra/cloudflare/environments/prod.tfvars`. Merging this PR triggers',\n '`cloudflare-infra.yml` which runs `terraform apply` against the',\n `\\`${publicConfig.tfOrg}\\` Terraform Cloud organization, provisioning the Cloudflare`,\n 'Tunnel, DNS records, R2 buckets, and Pages project.',\n '',\n `Generated by \\`create-op-node init\\`.`,\n ].join('\\n'),\n });\n prSpin.stop(pc.green(`✓ Opened PR #${pr.number}`));\n return pr;\n } catch (err) {\n prSpin.stop(pc.red(`✗ Couldn't open PR: ${(err as Error).message}`));\n p.cancel('Branch + tfvars are committed; open the PR by hand on GitHub.');\n process.exit(1);\n }\n}\n\n// ---- pgsodium master key (read existing OR generate fresh) ----\n//\n// Three branches: Keychain hit + key present + no --overwrite → surface the\n// existing key; Keychain hit + missing/--overwrite → generate + save; no\n// Keychain → generate + print for manual stash.\nasync function persistPgsodiumKey(args: {\n keychain: Awaited<ReturnType<typeof detectKeychain>>;\n opts: InitOptions;\n region: string;\n}): Promise<void> {\n const { keychain, opts, region } = args;\n const pgsodiumCoords = { region, account: 'pgsodium-root-key' as const };\n const keyLabel = `org.opuspopuli.${region}/pgsodium-root-key`;\n\n if (!keychain.available) {\n const fresh = generatePgsodiumRootKey();\n await printKeyForManualSave(fresh, keyLabel);\n return;\n }\n\n const existing = opts.overwrite ? null : await readSecret(pgsodiumCoords);\n if (existing && /^[a-f0-9]{64}$/.test(existing)) {\n p.note(\n `${pc.green('✓')} Re-using existing pgsodium master key from Keychain (${pc.cyan(keyLabel)}). Pass --overwrite to rotate.`,\n 'Secret',\n );\n return;\n }\n\n const fresh = generatePgsodiumRootKey();\n const r = await saveSecret(pgsodiumCoords, fresh);\n if (r.written) {\n p.note(\n `${pc.green('✓')} pgsodium master key${r.updated ? ' rotated' : ' saved'} to Keychain as ${pc.cyan(keyLabel)}.`,\n 'Secret',\n );\n } else {\n await printKeyForManualSave(fresh, keyLabel, r.reason);\n }\n}\n\nfunction printLocalOnlyOutro(args: { region: string; newRepoFull: string }): void {\n const { region, newRepoFull } = args;\n p.outro(\n pc.cyan(\n [\n `Region ${region} provisioned for local-only mode.`,\n `Repo: https://github.com/${newRepoFull}`,\n ``,\n `Next: on the Studio (fresh or otherwise — bootstrap installs`,\n `brew packages it needs), run:`,\n ` npx create-op-node bootstrap --region ${region} --local-only`,\n ``,\n `When you're ready to expose publicly, re-run BOTH \\`init\\` and`,\n `\\`bootstrap\\` without --local-only. Same region repo + pgsodium key`,\n `promote cleanly to the production-shaped deploy.`,\n ].join('\\n'),\n ),\n );\n}\n\n// Pause for the operator to merge the infra PR. Returns false when the flow\n// should stop here (--skip-wait, or the operator hasn't merged yet).\nasync function pauseForMerge(args: {\n pr: { htmlUrl: string };\n opts: InitOptions;\n}): Promise<boolean> {\n const { pr, opts } = args;\n if (opts.skipWait) {\n p.outro(\n pc.cyan(\n `Review + merge ${pr.htmlUrl} when ready. Re-run with no --skip-wait or run \\`npx create-op-node verify\\` afterwards.`,\n ),\n );\n return false;\n }\n\n p.note(\n [\n `Open the PR: ${pc.cyan(pr.htmlUrl)}`,\n '',\n 'Review the `terraform plan` comment, then merge to main.',\n 'The workflow then runs `terraform apply` against Terraform Cloud.',\n ].join('\\n'),\n 'Next step: review + merge',\n );\n const merged = unwrap(await p.confirm({ message: 'PR merged?', initialValue: false }));\n if (!merged) {\n p.outro(\n pc.cyan(`No worries — re-run \\`create-op-node init --skip-wait\\` later to skip this step, or finish manually.`),\n );\n return false;\n }\n return true;\n}\n\n// ---- Poll TFC for apply completion + fetch the tunnel token ----\nasync function fetchTunnelToken(args: { publicConfig: PublicConfig }): Promise<string> {\n const { publicConfig } = args;\n const ws = await findWorkspace({\n token: publicConfig.tfToken,\n organization: publicConfig.tfOrg,\n tags: ['opuspopuli', 'cloudflare'],\n });\n if (!ws) {\n p.cancel(\n `Couldn't find a TFC workspace tagged opuspopuli + cloudflare in ${publicConfig.tfOrg}. ` +\n `Check the workflow's run log; the workspace is created on first apply.`,\n );\n process.exit(1);\n }\n\n const tunnelToken = await waitForApplyAndFetchTunnelToken({\n token: publicConfig.tfToken,\n organization: publicConfig.tfOrg,\n workspaceId: ws.id,\n runId: ws.currentRunId,\n });\n if (!tunnelToken) {\n p.cancel(\n `Terraform apply didn't produce a tunnel_token output. Check the run on TFC; if it succeeded, the output may be named differently — patch and re-run, or fetch via 'terraform output -raw tunnel_token'.`,\n );\n process.exit(1);\n }\n return tunnelToken;\n}\n\nasync function persistTunnelToken(args: {\n keychain: Awaited<ReturnType<typeof detectKeychain>>;\n region: string;\n tunnelToken: string;\n}): Promise<void> {\n const { keychain, region, tunnelToken } = args;\n const tunnelCoords = { region, account: 'tunnel-token' as const };\n const tunnelLabel = `org.opuspopuli.${region}/tunnel-token`;\n if (!keychain.available) {\n await printKeyForManualSave(tunnelToken, tunnelLabel);\n return;\n }\n const r = await saveSecret(tunnelCoords, tunnelToken);\n if (r.written) {\n p.note(\n `${pc.green('✓')} Tunnel token saved to Keychain as ${pc.cyan(tunnelLabel)}.`,\n 'Secret',\n );\n } else {\n await printKeyForManualSave(tunnelToken, tunnelLabel, r.reason);\n }\n}\n\nfunction printDoneOutro(region: string): void {\n p.outro(\n pc.cyan(\n `Region ${region} is provisioned. Next: \\`npx create-op-node bootstrap\\` on the Mac Studio.`,\n ),\n );\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n/** Source-specific minimums — every real-world token from these issuers is\n * longer than the floor, so a short input is a typo or paste error. */\nconst MIN_TOKEN_LENGTH: Record<SecretKind, number> = {\n cloudflare: 40,\n tfc: 40,\n github: 40,\n generic: 20,\n};\n\ntype SecretKind = 'cloudflare' | 'tfc' | 'github' | 'generic';\n\n/** Pure description of which init phases will run given the operator's\n * flags. Useful for testing the flag-routing logic without touching the\n * action handler (which shells out to GH / Cloudflare / TFC). The action\n * uses the same `opts.localOnly` directly; this is a docs + test seam. */\nexport function summarizePhases(opts: Pick<InitOptions, 'localOnly'>): {\n cloudflareProbe: boolean;\n tfcProbe: boolean;\n seedSecrets: boolean;\n branchAndPR: boolean;\n tunnelTokenWait: boolean;\n} {\n const production = !opts.localOnly;\n return {\n cloudflareProbe: production,\n tfcProbe: production,\n seedSecrets: production,\n branchAndPR: production,\n tunnelTokenWait: production,\n };\n}\n\n/** Which production-only flags the operator passed but which won't be used\n * in `--local-only` mode. Surfaced as a warning so the operator knows their\n * --cf-token / --domain / etc. weren't silently swallowed. (review S2/S3) */\nexport function listIgnoredLocalOnlyFlags(opts: InitOptions): string[] {\n const ignored: string[] = [];\n if (opts.domain) ignored.push('--domain');\n if (opts.cfToken) ignored.push('--cf-token');\n if (opts.cfAccount) ignored.push('--cf-account');\n if (opts.cfZone) ignored.push('--cf-zone');\n if (opts.tfToken) ignored.push('--tf-token');\n if (opts.tfOrg) ignored.push('--tf-org');\n if (opts.skipWait) ignored.push('--skip-wait');\n return ignored;\n}\n\n/** All the inputs init needs when running the full production flow.\n * Returned by `collectPublicConfig` (whose presence is gated on\n * `!opts.localOnly`). Carrying this around as a tagged shape lets the\n * downstream code use the fields without non-null assertions. */\nexport interface PublicConfig {\n domain: string;\n cfToken: string;\n cfAccount: string;\n cfZone: string;\n tfToken: string;\n tfOrg: string;\n}\n\n/** Prompt for + verify Cloudflare and Terraform Cloud creds. Exits the\n * process on any verification failure. Only called in production mode;\n * in --local-only mode the caller passes `null` straight through. */\nasync function collectPublicConfig(opts: InitOptions): Promise<PublicConfig> {\n const domain = opts.domain\n ? opts.domain\n : unwrap(\n await p.text({\n message: 'Domain registered in Cloudflare?',\n placeholder: 'example.org',\n validate: (v) => {\n if (!v) return 'Required';\n return v.includes('.') ? undefined : 'Missing a TLD?';\n },\n }),\n );\n\n // ---- Cloudflare token --------------------------------------------------\n const cfToken = await collectSecret(\n opts.cfToken,\n 'Cloudflare Account API token (input hidden)',\n 'cloudflare',\n );\n const cfAccount = await collectId(opts.cfAccount, 'Cloudflare account ID');\n const cfZone = await collectId(opts.cfZone, `Cloudflare zone ID for ${domain}`);\n\n const cfSpin = p.spinner();\n cfSpin.start('Verifying Cloudflare token + 5 scopes…');\n const cfProbe = await probeCloudflareToken({\n token: cfToken,\n accountId: cfAccount,\n zoneId: cfZone,\n });\n if (!cfProbe.ok) {\n cfSpin.stop(pc.red('✗ Cloudflare token check failed.'));\n for (const issue of cfProbe.issues) console.error(` - ${issue}`);\n p.cancel('Fix the token in the Cloudflare dashboard, then re-run.');\n process.exit(1);\n }\n cfSpin.stop(pc.green('✓ Cloudflare token valid, 5 scopes present.'));\n\n // ---- Terraform Cloud token ---------------------------------------------\n const tfToken = await collectSecret(\n opts.tfToken,\n 'Terraform Cloud user/team API token',\n 'tfc',\n );\n const tfOrg = opts.tfOrg\n ? opts.tfOrg\n : unwrap(\n await p.text({\n message: 'Terraform Cloud organization name?',\n placeholder: 'op-region-ca',\n }),\n );\n\n const tfSpin = p.spinner();\n tfSpin.start('Verifying Terraform Cloud token + organization…');\n const tfProbe = await probeTfcToken({ token: tfToken, organization: tfOrg });\n if (!tfProbe.ok) {\n tfSpin.stop(pc.red('✗ Terraform Cloud check failed.'));\n for (const issue of tfProbe.issues) console.error(` - ${issue}`);\n p.cancel('Fix the token / org, then re-run.');\n process.exit(1);\n }\n const asUser = tfProbe.userName ? ` (as ${tfProbe.userName})` : '';\n tfSpin.stop(\n pc.green(\n `✓ TFC token valid${asUser}, org \"${tfOrg}\" reachable.`,\n ),\n );\n\n return { domain, cfToken, cfAccount, cfZone, tfToken, tfOrg };\n}\n\nasync function collectSecret(\n preset: string | undefined,\n message: string,\n kind: SecretKind = 'generic',\n): Promise<string> {\n if (preset) return preset;\n const min = MIN_TOKEN_LENGTH[kind];\n const v = unwrap(\n await p.password({\n message,\n validate: (v) =>\n v && v.length >= min\n ? undefined\n : `That looks too short — expected at least ${min} characters for a ${kind} token`,\n }),\n );\n return v;\n}\n\nasync function collectId(preset: string | undefined, message: string): Promise<string> {\n if (preset) return preset;\n const v = unwrap(\n await p.text({\n message,\n placeholder: '0000000000000000000000000000000',\n validate: (v) =>\n /^[a-f0-9]{32}$/.test(v ?? '') ? undefined : 'Expected 32 hex characters',\n }),\n );\n return v;\n}\n\nasync function printKeyForManualSave(\n value: string,\n label: string,\n reason?: string,\n): Promise<void> {\n p.note(\n [\n reason ? `${pc.red('✗')} ${reason}` : '',\n `Save this value to your secret store as ${pc.cyan(label)}:`,\n '',\n pc.yellow(value),\n '',\n pc.dim('It will not be shown again.'),\n pc.dim('On the Studio, bootstrap will prompt you to paste it back.'),\n ]\n .filter((line) => line.length > 0)\n .join('\\n'),\n 'Manual save',\n );\n unwrap(\n await p.confirm({\n message: 'Value stashed?',\n initialValue: true,\n }),\n );\n}\n\n/** Compact ISO timestamp suitable for a git branch name: 20260618-184530Z.\n * UTC so re-runs across timezones sort coherently. */\nfunction isoStampUtc(d: Date): string {\n const pad = (n: number, w = 2) => n.toString().padStart(w, '0');\n return (\n `${d.getUTCFullYear()}` +\n `${pad(d.getUTCMonth() + 1)}` +\n `${pad(d.getUTCDate())}` +\n `-` +\n `${pad(d.getUTCHours())}` +\n `${pad(d.getUTCMinutes())}` +\n `${pad(d.getUTCSeconds())}Z`\n );\n}\n\ninterface WaitInput {\n token: string;\n organization: string;\n workspaceId: string;\n runId: string | null;\n}\n\n/** Thin command-side adapter for the polling lib — renders Clack spinner\n * state from the lib's progress callback + maps the discriminated outcome\n * to a single nullable result the command keeps using. */\nasync function waitForApplyAndFetchTunnelToken(input: WaitInput): Promise<string | null> {\n const spin = p.spinner();\n spin.start('Waiting for terraform apply to finish (polling every 10s)…');\n\n const outcome = await waitForApply(\n {\n token: input.token,\n organization: input.organization,\n workspaceId: input.workspaceId,\n runId: input.runId,\n workspaceTags: ['opuspopuli', 'cloudflare'],\n outputName: 'tunnel_token',\n },\n undefined,\n {\n ...realWaitDeps,\n // Surface a transient network hiccup instead of silently re-polling, so\n // a slow wait doesn't look like a hang.\n onProgress: (phase) => {\n if (phase === 'retry') spin.message('Transient network error — retrying next poll…');\n },\n },\n );\n\n switch (outcome.kind) {\n case 'success':\n spin.stop(pc.green('✓ Tunnel token retrieved.'));\n return outcome.value;\n case 'output-missing':\n spin.stop(pc.red('✗ Apply succeeded but tunnel_token output is missing.'));\n return null;\n case 'no-run-started':\n spin.stop(pc.red('✗ No run started in the workspace yet.'));\n return null;\n case 'run-failed':\n spin.stop(pc.red(`✗ Run finished with status \"${outcome.status}\".`));\n return null;\n case 'timeout':\n spin.stop(pc.red('✗ Timed out after 10 minutes.'));\n return null;\n }\n}\n","/**\n * Detect Homebrew + install packages (formulae or casks) idempotently.\n *\n * Bootstrap shells out to brew once per package — `brew install` is itself\n * idempotent (no-op when already installed) but we list-check first so the\n * wizard can print \"already present\" vs \"installing…\" and skip the\n * potentially-multi-minute download for packages that are already on the\n * Studio.\n *\n * We don't try to AUTO-install Homebrew itself. The official installer is a\n * curl-pipe-bash script that prompts for sudo + has its own UX; the wizard\n * detects its absence, prints the single-line install command, and waits for\n * the operator to confirm before proceeding.\n */\n\nimport { safeExeca } from './exec.js';\n\nexport type PackageKind = 'formula' | 'cask';\n\nexport interface PackageSpec {\n name: string;\n kind: PackageKind;\n}\n\n/** The package set the runbook installs on the Studio. Casks need GUI\n * authorization on first launch — Docker Desktop in particular requires\n * manual click-through after `brew install --cask docker`. The wizard\n * surfaces that as a follow-up prompt; this list is just what we'd shell\n * out for.\n *\n * Deep-readonly via `as const` — neither the array nor the individual\n * PackageSpec entries can be mutated by accident. */\nexport const STUDIO_PACKAGES = [\n { name: 'git', kind: 'formula' },\n { name: 'gh', kind: 'formula' },\n { name: 'pnpm', kind: 'formula' },\n { name: 'jq', kind: 'formula' },\n { name: 'cloudflared', kind: 'formula' },\n { name: 'rclone', kind: 'formula' },\n { name: 'ollama', kind: 'formula' },\n { name: 'docker', kind: 'cask' },\n { name: 'tailscale', kind: 'cask' },\n] as const satisfies readonly PackageSpec[];\n\nexport interface BrewInfo {\n installed: boolean;\n /** Version string when installed (`Homebrew 4.x.y`). Undefined otherwise. */\n version?: string;\n}\n\nexport async function detectBrew(): Promise<BrewInfo> {\n const res = await safeExeca('brew', ['--version']);\n if (res === null || res.exitCode !== 0) {\n return { installed: false };\n }\n // `brew --version` prints e.g. \"Homebrew 4.4.10\".\n const version = res.stdout.split('\\n').find((l) => l.startsWith('Homebrew '));\n return { installed: true, ...(version ? { version } : {}) };\n}\n\n/** The one-shot install command operators paste into their shell when brew is\n * missing. Surfaced verbatim so the wizard can show + the docs can quote\n * the same string. */\nexport const HOMEBREW_INSTALL_COMMAND =\n '/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"';\n\n/**\n * Is the named package already installed? `brew list <name>` exits 0 when\n * yes, non-zero when no. Cask vs formula lookup uses different flags.\n */\nexport async function isPackageInstalled(pkg: PackageSpec): Promise<boolean> {\n const flag = pkg.kind === 'cask' ? '--cask' : '--formula';\n const res = await safeExeca('brew', ['list', flag, pkg.name]);\n return res !== null && res.exitCode === 0;\n}\n\nexport interface InstallResult {\n ok: boolean;\n /** Set when ok=false. Stderr or stdout from the failing command. */\n reason?: string;\n}\n\n/** Install one package. Caller should `isPackageInstalled` first to skip\n * re-installs when speed matters; brew install is itself idempotent. */\nexport async function installPackage(pkg: PackageSpec): Promise<InstallResult> {\n const args =\n pkg.kind === 'cask'\n ? ['install', '--cask', pkg.name]\n : ['install', pkg.name];\n const res = await safeExeca('brew', args);\n if (res === null) {\n return { ok: false, reason: '`brew` not on PATH' };\n }\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `brew install ${pkg.name} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport interface InstallReport {\n installed: PackageSpec[];\n alreadyPresent: PackageSpec[];\n failed: Array<{ pkg: PackageSpec; reason: string }>;\n}\n\n/**\n * Install every package in the spec list. Each is independently logged into\n * one of three buckets so the wizard can show a clean summary. A failure in\n * one package doesn't abort the rest — we want the operator to see the\n * whole landscape and decide which to retry.\n */\nexport async function installPackages(\n packages: readonly PackageSpec[],\n onEach?: (pkg: PackageSpec, status: 'checking' | 'installing' | 'present' | 'installed' | 'failed') => void,\n): Promise<InstallReport> {\n const report: InstallReport = {\n installed: [],\n alreadyPresent: [],\n failed: [],\n };\n for (const pkg of packages) {\n onEach?.(pkg, 'checking');\n if (await isPackageInstalled(pkg)) {\n report.alreadyPresent.push(pkg);\n onEach?.(pkg, 'present');\n continue;\n }\n onEach?.(pkg, 'installing');\n const r = await installPackage(pkg);\n if (r.ok) {\n report.installed.push(pkg);\n onEach?.(pkg, 'installed');\n } else {\n report.failed.push({ pkg, reason: r.reason ?? 'unknown' });\n onEach?.(pkg, 'failed');\n }\n }\n return report;\n}\n","/**\n * Read + write the small set of macOS settings `create-op-node bootstrap`\n * cares about on the Mac Studio:\n *\n * - Hostname and OS version (informational + sanity check we're on Apple Silicon).\n * - Power management (`pmset`): auto-restart-on-power-failure, disk sleep.\n * - FileVault status (`fdesetup`) — informational only; we don't toggle it,\n * since the operator's earlier decision (gate 0.7 in the runbook) was OFF.\n *\n * All probes shell out via `safeExeca` from `lib/exec.ts` so a missing binary\n * (extremely unusual on macOS, but it's the principle) doesn't crash the\n * wizard. Writers use `pmset -a` which requires sudo on macOS — execa\n * propagates the operator's stdin so the password prompt works inline.\n */\n\nimport { safeExeca } from './exec.js';\n\nexport interface SystemSnapshot {\n hostname: string;\n /** `sw_vers -productVersion` output, or `null` when the call failed. */\n osVersion: string | null;\n /** True when `pmset -g` reports `autorestart 1`. */\n autoRestartOnPowerFailure: boolean;\n /** True when `pmset -g` reports `disksleep 0` (i.e. disk sleep DISABLED — the\n * state the bootstrap wants). */\n diskSleepDisabled: boolean;\n /** `true` / `false` when `fdesetup status` reported decisively, `'unknown'`\n * when the call failed or the output was unexpected. We don't toggle\n * FileVault — this is for the operator-facing summary only. */\n fileVaultEnabled: boolean | 'unknown';\n /** True when `uname -m` returns `arm64` (i.e. Apple Silicon Mac).\n * Bootstrap is M-series-only; Intel Macs fail with a clear message. */\n isAppleSilicon: boolean;\n}\n\nexport async function inspectSystem(): Promise<SystemSnapshot> {\n const [hostnameOut, osVersionOut, pmsetOut, fdesetupOut, unameOut] =\n await Promise.all([\n safeExeca('hostname', []),\n safeExeca('sw_vers', ['-productVersion']),\n safeExeca('pmset', ['-g']),\n safeExeca('fdesetup', ['status']),\n safeExeca('uname', ['-m']),\n ]);\n\n return {\n hostname: hostnameOut?.stdout.trim() ?? 'unknown',\n osVersion:\n osVersionOut && osVersionOut.exitCode === 0\n ? osVersionOut.stdout.trim()\n : null,\n autoRestartOnPowerFailure: parsePmsetBool(pmsetOut?.stdout ?? '', 'autorestart', 1),\n diskSleepDisabled: parsePmsetBool(pmsetOut?.stdout ?? '', 'disksleep', 0),\n fileVaultEnabled: parseFileVault(fdesetupOut?.stdout ?? ''),\n isAppleSilicon: (unameOut?.stdout.trim() ?? '') === 'arm64',\n };\n}\n\n/**\n * `pmset -g` prints one space-separated `key value` per line, e.g.:\n *\n * ```\n * System-wide power settings:\n * Currently in use:\n * lidwake 1\n * autorestart 1\n * disksleep 0\n * ```\n *\n * Returns `true` when the named key's value matches `expected`. Tolerant of\n * leading/trailing whitespace; matches first occurrence.\n */\nexport function parsePmsetBool(\n output: string,\n key: string,\n expected: number,\n): boolean {\n for (const line of output.split('\\n')) {\n const match = line.match(/^\\s*([a-z]+)\\s+(-?\\d+)\\s*$/);\n if (match && match[1] === key) {\n return Number(match[2]) === expected;\n }\n }\n return false;\n}\n\n/**\n * `fdesetup status` prints either:\n * - `FileVault is On.`\n * - `FileVault is Off.`\n * - `Encryption in progress: ...` (treat as On)\n * - anything else → `'unknown'`\n */\nexport function parseFileVault(output: string): boolean | 'unknown' {\n const trimmed = output.trim();\n if (/^FileVault is On\\.?/i.test(trimmed)) return true;\n if (/^FileVault is Off\\.?/i.test(trimmed)) return false;\n if (/encryption in progress/i.test(trimmed)) return true;\n return 'unknown';\n}\n\nexport interface SetResult {\n ok: boolean;\n /** Set when `ok=false`. Stderr or stdout from the failing command. */\n reason?: string;\n}\n\n/**\n * Enable auto-restart-on-power-failure (`pmset -a autorestart 1`). Requires\n * sudo; the operator's password prompt is inherited from the parent shell.\n */\nexport async function enableAutoRestartOnPowerFailure(): Promise<SetResult> {\n return runSudoPmset(['autorestart', '1']);\n}\n\n/** Disable disk sleep (`pmset -a disksleep 0`). Same sudo behavior. */\nexport async function disableDiskSleep(): Promise<SetResult> {\n return runSudoPmset(['disksleep', '0']);\n}\n\n/**\n * Read the Studio's unified memory in GB via `sysctl hw.memsize`. Returns\n * `null` when sysctl is unavailable or the output is unparseable — callers\n * fall back to platform defaults in that case.\n *\n * `hw.memsize` reports bytes (e.g. `137438953472` for 128 GB). We divide\n * by 2^30 and round; vendors mostly ship integer GB so the rounding is\n * cosmetic, but the user may see `127` instead of `128` on rare configs.\n */\nexport async function detectUnifiedMemoryGB(): Promise<number | null> {\n const res = await safeExeca('sysctl', ['-n', 'hw.memsize']);\n if (res === null || res.exitCode !== 0) return null;\n const bytes = Number.parseInt(res.stdout.trim(), 10);\n if (!Number.isFinite(bytes) || bytes <= 0) return null;\n return Math.round(bytes / 2 ** 30);\n}\n\nasync function runSudoPmset(args: string[]): Promise<SetResult> {\n const res = await safeExeca('sudo', ['pmset', '-a', ...args]);\n if (res === null) {\n return { ok: false, reason: '`sudo` not on PATH' };\n }\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `pmset ${args.join(' ')} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n","/**\n * macOS LaunchAgent for the env-loader that the bootstrap puts in place.\n *\n * The plist's whole job is to inject two env vars into the launchd session at\n * login so Docker Desktop + the container stack see them:\n *\n * PGSODIUM_ROOT_KEY — 64-hex pgsodium master key, read from a `0400` file\n * outside the container so a `docker compose --build`\n * can never wipe it (runbook gate / #791).\n * TUNNEL_TOKEN — Cloudflare Tunnel token, baked into the plist literal.\n *\n * The pgsodium key is materialized as a separate `0400` file (not embedded in\n * the plist) so it can be backed up out-of-band + rotated independently. The\n * Tunnel token gets baked into the plist directly — it's a different rotation\n * cadence (rotates with the Tunnel resource, not on pgsodium key churn).\n *\n * File modes match the runbook:\n * - pgsodium key file: 0400 (owner-read-only)\n * - plist file: 0600 (owner read+write; contains TUNNEL_TOKEN)\n */\n\nimport { mkdir, writeFile, chmod, rm } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { homedir } from 'node:os';\n\nimport {\n PGSODIUM_KEY_RE,\n SAFE_LAUNCHCTL_VALUE_RE,\n SAFE_PATH_RE,\n SAFE_URL_RE,\n TUNNEL_TOKEN_RE,\n} from './constants.js';\nimport { safeExeca } from './exec.js';\n\nexport const LAUNCH_AGENT_LABEL = 'org.opuspopuli.envloader';\n\nexport interface LaunchAgentPaths {\n /** Absolute path to the 64-hex pgsodium master key file (mode 0400). */\n keyFile: string;\n /** Absolute path to the LaunchAgent plist (mode 0600). */\n plistFile: string;\n}\n\n/** Default on-disk locations the runbook documents. Operators can override. */\nexport function defaultPaths(home: string = homedir()): LaunchAgentPaths {\n return {\n keyFile: `${home}/.config/opuspopuli/pgsodium_root_key`,\n plistFile: `${home}/Library/LaunchAgents/${LAUNCH_AGENT_LABEL}.plist`,\n };\n}\n\nexport interface WriteResult {\n ok: boolean;\n /** Set when ok=false. */\n reason?: string;\n}\n\n/**\n * Write the 64-hex pgsodium master key to `keyFile` with mode 0400. Creates\n * the parent directory tree (mode 0700 on the immediate parent) and refuses\n * non-64-hex input.\n */\nexport async function writePgsodiumKeyFile(\n key: string,\n keyFile: string,\n): Promise<WriteResult> {\n if (!PGSODIUM_KEY_RE.test(key)) {\n return {\n ok: false,\n reason: `pgsodium key must be 64 lowercase hex characters (got ${key.length} chars)`,\n };\n }\n try {\n const dir = dirname(keyFile);\n await mkdir(dir, { recursive: true, mode: 0o700 });\n await writeFile(keyFile, key, { mode: 0o400 });\n // mkdir's mode option respects umask; chmod is the belt to the suspenders.\n await chmod(dir, 0o700);\n await chmod(keyFile, 0o400);\n return { ok: true };\n } catch (err) {\n return { ok: false, reason: `writing ${keyFile} failed: ${(err as Error).message}` };\n }\n}\n\n/** Model-identifier safe set. Requires at least one alphanumeric character\n * to start (rejects lone `:`, `.`, `///`, etc. — Ollama would reject those\n * too, but catching them here gives a clearer error). Then allows the\n * letters/digits + Ollama's separators (`.`, `:`, `_`, `-`, `/`) — matches\n * shapes like `qwen3.5:9b`, `library/llama3.3:70b-q4`, `mxbai-embed-large`.\n * Reject anything outside this because the value gets interpolated into a\n * `sh -c` body run by launchd — `;`, `$`, backticks, quotes would all give\n * shell injection. */\nconst MODEL_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;\n\nexport interface PlistInput {\n /** Path the plist will exec — sourced from defaultPaths() unless an operator\n * overrides on the command line. */\n keyFilePath: string;\n /** Literal Cloudflare Tunnel token; embedded in the plist. Omit for\n * `bootstrap --local-only` flows where no Tunnel is provisioned — the\n * rendered plist will only set PGSODIUM_ROOT_KEY. */\n tunnelToken?: string;\n /** Ollama model identifier (e.g. `qwen3.5:9b`, `llama3.3:70b`).\n * When set, plist exports `LLM_MODEL` into the launchd session so the\n * knowledge service reads it via env. */\n llmModel?: string;\n /** Ollama embedding model identifier. When set, plist exports\n * `EMBEDDINGS_MODEL` into the launchd session. Only meaningful when the\n * knowledge service runs with `EMBEDDINGS_PROVIDER=ollama`. */\n embeddingModel?: string;\n /** Self-hosted Supabase credentials. When provided, the plist exports each\n * value via `launchctl setenv` so docker-compose-prod.yml — and every\n * Supabase container the compose brings up — sees them. Omit individual\n * fields to skip emitting that var (e.g. for partial re-runs). */\n postgresPassword?: string;\n jwtSecret?: string;\n supabaseAnonKey?: string;\n supabaseServiceRoleKey?: string;\n dashboardPassword?: string;\n /** Public-facing Supabase URL — what browsers + microservices use to reach\n * Kong. Local dev: `http://localhost:8000`. Tunnel: `https://supabase.<domain>`. */\n supabaseUrl?: string;\n}\n\n/**\n * Render the LaunchAgent plist XML. Pure function — caller writes it.\n *\n * The plist runs a `/bin/sh -c` at load that calls `launchctl setenv` for\n * each var. `launchctl setenv` exports into the running launchd session,\n * not just the agent's own env, so anything Docker Desktop launches\n * downstream sees the same values.\n *\n * Required: `PGSODIUM_ROOT_KEY`. Optional: `TUNNEL_TOKEN`, `LLM_MODEL`,\n * `EMBEDDINGS_MODEL` — omitted from the setenv list when their inputs\n * are undefined.\n */\nexport function renderLaunchAgentPlist(input: PlistInput): string {\n validatePlistInput(input);\n const command = buildSetenvCommand(input);\n\n return [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">',\n '<plist version=\"1.0\">',\n '<dict>',\n ` <key>Label</key><string>${LAUNCH_AGENT_LABEL}</string>`,\n ' <key>ProgramArguments</key>',\n ' <array>',\n ' <string>/bin/sh</string>',\n ' <string>-c</string>',\n ` <string>${command}</string>`,\n ' </array>',\n ' <key>RunAtLoad</key><true/>',\n '</dict>',\n '</plist>',\n '',\n ].join('\\n');\n}\n\n// Reject any input that would break the XML or inject shell metacharacters\n// into the `sh -c` body launchd runs at every login. Throws on the first\n// offending field. Our own generators only emit safe alphabets, but\n// operators can pass --import-* overrides, so re-validate here.\nfunction validatePlistInput(input: PlistInput): void {\n if (input.tunnelToken !== undefined && !TUNNEL_TOKEN_RE.test(input.tunnelToken)) {\n throw new Error('Tunnel token contains characters outside the expected base64-url set');\n }\n if (input.llmModel !== undefined && !MODEL_NAME_RE.test(input.llmModel)) {\n throw new Error(\n `llmModel ${JSON.stringify(input.llmModel)} contains characters not allowed in a launchd setenv value`,\n );\n }\n if (input.embeddingModel !== undefined && !MODEL_NAME_RE.test(input.embeddingModel)) {\n throw new Error(\n `embeddingModel ${JSON.stringify(input.embeddingModel)} contains characters not allowed in a launchd setenv value`,\n );\n }\n if (!SAFE_PATH_RE.test(input.keyFilePath)) {\n // The keyFilePath gets interpolated into a `sh -c` command run by launchd\n // at every login — reject shell metacharacters even though defaultPaths()\n // never produces one (defense in depth against operator overrides).\n throw new Error(\n `keyFilePath ${JSON.stringify(input.keyFilePath)} contains characters not allowed in a launchd path interpolation`,\n );\n }\n const supabaseFields: Array<[keyof PlistInput, string | undefined]> = [\n ['postgresPassword', input.postgresPassword],\n ['jwtSecret', input.jwtSecret],\n ['supabaseAnonKey', input.supabaseAnonKey],\n ['supabaseServiceRoleKey', input.supabaseServiceRoleKey],\n ['dashboardPassword', input.dashboardPassword],\n ];\n for (const [name, value] of supabaseFields) {\n if (value !== undefined && !SAFE_LAUNCHCTL_VALUE_RE.test(value)) {\n throw new Error(`${String(name)} contains characters not allowed in a launchd setenv value`);\n }\n }\n if (input.supabaseUrl !== undefined && !SAFE_URL_RE.test(input.supabaseUrl)) {\n throw new Error(\n `supabaseUrl ${JSON.stringify(input.supabaseUrl)} contains characters not allowed in a launchd setenv value`,\n );\n }\n}\n\n// Assemble the `; `-joined `launchctl setenv` command. PGSODIUM_ROOT_KEY is\n// always set; every other var is emitted only when its value is present.\nfunction buildSetenvCommand(input: PlistInput): string {\n return [\n `launchctl setenv PGSODIUM_ROOT_KEY \"$(cat ${input.keyFilePath})\"`,\n ...(input.tunnelToken !== undefined\n ? [`launchctl setenv TUNNEL_TOKEN \"${input.tunnelToken}\"`]\n : []),\n ...(input.llmModel !== undefined ? [`launchctl setenv LLM_MODEL \"${input.llmModel}\"`] : []),\n ...(input.embeddingModel !== undefined\n ? [`launchctl setenv EMBEDDINGS_MODEL \"${input.embeddingModel}\"`]\n : []),\n ...(input.postgresPassword !== undefined\n ? [`launchctl setenv POSTGRES_PASSWORD \"${input.postgresPassword}\"`]\n : []),\n ...(input.jwtSecret !== undefined ? [`launchctl setenv JWT_SECRET \"${input.jwtSecret}\"`] : []),\n ...(input.supabaseAnonKey !== undefined\n ? [`launchctl setenv SUPABASE_ANON_KEY \"${input.supabaseAnonKey}\"`]\n : []),\n ...(input.supabaseServiceRoleKey !== undefined\n ? [`launchctl setenv SUPABASE_SERVICE_ROLE_KEY \"${input.supabaseServiceRoleKey}\"`]\n : []),\n ...(input.dashboardPassword !== undefined\n ? [`launchctl setenv DASHBOARD_PASSWORD \"${input.dashboardPassword}\"`]\n : []),\n ...(input.supabaseUrl !== undefined\n ? [`launchctl setenv SUPABASE_URL \"${input.supabaseUrl}\"`]\n : []),\n ].join('; ');\n}\n\n/** Write the plist file to disk at mode 0600. */\nexport async function writeLaunchAgentPlist(\n plistFile: string,\n content: string,\n): Promise<WriteResult> {\n try {\n await mkdir(dirname(plistFile), { recursive: true });\n await writeFile(plistFile, content, { mode: 0o600 });\n await chmod(plistFile, 0o600);\n return { ok: true };\n } catch (err) {\n return { ok: false, reason: `writing ${plistFile} failed: ${(err as Error).message}` };\n }\n}\n\n/**\n * Load (or reload) the agent via `launchctl load`. Unload first to handle\n * re-runs; ignore errors on unload since it could just not be loaded yet.\n */\nexport async function loadLaunchAgent(plistFile: string): Promise<WriteResult> {\n await safeExeca('launchctl', ['unload', plistFile]); // ignore errors\n const load = await safeExeca('launchctl', ['load', plistFile]);\n if (load === null) {\n return { ok: false, reason: '`launchctl` not on PATH' };\n }\n if (load.exitCode !== 0) {\n return {\n ok: false,\n reason: `launchctl load failed (${load.exitCode ?? 'signal'}): ${load.stderr || load.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport interface SetupInput {\n pgsodiumKey: string;\n /** Omit for `bootstrap --local-only` flows — the rendered plist will only\n * set `PGSODIUM_ROOT_KEY`. */\n tunnelToken?: string;\n /** Ollama LLM model name. When set, plist exports `LLM_MODEL`. */\n llmModel?: string;\n /** Ollama embedding model name. When set, plist exports `EMBEDDINGS_MODEL`. */\n embeddingModel?: string;\n /** Self-hosted Supabase credentials — generated by `bootstrap` and stored\n * in Keychain. Each value here gets exported into the launchd session\n * via the plist's `launchctl setenv` lines. */\n postgresPassword?: string;\n jwtSecret?: string;\n supabaseAnonKey?: string;\n supabaseServiceRoleKey?: string;\n dashboardPassword?: string;\n /** Public-facing Supabase URL. */\n supabaseUrl?: string;\n paths?: LaunchAgentPaths;\n}\n\nexport interface SetupReport {\n ok: boolean;\n paths: LaunchAgentPaths;\n step?: 'key-file' | 'plist' | 'load';\n reason?: string;\n}\n\n/**\n * One-shot: write the key file, render + write the plist, load the agent.\n * Returns a report that names which step failed (if any) for clean operator\n * messaging.\n */\n// Map the flat SetupInput onto a PlistInput, carrying only the fields that\n// are present (each optional secret is spread in only when defined).\nfunction plistInputFromSetup(input: SetupInput, keyFilePath: string): PlistInput {\n return {\n keyFilePath,\n ...(input.tunnelToken !== undefined ? { tunnelToken: input.tunnelToken } : {}),\n ...(input.llmModel !== undefined ? { llmModel: input.llmModel } : {}),\n ...(input.embeddingModel !== undefined ? { embeddingModel: input.embeddingModel } : {}),\n ...(input.postgresPassword !== undefined ? { postgresPassword: input.postgresPassword } : {}),\n ...(input.jwtSecret !== undefined ? { jwtSecret: input.jwtSecret } : {}),\n ...(input.supabaseAnonKey !== undefined ? { supabaseAnonKey: input.supabaseAnonKey } : {}),\n ...(input.supabaseServiceRoleKey !== undefined\n ? { supabaseServiceRoleKey: input.supabaseServiceRoleKey }\n : {}),\n ...(input.dashboardPassword !== undefined ? { dashboardPassword: input.dashboardPassword } : {}),\n ...(input.supabaseUrl !== undefined ? { supabaseUrl: input.supabaseUrl } : {}),\n };\n}\n\nexport async function setupLaunchAgent(input: SetupInput): Promise<SetupReport> {\n const paths = input.paths ?? defaultPaths();\n\n const keyResult = await writePgsodiumKeyFile(input.pgsodiumKey, paths.keyFile);\n if (!keyResult.ok) {\n return { ok: false, paths, step: 'key-file', ...(keyResult.reason ? { reason: keyResult.reason } : {}) };\n }\n\n let plistContent: string;\n try {\n plistContent = renderLaunchAgentPlist(plistInputFromSetup(input, paths.keyFile));\n } catch (err) {\n return { ok: false, paths, step: 'plist', reason: (err as Error).message };\n }\n\n const plistResult = await writeLaunchAgentPlist(paths.plistFile, plistContent);\n if (!plistResult.ok) {\n return { ok: false, paths, step: 'plist', ...(plistResult.reason ? { reason: plistResult.reason } : {}) };\n }\n\n const loadResult = await loadLaunchAgent(paths.plistFile);\n if (!loadResult.ok) {\n return { ok: false, paths, step: 'load', ...(loadResult.reason ? { reason: loadResult.reason } : {}) };\n }\n\n return { ok: true, paths };\n}\n\nexport interface TeardownResult {\n ok: boolean;\n /** Per-step outcome. Each step is independently logged so the operator can\n * see \"unload worked but the plist file was already gone.\" */\n steps: Array<{ step: 'unload' | 'rm-plist' | 'rm-key-file'; ok: boolean; reason?: string }>;\n}\n\nexport interface TeardownOptions {\n /** When true, leave the pgsodium key file in place. Useful when the\n * operator wants to unload the LaunchAgent + remove the plist but\n * keep the key as belt-and-suspenders backup. */\n keepKeyFile?: boolean;\n}\n\n/**\n * Reverse of `setupLaunchAgent`: unload the agent via `launchctl unload`,\n * then `rm -f` both the plist and (unless `keepKeyFile`) the pgsodium key\n * file. Idempotent — `rm -f` is a no-op when the file doesn't exist, and\n * we treat `launchctl unload` of an already-unloaded agent as success.\n *\n * Used by `reset`. Also useful as a test seam during integration tests.\n */\nexport async function teardownLaunchAgent(\n paths: LaunchAgentPaths,\n opts: TeardownOptions = {},\n): Promise<TeardownResult> {\n const steps: TeardownResult['steps'] = [];\n\n const unload = await safeExeca('launchctl', ['unload', paths.plistFile]);\n // `launchctl unload` exits non-zero when the agent isn't loaded — that's\n // a successful teardown from our point of view, so we don't propagate it.\n steps.push({\n step: 'unload',\n ok: true,\n ...(unload === null ? { reason: '`launchctl` not on PATH' } : {}),\n });\n\n try {\n await rm(paths.plistFile, { force: true });\n steps.push({ step: 'rm-plist', ok: true });\n } catch (err) {\n steps.push({ step: 'rm-plist', ok: false, reason: (err as Error).message });\n }\n\n if (!opts.keepKeyFile) {\n try {\n await rm(paths.keyFile, { force: true });\n steps.push({ step: 'rm-key-file', ok: true });\n } catch (err) {\n steps.push({ step: 'rm-key-file', ok: false, reason: (err as Error).message });\n }\n }\n\n return { ok: steps.every((s) => s.ok), steps };\n}\n","/**\n * Renders the `bin/op-compose` wrapper script that lives in the operator's\n * region-node repo.\n *\n * **Why a wrapper instead of a `.env` file:**\n * The project's vault-first principle (#811) says runtime secrets read via\n * `secretsProvider.getSecret()` at point of use; env-on-disk is reserved\n * for bootstrap-critical config. The bootstrap-layer secrets (Postgres\n * password, JWT secret, Supabase admin tokens) ARE bootstrap-critical\n * (Postgres / kong / gotrue can't start without them, and Vault doesn't\n * exist until Postgres is up) — but they don't need to LIVE on disk in\n * plaintext to be available at compose-invocation time.\n *\n * This wrapper reads them from macOS Keychain (FileVault-encrypted at\n * rest) on every invocation and exports them only into the docker compose\n * subprocess's env. No plaintext .env file ever lands on disk; the\n * Keychain is the sole persistent store.\n *\n * **Why launchctl setenv isn't sufficient:**\n * `launchctl setenv` only propagates to processes spawned by launchd\n * AFTER the setenv call. SSH-spawned shells (sshd children) and\n * already-running Terminal.app instances never see the new vars, so\n * `docker compose` hard-fails on `${VAR:?…}` even though `launchctl\n * getenv` confirms launchd has them. The wrapper is shell-agnostic and\n * works the same in every invocation context.\n *\n * **Operator workflow:**\n * $ ./bin/op-compose -f docker-compose-prod.yml up -d\n * $ ./bin/op-compose -f docker-compose-prod.yml pull\n * $ ./bin/op-compose -f docker-compose-prod.yml down\n *\n * The wrapper accepts every argument `docker compose` accepts.\n *\n * **Security:**\n * - Script is mode 0755 (executable, world-readable). The script ITSELF\n * has no secrets — it's a static shell script with the region name\n * baked in. The secrets only exist in process env for the lifetime\n * of the docker compose invocation.\n * - Region name is the only baked-in value (used to scope the Keychain\n * service identifier `org.opuspopuli.<region>`); shell-injection is\n * prevented by the region-validation regex in bootstrap.ts.\n * - Errors when a required Keychain entry is missing point the operator\n * at `create-op-node bootstrap`.\n */\n\nconst REGION_RE = /^[a-z0-9-]{2,32}$/;\n\n/** URL-shape regex for values baked into the wrapper as\n * `export PROMPT_SERVICE_URL=\"…\"`. Matches what bootstrap.ts validates\n * via SAFE_URL_RE — letters, digits, `:`, `/`, `_`, `-`, `.`. Reject\n * shell metacharacters that would inject when the wrapper sources. */\nconst PROMPT_SERVICE_URL_RE = /^[A-Za-z0-9:/_.-]+$/;\n\nexport interface OpComposeScriptInput {\n /** Region slug — gets interpolated into the Keychain service identifier\n * `org.opuspopuli.<region>`. Validated against the same regex bootstrap\n * uses, so a tampered call site can't inject shell metacharacters. */\n region: string;\n /** Default value the wrapper sets for `PROMPT_SERVICE_URL` when nothing\n * in the docker compose service-level env overrides it. For\n * `region-with-prompts` deployments this is the in-network address\n * `http://opuspopuli-prompts:3210` (and the overlay still wins via\n * service-level env). For `region` (remote prompts) it's whatever URL\n * the operator pointed at — typically https://prompts.opuspopuli.org.\n * Omit and the wrapper won't export PROMPT_SERVICE_URL at all. */\n promptServiceUrl?: string;\n}\n\n/**\n * Render the wrapper script. Pure function — caller writes it to disk and\n * `chmod 0755`s the result.\n *\n * Throws on an invalid region label rather than emit a script with a\n * shell-injectable service identifier.\n */\nexport function renderOpComposeScript(input: OpComposeScriptInput): string {\n if (!REGION_RE.test(input.region)) {\n throw new Error(\n `region ${JSON.stringify(input.region)} contains characters not allowed in a launchd / Keychain service identifier`,\n );\n }\n if (input.promptServiceUrl !== undefined && !PROMPT_SERVICE_URL_RE.test(input.promptServiceUrl)) {\n throw new Error(\n `promptServiceUrl ${JSON.stringify(input.promptServiceUrl)} contains characters not allowed in a wrapper export`,\n );\n }\n const promptServiceUrlExport =\n input.promptServiceUrl !== undefined\n ? `# Backend services call prompt-service via this URL. Service-level env\n# from docker-compose-prompt-service.yml overlay (when layered) wins\n# over this default — so colocated deployments still hit\n# http://opuspopuli-prompts:3210 even though we may have a public URL\n# baked in here.\nexport PROMPT_SERVICE_URL=\"\\${PROMPT_SERVICE_URL:-${input.promptServiceUrl}}\"\n\n`\n : '';\n\n return `#!/bin/bash\n# op-compose — wrapper that reads region secrets from macOS Keychain just\n# before invoking \\`docker compose\\`. Auto-generated by\n# \\`create-op-node bootstrap --region ${input.region}\\`. Do not edit by\n# hand; re-run bootstrap to regenerate.\n#\n# Why: launchctl setenv only propagates to launchd-spawned processes, so\n# SSH shells and pre-existing Terminal.app instances never see the env\n# vars bootstrap exports. This wrapper hydrates the docker compose\n# subprocess directly, so every invocation works regardless of how the\n# operator's shell was started.\n#\n# Usage:\n# ./bin/op-compose -f docker-compose-prod.yml up -d\n# ./bin/op-compose -f docker-compose-prod.yml pull\n# ./bin/op-compose -f docker-compose-prod.yml down\n\nset -euo pipefail\n\nSVC=\"org.opuspopuli.${input.region}\"\n\n# macOS \\`security\\` exit codes:\n# 0 = success\n# 36 = errSecInteractionNotAllowed (keychain is locked)\n# 44 = errSecItemNotFound (entry doesn't exist)\n# Earlier wrapper versions conflated 36 and 44 into a generic \"missing\"\n# message, which sent operators down the wrong path (re-bootstrap when\n# the real fix was \\`security unlock-keychain\\`).\nrequire_secret() {\n local account=\"$1\"\n local value\n local rc=0\n value=$(security find-generic-password -s \"$SVC\" -a \"$account\" -w 2>/dev/null) || rc=$?\n case \"$rc\" in\n 0)\n printf '%s' \"$value\"\n return 0\n ;;\n 36)\n cat >&2 <<EOM\nop-compose: keychain is LOCKED — could not read entry '$account'.\nSSH sessions don't auto-unlock the login keychain. Unlock with:\n security unlock-keychain ~/Library/Keychains/login.keychain-db\nThen re-run this command.\nEOM\n exit 1\n ;;\n 44)\n cat >&2 <<EOM\nop-compose: keychain entry '$account' is MISSING under service '$SVC'.\nRun: create-op-node bootstrap --region ${input.region}\nEOM\n exit 1\n ;;\n *)\n echo \"op-compose: \\`security\\` failed reading '$account' (exit $rc).\" >&2\n exit 1\n ;;\n esac\n}\n\n# Used for entries that may legitimately not exist (TUNNEL_TOKEN in\n# local-only mode, prompt-service secrets when colocation isn't active).\n# Treats exit 44 (missing) as a silent OK — returns empty string.\n# Treats exit 36 (locked) as a hard error, since the require_secret calls\n# at the top of the wrapper would have caught this first in normal use;\n# reaching this path means something else bypassed the lock check.\noptional_secret() {\n local account=\"$1\"\n local value\n local rc=0\n value=$(security find-generic-password -s \"$SVC\" -a \"$account\" -w 2>/dev/null) || rc=$?\n case \"$rc\" in\n 0) printf '%s' \"$value\" ;;\n 44) ;; # legitimately absent — empty string is correct\n 36)\n cat >&2 <<EOM\nop-compose: keychain is LOCKED — could not probe optional entry '$account'.\nUnlock with: security unlock-keychain ~/Library/Keychains/login.keychain-db\nEOM\n exit 1\n ;;\n *)\n echo \"op-compose: \\`security\\` failed reading '$account' (exit $rc).\" >&2\n exit 1\n ;;\n esac\n}\n\n# Bootstrap-critical: Postgres + Supabase admin credentials.\nexport PGSODIUM_ROOT_KEY=\"$(require_secret pgsodium-root-key)\"\nexport POSTGRES_PASSWORD=\"$(require_secret postgres-password)\"\nexport JWT_SECRET=\"$(require_secret jwt-secret)\"\nexport SUPABASE_ANON_KEY=\"$(require_secret supabase-anon-key)\"\nexport SUPABASE_SERVICE_ROLE_KEY=\"$(require_secret supabase-service-role-key)\"\nexport DASHBOARD_PASSWORD=\"$(require_secret dashboard-password)\"\n\n# AUTH_JWT_SECRET historically equals JWT_SECRET in dev/UAT — supply that\n# default if the operator hasn't set one independently.\nexport AUTH_JWT_SECRET=\"\\${AUTH_JWT_SECRET:-$JWT_SECRET}\"\n\n# Optional: Cloudflare Tunnel token (only present in non-local-only mode).\nTUNNEL_TOKEN_VAL=\"$(optional_secret tunnel-token)\"\nif [ -n \"$TUNNEL_TOKEN_VAL\" ]; then\n export TUNNEL_TOKEN=\"$TUNNEL_TOKEN_VAL\"\nfi\n\n# SUPABASE_URL is not a secret — read from env if the operator set one,\n# default to localhost for --local-only.\nexport SUPABASE_URL=\"\\${SUPABASE_URL:-http://localhost:8000}\"\n\n${promptServiceUrlExport}# prompt-service credentials. Always exported — harmless when the operator\n# is NOT colocating prompt-service (the main compose doesn't read these\n# vars; the overlay does). The PROMPT_SERVICE_API_KEYS list is built from\n# the operator's region + the single HMAC key in Keychain, matching the\n# prompt-service env format \\`<region>:<key>,<region>:<key>,…\\`.\nPROMPTS_DB_PASSWORD_VAL=\"$(optional_secret prompts-db-password)\"\nPROMPT_SERVICE_API_KEY_VAL=\"$(optional_secret prompt-service-api-key)\"\nPROMPT_SERVICE_ADMIN_API_KEY_VAL=\"$(optional_secret prompt-service-admin-api-key)\"\nif [ -n \"$PROMPTS_DB_PASSWORD_VAL\" ]; then\n export PROMPTS_DB_PASSWORD=\"$PROMPTS_DB_PASSWORD_VAL\"\nfi\nif [ -n \"$PROMPT_SERVICE_API_KEY_VAL\" ]; then\n export PROMPT_SERVICE_API_KEY=\"$PROMPT_SERVICE_API_KEY_VAL\"\n # API_KEYS env on prompt-service is \\`<region>:<key>,…\\` — render the\n # single-region pair here so prompt-service accepts the same key the\n # backend sends. The prompts team adds additional regions on the\n # central deployment for Phase 2.\n export PROMPT_SERVICE_API_KEYS=\"${input.region}:$PROMPT_SERVICE_API_KEY_VAL\"\nfi\nif [ -n \"$PROMPT_SERVICE_ADMIN_API_KEY_VAL\" ]; then\n export PROMPT_SERVICE_ADMIN_API_KEYS=\"$PROMPT_SERVICE_ADMIN_API_KEY_VAL\"\nfi\n\nexec docker compose \"$@\"\n`;\n}\n","/**\n * Side-effecting installer for the `bin/op-compose` wrapper script.\n *\n * Pure rendering lives in op-compose-script.ts so it stays unit-testable.\n * This file owns:\n * 1. Creating `<repo>/bin/` if needed\n * 2. Atomically writing the script (temp file + rename) so an\n * interrupted bootstrap never leaves a half-written wrapper that\n * `exec` would crash on\n * 3. `chmod 0755` so the operator can run `./bin/op-compose`\n */\n\nimport { chmod, mkdir, rename, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { renderOpComposeScript, type OpComposeScriptInput } from './op-compose-script.js';\n\nexport interface InstallOpComposeInput extends OpComposeScriptInput {\n /** Directory containing the compose file. Script lands at `<repoDir>/bin/op-compose`. */\n repoDir: string;\n}\n\nexport interface InstallOpComposeResult {\n ok: boolean;\n /** Absolute path the script was written to, when ok=true. */\n path?: string;\n reason?: string;\n}\n\nexport async function installOpComposeWrapper(\n input: InstallOpComposeInput,\n): Promise<InstallOpComposeResult> {\n let content: string;\n try {\n content = renderOpComposeScript({\n region: input.region,\n ...(input.promptServiceUrl !== undefined ? { promptServiceUrl: input.promptServiceUrl } : {}),\n });\n } catch (err) {\n return { ok: false, reason: (err as Error).message };\n }\n\n const binDir = join(input.repoDir, 'bin');\n const target = join(binDir, 'op-compose');\n const tmp = `${target}.tmp.${process.pid}`;\n\n try {\n await mkdir(binDir, { recursive: true });\n await writeFile(tmp, content, { mode: 0o755 });\n // mkdir/writeFile respect umask; chmod ensures 0755 regardless.\n await chmod(tmp, 0o755);\n await rename(tmp, target); // atomic on POSIX\n return { ok: true, path: target };\n } catch (err) {\n return { ok: false, reason: `writing ${target} failed: ${(err as Error).message}` };\n }\n}\n","/**\n * Docker compose + ghcr.io login orchestration.\n *\n * Three concerns this lib covers:\n *\n * 1. Authenticate Docker to ghcr.io using the operator's `gh auth token`,\n * piped on stdin so the token never lands in argv.\n * 2. `docker compose pull / up -d` against the prod compose set in the\n * operator's node repo checkout.\n * 3. Poll `docker compose ps --format json` until every service reports\n * `(healthy)`, with the same two-phase-budget pattern as lib/polling.ts\n * (containers can take a while to start showing up; healthy check then\n * runs on its own clock).\n */\n\nimport { safeExeca } from './exec.js';\n\n/** Default registry. Constant so tests + the bootstrap command read the same\n * value and an op-region migration to a different registry only changes\n * one place. */\nexport const GHCR_REGISTRY = 'ghcr.io';\n\nexport interface LoginResult {\n ok: boolean;\n reason?: string;\n}\n\n/**\n * Authenticate Docker to ghcr.io. Pulls the token from `gh auth token`,\n * pipes it on stdin to `docker login --password-stdin`. The username comes\n * from `gh api user --jq .login`. Three execa calls; failure at any point\n * reports cleanly with the responsible step.\n */\nexport async function loginToGhcr(): Promise<LoginResult> {\n const tokenRes = await safeExeca('gh', ['auth', 'token']);\n if (tokenRes === null) return { ok: false, reason: '`gh` not installed' };\n if (tokenRes.exitCode !== 0) {\n return {\n ok: false,\n reason: `gh auth token failed (${tokenRes.exitCode ?? 'signal'}): ${tokenRes.stderr || tokenRes.stdout}`,\n };\n }\n const token = tokenRes.stdout.trim();\n if (token.length === 0) {\n return { ok: false, reason: 'gh auth token returned empty — run `gh auth login` first' };\n }\n\n const userRes = await safeExeca('gh', ['api', 'user', '--jq', '.login']);\n if (userRes === null || userRes.exitCode !== 0) {\n return {\n ok: false,\n reason: `couldn't resolve GitHub user via gh api: ${userRes?.stderr || userRes?.stdout || 'gh missing'}`,\n };\n }\n const user = userRes.stdout.trim();\n if (user.length === 0) {\n return { ok: false, reason: 'gh api user returned empty — gh not signed in' };\n }\n\n const loginRes = await safeExeca(\n 'docker',\n ['login', GHCR_REGISTRY, '-u', user, '--password-stdin'],\n { input: token },\n );\n if (loginRes === null) return { ok: false, reason: '`docker` not installed' };\n if (loginRes.exitCode !== 0) {\n return {\n ok: false,\n reason: `docker login ${GHCR_REGISTRY} failed (${loginRes.exitCode ?? 'signal'}): ${loginRes.stderr || loginRes.stdout}`,\n };\n }\n return { ok: true };\n}\n\n// ----------------------------------------------------------------------------\n// Compose pull / up\n// ----------------------------------------------------------------------------\n\nexport interface ComposeOptions {\n /** Compose file paths, in order. Becomes `-f X -f Y …` on the command line. */\n files: string[];\n /** Working directory the compose command runs from. */\n cwd: string;\n /** Optional env-file flag, in the same convention as `--env-file`. */\n envFile?: string;\n /** Compose profiles to activate. Repeats as `--profile X --profile Y`. The\n * template's `cloudflared` service is gated behind the `public` profile;\n * bootstrap in local-only mode passes an empty array so cloudflared\n * stays down. */\n profiles?: ReadonlyArray<string>;\n /** Extra env vars passed to the docker compose subprocess. Used by\n * bootstrap to hydrate Keychain-loaded secrets (POSTGRES_PASSWORD,\n * JWT_SECRET, the Supabase JWTs, etc.) at compose-invocation time\n * without writing them to a plaintext `.env` file on disk. Per the\n * vault-first principle (#811), the wrapper script (`bin/op-compose`)\n * is the operator-facing version of the same pattern. */\n env?: NodeJS.ProcessEnv;\n}\n\nfunction composeArgs(opts: ComposeOptions, sub: string[]): string[] {\n const files = opts.files.flatMap((f) => ['-f', f]);\n const env = opts.envFile ? ['--env-file', opts.envFile] : [];\n const profiles = (opts.profiles ?? []).flatMap((pr) => ['--profile', pr]);\n return ['compose', ...files, ...env, ...profiles, ...sub];\n}\n\nexport interface ComposeResult {\n ok: boolean;\n reason?: string;\n}\n\n/** Build the execa options object once — both env and cwd flow from\n * ComposeOptions to safeExeca so subprocess hydration works uniformly. */\nfunction execOpts(opts: ComposeOptions): { cwd: string; env?: NodeJS.ProcessEnv } {\n return opts.env ? { cwd: opts.cwd, env: opts.env } : { cwd: opts.cwd };\n}\n\n/** `docker compose -f … pull`. Idempotent on first run; pulls new image tags. */\nexport async function composePull(opts: ComposeOptions): Promise<ComposeResult> {\n const res = await safeExeca('docker', composeArgs(opts, ['pull']), execOpts(opts));\n return result(res, 'compose pull');\n}\n\n/** `docker compose -f … up -d --remove-orphans`. */\nexport async function composeUp(opts: ComposeOptions): Promise<ComposeResult> {\n const res = await safeExeca('docker', composeArgs(opts, ['up', '-d', '--remove-orphans']), execOpts(opts));\n return result(res, 'compose up');\n}\n\n/**\n * `docker compose -f … rm -sfv <service>`. Stops + removes a single service +\n * its anonymous volumes. Used by `bootstrap --local-only` to evict a\n * cloudflared container left over from a prior public bootstrap; otherwise it\n * lingers in `compose ps` and the health-check loop demands it reach healthy.\n *\n * Returns ok=true when the service doesn't exist (compose treats \"rm a\n * service that isn't there\" as a no-op exit 0), so callers can call this\n * unconditionally.\n */\nexport async function composeRemoveService(\n opts: ComposeOptions,\n service: string,\n): Promise<ComposeResult> {\n const res = await safeExeca('docker', composeArgs(opts, ['rm', '-sfv', service]), execOpts(opts));\n return result(res, `compose rm ${service}`);\n}\n\nexport interface ComposeDownOptions extends ComposeOptions {\n /** When true, adds `-v` — destroys named volumes. The default false is the\n * safe choice: stop the stack but preserve the database. Callers must\n * ALWAYS surface a typed confirmation before flipping this on. */\n wipeVolumes?: boolean;\n /** When true, adds `--remove-orphans` — drops containers from compose files\n * no longer present. Useful on first-after-rename runs. */\n removeOrphans?: boolean;\n /** When set, adds `--rmi <mode>` to also remove the images.\n * - `'all'`: removes all images referenced by services (forces re-pull\n * on next `compose up`).\n * - `'local'`: removes only images that don't have a custom tag (i.e.,\n * locally-built ones; pulled images stay).\n * Use 'all' for true \"wipe everything and start over\" iteration loops. */\n removeImages?: 'all' | 'local';\n}\n\n/** `docker compose -f … down [-v] [--remove-orphans] [--rmi MODE]`. */\nexport async function composeDown(opts: ComposeDownOptions): Promise<ComposeResult> {\n const flags: string[] = ['down'];\n if (opts.wipeVolumes) flags.push('-v');\n if (opts.removeOrphans) flags.push('--remove-orphans');\n if (opts.removeImages) flags.push('--rmi', opts.removeImages);\n const label = [\n 'compose down',\n opts.wipeVolumes ? '-v' : '',\n opts.removeImages ? `--rmi ${opts.removeImages}` : '',\n ]\n .filter(Boolean)\n .join(' ');\n const res = await safeExeca('docker', composeArgs(opts, flags), execOpts(opts));\n return result(res, label);\n}\n\n/**\n * `docker logout <registry>`.\n *\n * Behavior on \"not currently logged in\" varies by version: Docker 24+ returns\n * exit 0 with \"Not logged in to <registry>\" on stdout, but older Docker\n * Desktop releases (and some credential-helper configurations) return a\n * non-zero exit instead. `reset` therefore renders a non-zero outcome as a\n * warning rather than a failure — the goal is \"ensure no creds remain,\" and\n * \"no creds existed to begin with\" satisfies that goal.\n *\n * Note: this only clears the credential-store entry. If the operator's\n * credential helper has cached the token elsewhere, or if `~/.docker/config.json`\n * has stale entries from a different host, those need separate cleanup.\n */\nexport async function dockerLogout(registry: string = GHCR_REGISTRY): Promise<ComposeResult> {\n const res = await safeExeca('docker', ['logout', registry]);\n return result(res, `docker logout ${registry}`);\n}\n\nfunction result(\n res: { exitCode: number | undefined; stdout: string; stderr: string } | null,\n label: string,\n): ComposeResult {\n if (res === null) return { ok: false, reason: '`docker` not installed' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `${label} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\n// ----------------------------------------------------------------------------\n// Compose ps — for the health check loop\n// ----------------------------------------------------------------------------\n\nexport interface ContainerSnapshot {\n name: string;\n /** `running`, `exited`, etc. — the Docker container state. */\n state: string;\n /** `healthy`, `unhealthy`, `starting`, or `none` (no healthcheck defined). */\n health: 'healthy' | 'unhealthy' | 'starting' | 'none';\n exitCode: number | null;\n}\n\n/**\n * Parse `docker compose ps --format json` output. Compose v2 emits one JSON\n * object per line for each container. We tolerate either format (NDJSON or\n * a single-line JSON array, depending on version).\n */\nexport function parseComposePs(stdout: string): ContainerSnapshot[] {\n // First try NDJSON line-by-line.\n const trimmed = stdout.trim();\n if (trimmed.length === 0) return [];\n\n const lines = trimmed.split('\\n').map((l) => l.trim()).filter((l) => l.length > 0);\n const out: ContainerSnapshot[] = [];\n\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as unknown;\n if (Array.isArray(parsed)) {\n for (const item of parsed) out.push(normalize(item));\n } else {\n out.push(normalize(parsed));\n }\n } catch {\n // Skip non-JSON lines (compose sometimes emits warnings on stdout).\n }\n }\n return out;\n}\n\nfunction normalize(raw: unknown): ContainerSnapshot {\n const r = (raw ?? {}) as Record<string, unknown>;\n const name = (r['Name'] as string) ?? (r['Service'] as string) ?? '<unknown>';\n const state = ((r['State'] as string) ?? 'unknown').toLowerCase();\n const healthRaw = ((r['Health'] as string) ?? '').toLowerCase();\n const health: ContainerSnapshot['health'] =\n healthRaw === 'healthy' || healthRaw === 'unhealthy' || healthRaw === 'starting'\n ? healthRaw\n : 'none';\n const exitCodeRaw = r['ExitCode'];\n const exitCode = typeof exitCodeRaw === 'number' ? exitCodeRaw : null;\n return { name, state, health, exitCode };\n}\n\n/**\n * `docker compose ps --format json`. Returns:\n *\n * - `null` when the call itself failed (docker missing, compose file wrong,\n * non-zero exit). The caller can distinguish a real failure from a\n * stack-not-up-yet case.\n * - `[]` when the call succeeded but no containers are listed yet (compose\n * up still in flight).\n * - `ContainerSnapshot[]` populated on success.\n */\nexport async function composePs(opts: ComposeOptions): Promise<ContainerSnapshot[] | null> {\n const res = await safeExeca('docker', composeArgs(opts, ['ps', '--format', 'json']), execOpts(opts));\n if (res === null || res.exitCode !== 0) return null;\n return parseComposePs(res.stdout);\n}\n\n// ----------------------------------------------------------------------------\n// Health-check loop\n// ----------------------------------------------------------------------------\n\nexport interface WaitForHealthyOptions {\n /** Container names that MUST be healthy before we return success. Empty\n * array means \"every container compose ps reports must be healthy or no-op\n * (i.e. state=exited with code 0 — db-migrate-style one-shots).\" */\n requireHealthy?: string[];\n /** Max time to wait, ms. Default 5 minutes. */\n timeoutMs?: number;\n /** Poll interval, ms. Default 5s. */\n pollMs?: number;\n /** Optional progress callback. */\n onPoll?: (snapshots: ContainerSnapshot[]) => void;\n}\n\nexport type HealthOutcome =\n | { kind: 'healthy'; snapshots: ContainerSnapshot[] }\n | { kind: 'unhealthy'; snapshots: ContainerSnapshot[]; problem: string }\n | { kind: 'timeout'; snapshots: ContainerSnapshot[] };\n\nexport interface WaitForHealthyDeps {\n ps: (opts: ComposeOptions) => Promise<ContainerSnapshot[] | null>;\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n}\n\nexport const realWaitDeps: WaitForHealthyDeps = {\n ps: composePs,\n sleep: (ms) => new Promise((res) => setTimeout(res, ms)),\n now: () => Date.now(),\n};\n\n/**\n * Poll `compose ps` until either every container reaches a happy terminal\n * state or the timeout fires. A \"happy\" state is:\n *\n * - `state=running` AND `health` ∈ {healthy, none}\n * - `state=exited` AND `exitCode === 0` (one-shot containers like db-migrate)\n *\n * `state=running` + `health=starting` keeps polling; `health=unhealthy` or\n * `state=exited` with non-zero exit returns immediately as `unhealthy`.\n */\n// Map a single non-empty poll result to a terminal HealthOutcome, or null\n// when the caller should keep polling ('pending' or no containers yet).\nfunction terminalOutcome(\n ps: ContainerSnapshot[],\n requireHealthy?: string[],\n): HealthOutcome | null {\n if (ps.length === 0) return null;\n const verdict = assessHealth(ps, requireHealthy);\n if (verdict.kind === 'healthy') return { kind: 'healthy', snapshots: ps };\n if (verdict.kind === 'unhealthy') {\n return { kind: 'unhealthy', snapshots: ps, problem: verdict.problem ?? 'unhealthy' };\n }\n return null;\n}\n\nexport async function waitForHealthy(\n composeOpts: ComposeOptions,\n options: WaitForHealthyOptions = {},\n deps: WaitForHealthyDeps = realWaitDeps,\n): Promise<HealthOutcome> {\n const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;\n const basePollMs = options.pollMs ?? 5 * 1000;\n const start = deps.now();\n let last: ContainerSnapshot[] = [];\n let pollCount = 0;\n\n while (deps.now() - start < timeoutMs) {\n pollCount++;\n const ps = await deps.ps(composeOpts);\n if (ps !== null) {\n last = ps;\n options.onPoll?.(ps);\n // A terminal verdict (healthy / unhealthy) returns immediately;\n // 'pending' (null here) falls through to the sleep + next iteration.\n const outcome = terminalOutcome(ps, options.requireHealthy);\n if (outcome) return outcome;\n }\n // Gentle backoff: 1× the base poll for the first 3 polls (fast feedback\n // while containers are settling), 2× after that. Caps wasted subprocess\n // startup on long timeouts without slowing down the typical case.\n const interval = pollCount < 3 ? basePollMs : basePollMs * 2;\n await deps.sleep(interval);\n }\n return { kind: 'timeout', snapshots: last };\n}\n\ninterface AssessVerdict {\n kind: 'healthy' | 'unhealthy' | 'pending';\n problem?: string;\n}\n\nexport function assessHealth(\n snapshots: ContainerSnapshot[],\n requireHealthy?: string[],\n): AssessVerdict {\n // Hard failures short-circuit regardless of the required-list mode.\n const hard = firstHardFailure(snapshots);\n if (hard) return hard;\n\n const required = requireHealthy ?? [];\n return required.length > 0\n ? assessRequired(snapshots, required)\n : assessAllRunning(snapshots);\n}\n\n// Hard failure conditions: any unhealthy, any exited-with-non-zero.\nfunction firstHardFailure(snapshots: ContainerSnapshot[]): AssessVerdict | null {\n for (const s of snapshots) {\n if (s.health === 'unhealthy') {\n return { kind: 'unhealthy', problem: `${s.name} reports unhealthy` };\n }\n if (s.state === 'exited' && (s.exitCode ?? 0) !== 0) {\n return { kind: 'unhealthy', problem: `${s.name} exited with code ${s.exitCode}` };\n }\n }\n return null;\n}\n\n// The caller specified a required-healthy list — gate on exactly those.\nfunction assessRequired(snapshots: ContainerSnapshot[], required: string[]): AssessVerdict {\n const byName = new Map(snapshots.map((s) => [s.name, s]));\n for (const name of required) {\n const s = byName.get(name);\n if (!s) return { kind: 'pending' };\n if (s.state === 'exited' && s.exitCode === 0) continue;\n if (s.state !== 'running') return { kind: 'pending' };\n if (s.health === 'starting') return { kind: 'pending' };\n if (s.health === 'unhealthy') {\n return { kind: 'unhealthy', problem: `${s.name} reports unhealthy` };\n }\n }\n return { kind: 'healthy' };\n}\n\n// No required list — all snapshots must be in a happy state.\nfunction assessAllRunning(snapshots: ContainerSnapshot[]): AssessVerdict {\n for (const s of snapshots) {\n if (s.state === 'exited' && s.exitCode === 0) continue;\n if (s.state !== 'running') return { kind: 'pending' };\n if (s.health === 'starting') return { kind: 'pending' };\n }\n return { kind: 'healthy' };\n}\n","/**\n * Ollama service + model management.\n *\n * Ollama is installed via Homebrew (handled by `lib/homebrew.ts`) and started\n * as a `brew services` job. This lib covers what the wizard does after that:\n *\n * - HTTP health check on `localhost:11434` (the running daemon).\n * - List installed models via the HTTP API (avoids parsing `ollama list`'s\n * human-formatted output).\n * - Pull a model — shells out to `ollama pull <name>` because the HTTP\n * `/api/pull` endpoint streams NDJSON progress and is awkward to consume.\n * - Warm a model with a single trivial generation so the first user request\n * doesn't pay a ~90s cold-start.\n * - Probe that containers can reach the host's Ollama via\n * `host.docker.internal` — common Docker Desktop configuration mistake.\n */\n\nimport { safeExeca } from './exec.js';\n\nexport const OLLAMA_URL = 'http://localhost:11434';\n\n/** Default LLM the platform ships against — small enough to pull on a fresh\n * Studio in minutes, capable enough to validate the inference path\n * end-to-end. Operators can override at bootstrap time with `--llm-model`,\n * and we surface a sizing table in `docs/docker-resources.md` for the\n * 70B-class jump. */\nexport const DEFAULT_LLM_MODEL = 'qwen3.5:9b';\n\n/** Default embedding model used by the knowledge service when\n * `EMBEDDINGS_PROVIDER=ollama`. With the default `xenova` (in-process)\n * provider, this isn't pulled. Operators can override with\n * `--embedding-model`. */\nexport const DEFAULT_EMBEDDING_MODEL = 'nomic-embed-text';\n\n/** Default model pull set for `bootstrap`. Kept as a `as const`-typed array\n * so existing code can iterate without re-deriving from the two scalars. */\nexport const DEFAULT_MODELS = [DEFAULT_LLM_MODEL, DEFAULT_EMBEDDING_MODEL] as const;\n\n/** Pinned alpine tag for the host.docker.internal probe. Latest is fine in\n * practice (the image only runs `curl`) but pinning keeps the probe\n * reproducible across operator machines. Bump when alpine cuts a major. */\nexport const PROBE_ALPINE_TAG = '3.20';\n\nexport interface OllamaHealth {\n /** True when the daemon answered the `/api/tags` probe with 200. */\n reachable: boolean;\n /** Names of currently-installed models, when reachable. */\n models: string[];\n}\n\n/**\n * Probe the daemon. We use `/api/tags` because it's the cheapest endpoint\n * that proves both reachability AND that the server is past initial bring-up\n * (a bare TCP-accept-but-not-ready Ollama returns 404 here, not 200).\n */\n/**\n * Try to start the Ollama service via `brew services start ollama`.\n * Idempotent — brew services no-ops on an already-started service. Returns\n * `ok: false` only if brew itself is missing or the start command errored\n * for a non-trivial reason.\n */\nexport async function startOllamaService(): Promise<{ ok: boolean; reason?: string }> {\n const res = await safeExeca('brew', ['services', 'start', 'ollama']);\n if (res === null) return { ok: false, reason: '`brew` not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `brew services start ollama failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport async function checkOllamaHealth(url: string = OLLAMA_URL): Promise<OllamaHealth> {\n try {\n const res = await fetch(`${url}/api/tags`);\n if (!res.ok) return { reachable: false, models: [] };\n const body = (await res.json()) as { models?: Array<{ name?: string }> };\n const models = (body.models ?? [])\n .map((m) => m.name ?? '')\n .filter((n) => n.length > 0);\n return { reachable: true, models };\n } catch {\n return { reachable: false, models: [] };\n }\n}\n\nexport interface PullResult {\n ok: boolean;\n /** Set when ok=false. */\n reason?: string;\n}\n\n/**\n * Pull a model. `ollama pull` is idempotent — re-pulling a present model is\n * a fast no-op — so we don't pre-check installation.\n */\nexport async function pullModel(name: string): Promise<PullResult> {\n const res = await safeExeca('ollama', ['pull', name]);\n if (res === null) return { ok: false, reason: '`ollama` not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `ollama pull ${name} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport interface WarmResult {\n ok: boolean;\n reason?: string;\n}\n\n/**\n * Send a trivial `/api/generate` call so the model loads into memory. First\n * request on a cold daemon can take 30-90s; that latency lands on the wizard,\n * not on a real user. We stream=false + ignore the response body.\n */\nexport async function warmModel(name: string, url: string = OLLAMA_URL): Promise<WarmResult> {\n try {\n const res = await fetch(`${url}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: name, prompt: 'hi', stream: false }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n return {\n ok: false,\n reason: `warm ${name} returned HTTP ${res.status}: ${text || '(no body)'}`,\n };\n }\n // Drain the body to ensure the model finished loading.\n await res.text();\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n reason: `warm ${name} failed: ${(err as Error).message}`,\n };\n }\n}\n\n/**\n * Verify Docker containers can reach the host's Ollama via\n * `host.docker.internal`. Operators sometimes disable that hostname in Docker\n * Desktop settings; this probe catches the misconfig before the stack comes\n * up and fails opaquely.\n */\nexport async function probeHostDockerInternal(): Promise<{ ok: boolean; reason?: string }> {\n const res = await safeExeca('docker', [\n 'run',\n '--rm',\n `alpine:${PROBE_ALPINE_TAG}`,\n 'sh',\n '-c',\n 'apk add --no-cache curl >/dev/null 2>&1 && curl -fsS http://host.docker.internal:11434/api/tags',\n ]);\n if (res === null) return { ok: false, reason: '`docker` not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason:\n `container couldn't reach host.docker.internal:11434 — check Docker Desktop ` +\n `settings → Resources → Network → Enable host.docker.internal`,\n };\n }\n return { ok: true };\n}\n\nexport interface SetupReport {\n pulled: string[];\n alreadyPresent: string[];\n failed: Array<{ model: string; reason: string }>;\n warmed: string[];\n}\n\n/**\n * Pull each model in `models` (skipping already-present ones) and warm the\n * first one. Continues past per-model failures so the operator sees the\n * whole landscape.\n */\nexport async function setupModels(\n models: readonly string[],\n onProgress?: (model: string, status: 'present' | 'pulling' | 'pulled' | 'failed' | 'warming' | 'warmed') => void,\n): Promise<SetupReport> {\n const report: SetupReport = {\n pulled: [],\n alreadyPresent: [],\n failed: [],\n warmed: [],\n };\n\n const health = await checkOllamaHealth();\n const present = new Set(health.models);\n\n for (const m of models) {\n if (present.has(m)) {\n report.alreadyPresent.push(m);\n onProgress?.(m, 'present');\n continue;\n }\n onProgress?.(m, 'pulling');\n const r = await pullModel(m);\n if (r.ok) {\n report.pulled.push(m);\n onProgress?.(m, 'pulled');\n } else {\n report.failed.push({ model: m, reason: r.reason ?? 'unknown' });\n onProgress?.(m, 'failed');\n }\n }\n\n // Warm the first model that exists by name in the user-supplied list, not\n // necessarily the first to pull successfully — keeps the warm target\n // predictable for tests + operator UX.\n const warmTarget = models.find((m) => present.has(m) || report.pulled.includes(m));\n if (warmTarget) {\n onProgress?.(warmTarget, 'warming');\n const w = await warmModel(warmTarget);\n if (w.ok) {\n report.warmed.push(warmTarget);\n onProgress?.(warmTarget, 'warmed');\n }\n // A failed warm-up isn't fatal — it just means the first real user\n // request pays the cold-start cost. Surface in the report.\n }\n\n return report;\n}\n","/**\n * Locate or clone the operator's node deployment repo on the Mac Studio.\n *\n * The bootstrap subcommand wants a working tree of the operator's region\n * deployment repo (created from `OpusPopuli/opuspopuli-node` by `init`) on\n * the Studio's filesystem — it's the source of `docker-compose-prod.yml`,\n * `supabase/init/`, `backup/scripts/`, `observability/`, etc.\n *\n * Three discovery paths the wizard tries in order:\n *\n * 1. **Explicit `--repo-dir`** — operator passed a path. Verify it's a\n * node repo (looks for the marker file) and use it.\n * 2. **Current directory** — operator may have already cloned + cd'd.\n * Same marker probe.\n * 3. **Clone fresh** — shell out to `gh repo clone <owner>/<repo>` into\n * `~/Development/<repo>`. The default location keeps it under the\n * operator's home (no sudo) and groups it with other dev work.\n */\n\nimport { access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nimport { safeExeca } from './exec.js';\n\n/** Files that a freshly-cloned (or template-derived) node repo always has.\n * Probing for these is how we distinguish a node repo from an arbitrary\n * directory the operator pointed us at. */\nexport const NODE_REPO_MARKERS = [\n 'docker-compose-prod.yml',\n 'supabase/init/pgsodium_getkey_env.sh',\n] as const;\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** True when every marker file is present at `dir`. False otherwise. */\nexport async function looksLikeNodeRepo(dir: string): Promise<boolean> {\n const checks = await Promise.all(\n NODE_REPO_MARKERS.map((m) => fileExists(join(dir, m))),\n );\n return checks.every((ok) => ok);\n}\n\nexport interface LocateInput {\n /** Owner of the node repo, e.g. `OpusPopuli`. */\n owner: string;\n /** Repo name, e.g. `opuspopuli-node-us-ca`. */\n name: string;\n /** Operator-supplied override (--repo-dir). When set, we use it iff it\n * looks like a node repo; otherwise return an error rather than fall\n * through to cloning a fresh copy. */\n explicit?: string;\n /** Where to put a fresh clone when neither --repo-dir nor cwd matches.\n * Default: ~/Development/<name>. */\n cloneInto?: string;\n /** When false, refuse to clone and require the operator to provide\n * a working tree (skip the gh shell-out). Default: true. */\n allowClone?: boolean;\n /** Working directory to probe as the \"already-cloned-and-cd'd\" path. */\n cwd?: string;\n}\n\nexport type LocateOutcome =\n | { kind: 'found'; path: string; source: 'explicit' | 'cwd' }\n | { kind: 'cloned'; path: string }\n | { kind: 'explicit-not-a-node-repo'; path: string }\n | { kind: 'gh-not-installed' }\n | { kind: 'clone-failed'; reason: string }\n | { kind: 'clone-disallowed' };\n\n/**\n * Walk the three discovery paths and return a discriminated outcome the\n * wizard can render. Cleanly separates \"operator-intentional path\" failures\n * from \"we tried but couldn't help\" failures.\n */\nexport async function locateOrCloneRepo(input: LocateInput): Promise<LocateOutcome> {\n // 1. Explicit --repo-dir.\n if (input.explicit) {\n if (await looksLikeNodeRepo(input.explicit)) {\n return { kind: 'found', path: input.explicit, source: 'explicit' };\n }\n return { kind: 'explicit-not-a-node-repo', path: input.explicit };\n }\n\n // 2. CWD probe.\n const cwd = input.cwd ?? process.cwd();\n if (await looksLikeNodeRepo(cwd)) {\n return { kind: 'found', path: cwd, source: 'cwd' };\n }\n\n // 3. Clone fresh.\n if (input.allowClone === false) {\n return { kind: 'clone-disallowed' };\n }\n\n const target = input.cloneInto ?? join(homedir(), 'Development', input.name);\n const res = await safeExeca('gh', ['repo', 'clone', `${input.owner}/${input.name}`, target]);\n if (res === null) return { kind: 'gh-not-installed' };\n if (res.exitCode !== 0) {\n return {\n kind: 'clone-failed',\n reason: `gh repo clone failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { kind: 'cloned', path: target };\n}\n","/**\n * Compile-time exhaustiveness guard. Passing a value that TypeScript has\n * not narrowed to `never` is a type error, so an unhandled `switch` / `if`\n * variant fails the build. At runtime this is a no-op — callers keep their\n * existing control flow (fall through, `return`, etc.).\n */\nexport function assertNever(_value: never): void {\n /* compile-time only */\n}\n","import { join } from 'node:path';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport {\n PGSODIUM_KEY_RE,\n SAFE_LAUNCHCTL_VALUE_RE,\n SAFE_URL_RE,\n TUNNEL_TOKEN_RE,\n URL_SAFE_PASSWORD_RE,\n} from '../lib/constants.js';\nimport {\n detectBrew,\n HOMEBREW_INSTALL_COMMAND,\n installPackages,\n STUDIO_PACKAGES,\n} from '../lib/homebrew.js';\nimport {\n detectUnifiedMemoryGB,\n disableDiskSleep,\n enableAutoRestartOnPowerFailure,\n inspectSystem,\n} from '../lib/macos.js';\nimport {\n detectKeychain,\n isKeychainLocked,\n isSshSession,\n readSecret,\n saveSecret,\n unlockKeychain,\n type SecretAccount,\n} from '../lib/keychain.js';\nimport {\n generateDashboardPassword,\n generateHmacApiKey,\n generateJwtSecret,\n generatePgsodiumRootKey,\n generatePostgresPassword,\n signSupabaseJwt,\n verifySupabaseJwt,\n} from '../lib/secrets.js';\nimport { setupLaunchAgent } from '../lib/launchagent.js';\nimport { installOpComposeWrapper } from '../lib/op-compose-install.js';\nimport {\n composePull,\n composeRemoveService,\n composeUp,\n loginToGhcr,\n waitForHealthy,\n} from '../lib/docker.js';\nimport {\n DEFAULT_EMBEDDING_MODEL,\n DEFAULT_LLM_MODEL,\n checkOllamaHealth,\n probeHostDockerInternal,\n setupModels,\n startOllamaService,\n} from '../lib/ollama.js';\nimport { locateOrCloneRepo, type LocateOutcome } from '../lib/noderepo.js';\nimport { safeExeca } from '../lib/exec.js';\nimport { unwrap } from '../lib/prompts.js';\nimport { assertNever } from '../lib/assert.js';\n\n/** Compose profile set used in production mode — activates cloudflared. */\nconst PUBLIC_PROFILES = ['public'] as const;\n/** Compose profile set used in --local-only mode — keeps cloudflared down\n * via the template's profile gating. */\nconst LOCAL_PROFILES = [] as const;\n\n/** Node deployment topology — selects which docker compose stack(s) +\n * Keychain entries bootstrap provisions.\n *\n * - `region` — standard region node (civic data for one region). Connects\n * to a REMOTE prompt-service via PROMPT_SERVICE_URL. The HMAC key for\n * that remote service is issued by the prompts team and pasted in;\n * bootstrap stores it under the same Keychain account as the colocated\n * case so the wrapper exports it transparently. This is the production\n * default for any operator who isn't on the prompts team.\n *\n * - `region-with-prompts` — region node + colocated prompt-service overlay\n * (the us-ca / team / dev case). Bootstrap generates a local HMAC key,\n * a prompt-service admin key, and a prompts-db password — all stored\n * in Keychain — and the op-compose wrapper exports them so the\n * `docker-compose-prompt-service.yml` overlay can layer on top.\n *\n * - `prompts-only` — STUB. Reserved for when the prompts team deploys the\n * central prompts.opuspopuli.org instance. No region services; only the\n * prompt-service + its DB. Bootstrap currently exits with a \"not yet\n * implemented\" message — the flag exists so the CLI surface is stable\n * for the future deployment.\n */\ntype NodeType = 'region' | 'region-with-prompts' | 'prompts-only';\n\ninterface BootstrapOptions {\n region?: string;\n owner?: string;\n repoDir?: string;\n composeFile?: string[];\n envFile?: string;\n skipBrew?: boolean;\n skipLaunchAgent?: boolean;\n skipOllama?: boolean;\n skipStack?: boolean;\n localOnly?: boolean;\n llmModel?: string;\n embeddingModel?: string;\n /** Public-facing Supabase URL. Defaults to `http://localhost:8000` in\n * --local-only mode, otherwise `https://supabase.<domain>` — operator\n * can override with --supabase-url. */\n supabaseUrl?: string;\n /** Selects which deployment stack to provision. Defaults to `region`. */\n nodeType?: NodeType;\n /** For `--node-type region` (remote prompt-service): the URL of the\n * central prompt-service the backend should call. Defaults to\n * `https://prompts.opuspopuli.org`. Ignored in `region-with-prompts`\n * (the overlay pins it to the in-network hostname). */\n promptServiceUrl?: string;\n yes?: boolean;\n}\n\nexport const bootstrapCommand = new Command('bootstrap')\n .description(\n 'Configure the Mac Studio and bring the stack up. Run this on the Studio itself, after `init` has finished on your laptop.',\n )\n .addOption(new Option('--region <slug>', 'Region label set during init (e.g. us-ca)'))\n .addOption(new Option('--owner <owner>', 'GitHub owner for the node repo').default('OpusPopuli'))\n .addOption(new Option('--repo-dir <path>', 'Explicit path to a checked-out node repo (overrides cwd + clone)'))\n .addOption(\n new Option(\n '--compose-file <path>',\n 'Repeatable. Compose file relative to repo root. Default: prod + backup (production), prod only (--local-only).',\n ),\n )\n .addOption(new Option('--env-file <path>', 'Compose --env-file. Default: .env.production'))\n .addOption(new Option('--skip-brew', \"Skip the Homebrew package install pass\").default(false))\n .addOption(\n new Option(\n '--skip-launch-agent',\n \"Skip the LaunchAgent setup (assumes one is already in place)\",\n ).default(false),\n )\n .addOption(new Option('--skip-ollama', \"Skip the Ollama model pull + warm\").default(false))\n .addOption(\n new Option(\n '--llm-model <model>',\n `Ollama LLM model to pull and warm. Default: ${DEFAULT_LLM_MODEL}. Examples: \\`llama3.3:70b\\`, \\`qwen2.5:72b\\`. Memory sizing table: docs/docker-resources.md in the opuspopuli-node template (or your region repo's checkout).`,\n ),\n )\n .addOption(\n new Option(\n '--embedding-model <model>',\n `Ollama embedding model. Default: ${DEFAULT_EMBEDDING_MODEL}. Only takes effect when the knowledge service runs with EMBEDDINGS_PROVIDER=ollama (otherwise embeddings are computed in-process via xenova).`,\n ),\n )\n .addOption(\n new Option(\n '--supabase-url <url>',\n 'Public-facing Supabase URL (what browsers + microservices use). Default: `http://localhost:8000` in --local-only mode, otherwise `https://supabase.<domain>` (which the operator can override).',\n ),\n )\n .addOption(\n new Option(\n '--node-type <type>',\n 'Deployment topology. `region` (default) = region node connecting to remote prompt-service. `region-with-prompts` = region node + colocated prompt-service overlay (team/dev use). `prompts-only` = future stub for the central prompts deployment.',\n ).choices(['region', 'region-with-prompts', 'prompts-only']),\n )\n .addOption(\n new Option(\n '--prompt-service-url <url>',\n \"Remote prompt-service URL. Only meaningful for --node-type=region (default: https://prompts.opuspopuli.org). Ignored for --node-type=region-with-prompts (the overlay pins it to http://opuspopuli-prompts:3210).\",\n ),\n )\n .addOption(new Option('--skip-stack', \"Stop before `docker compose pull && up`\").default(false))\n .addOption(\n new Option(\n '--local-only',\n \"Run for local dev / testing: no Tunnel token required, cloudflared stays down. Auto-generates the pgsodium key if not in Keychain (init unnecessary).\",\n ).default(false),\n )\n .addOption(new Option('-y, --yes', 'Skip confirmation prompts').default(false))\n .action(async (opts: BootstrapOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node bootstrap ')));\n\n const nodeType = await selectNodeType(opts);\n const region = await resolveRegion(opts);\n const owner = opts.owner ?? 'OpusPopuli';\n const repoName = `opuspopuli-node-${region}`;\n const composeFile = opts.composeFile ?? defaultComposeFiles(opts);\n\n // Model selection: flags override > interactive prompt > defaults. The\n // resolved values flow to both Ollama (pull + warm) and the LaunchAgent\n // (LLM_MODEL / EMBEDDINGS_MODEL). bootstrap is the source of truth for\n // what model runs. (N3)\n const llmModelChoice = opts.llmModel ?? (await selectLlmModel(opts));\n const [embeddingModel, llmModel] = resolveModels({\n llmModel: llmModelChoice,\n ...(opts.embeddingModel !== undefined ? { embeddingModel: opts.embeddingModel } : {}),\n });\n\n // ---- Phases 1–4: system checks, Homebrew, auth, locate repo ----\n await runSystemChecksPhase();\n await runBrewPhase(opts);\n await ensureGhAuth();\n await promptTailscaleSignin();\n const repoPath = await locateRegionRepoPhase(opts, owner, repoName);\n\n // ---- Phase 5: secrets (Keychain unlock, load/generate, URLs) ----\n await unlockKeychainPhase();\n\n const secrets = await collectSecretsPhase({ region, nodeType, opts });\n await runLaunchAgentPhase({ opts, secrets, llmModel, embeddingModel });\n await installWrapperPhase({ repoPath, region, promptServiceUrl: secrets.promptServiceUrl });\n await loginGhcrPhase();\n await runOllamaPhase({ opts, embeddingModel, llmModel });\n await runStackPhase({ opts, repoPath, region, composeFile, secrets, llmModel, embeddingModel });\n });\n\n// ----------------------------------------------------------------------------\n// Bootstrap phases\n// ----------------------------------------------------------------------------\n// The command action delegates to these phase helpers so no single function\n// exceeds the cognitive-complexity budget. Each is behavior-preserving — the\n// interactive prompts, spinners, and `process.exit` calls are relocated\n// verbatim, not changed. The orchestrator threads values through explicitly.\n\ninterface CollectedSecrets {\n pgsodiumKey: string;\n tunnelToken: string | undefined;\n postgresPassword: string;\n jwtSecret: string;\n supabaseAnonKey: string;\n supabaseServiceRoleKey: string;\n dashboardPassword: string;\n promptServiceUrl: string;\n supabaseUrl: string;\n}\n\n// Default compose file set by mode (review S4): production runs the\n// backup stack (restic / rclone) alongside the main stack; local-only\n// skips it (don't burn dev-machine disk on backups; don't try to push\n// to an R2 bucket that may not exist). Operator can still override\n// with explicit --compose-file flags.\nfunction defaultComposeFiles(opts: BootstrapOptions): string[] {\n return opts.localOnly\n ? ['docker-compose-prod.yml']\n : ['docker-compose-prod.yml', 'docker-compose-backup.yml'];\n}\n\n// Node type selects which stack to provision. Default is `region` — the\n// common case for any operator who isn't on the prompts team.\n// `region-with-prompts` covers the team/dev case where the operator runs\n// prompt-service alongside the region stack. `prompts-only` is a documented\n// stub for the future central prompts deployment — exits early to keep the\n// CLI surface stable now.\nasync function selectNodeType(opts: BootstrapOptions): Promise<NodeType> {\n const nodeType: NodeType = opts.nodeType\n ? opts.nodeType\n : (unwrap(\n await p.select({\n message: 'What kind of node are you provisioning?',\n options: [\n {\n value: 'region',\n label: 'Region node (civic data for one region, remote prompt-service)',\n },\n {\n value: 'region-with-prompts',\n label: 'Region + colocated prompt-service (team / dev)',\n },\n {\n value: 'prompts-only',\n label: 'Prompt-service node (central prompts deployment — future)',\n },\n ],\n initialValue: 'region',\n }),\n ) as NodeType);\n\n if (nodeType === 'prompts-only') {\n p.cancel(\n 'prompts-only node deployment is not yet implemented. ' +\n 'This flag exists so the CLI surface is stable for when the prompts team ' +\n 'deploys the central prompts.opuspopuli.org instance — but the deployment ' +\n 'stack (compose file, healthchecks, observability) is filled in later, ' +\n 'when there is an actual central prompt-service to deploy.',\n );\n process.exit(1);\n }\n return nodeType;\n}\n\n// Region label (required to find Keychain items + repo name).\nasync function resolveRegion(opts: BootstrapOptions): Promise<string> {\n return opts.region\n ? opts.region\n : unwrap(\n await p.text({\n message: 'Region label (the slug used during init — e.g. us-ca)?',\n placeholder: 'us-ca',\n validate: (v) =>\n /^[a-z0-9-]{2,32}$/.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens; 2–32 chars',\n }),\n );\n}\n\n// ---- Phase 1: macOS sanity ----\nasync function runSystemChecksPhase(): Promise<void> {\n const sysSpin = p.spinner();\n sysSpin.start('Inspecting macOS…');\n const snap = await inspectSystem();\n sysSpin.stop(pc.green('✓ macOS inspected.'));\n\n if (!snap.isAppleSilicon) {\n p.cancel(\n `Bootstrap requires an Apple Silicon Mac (the runbook targets M-series). Detected: ${snap.osVersion ?? 'unknown'} (uname -m != arm64).`,\n );\n process.exit(1);\n }\n\n p.note(\n [\n `Hostname: ${pc.cyan(snap.hostname)}`,\n `macOS: ${pc.cyan(snap.osVersion ?? '(sw_vers failed)')}`,\n `Auto-restart on power: ${kvBool(snap.autoRestartOnPowerFailure)}`,\n `Disk sleep disabled: ${kvBool(snap.diskSleepDisabled)}`,\n `FileVault: ${kvFileVault(snap.fileVaultEnabled)}`,\n ].join('\\n'),\n 'System snapshot',\n );\n\n if (!snap.autoRestartOnPowerFailure) {\n const fix = unwrap(\n await p.confirm({\n message: 'Auto-restart-on-power-failure is OFF. Enable now (requires sudo)?',\n initialValue: true,\n }),\n );\n if (fix) {\n const r = await enableAutoRestartOnPowerFailure();\n if (!r.ok) p.note(`${pc.red('✗')} ${r.reason}`, 'pmset failed');\n }\n }\n if (!snap.diskSleepDisabled) {\n const fix = unwrap(\n await p.confirm({\n message: 'Disk sleep is enabled. Disable now (requires sudo)?',\n initialValue: true,\n }),\n );\n if (fix) {\n const r = await disableDiskSleep();\n if (!r.ok) p.note(`${pc.red('✗')} ${r.reason}`, 'pmset failed');\n }\n }\n}\n\n// ---- Phase 2: Homebrew + tool installs ----\nasync function runBrewPhase(opts: BootstrapOptions): Promise<void> {\n if (opts.skipBrew) return;\n\n const brewInfo = await detectBrew();\n if (!brewInfo.installed) {\n p.note(\n [\n `Homebrew is not installed. Open another shell and run:`,\n '',\n pc.cyan(HOMEBREW_INSTALL_COMMAND),\n '',\n pc.dim('Then come back and press Enter.'),\n ].join('\\n'),\n 'Manual step',\n );\n unwrap(await p.confirm({ message: 'Homebrew installed?', initialValue: true }));\n }\n\n const brewSpin = p.spinner();\n brewSpin.start('Installing Studio packages… (~5–15 min first run)');\n const report = await installPackages(STUDIO_PACKAGES, (pkg, status) => {\n brewSpin.message(`${status}: ${pkg.name}`);\n });\n brewSpin.stop(\n report.failed.length === 0\n ? pc.green(\n `✓ ${report.installed.length} installed, ${report.alreadyPresent.length} already present`,\n )\n : pc.yellow(\n `⚠ ${report.installed.length} installed, ${report.alreadyPresent.length} present, ${report.failed.length} failed`,\n ),\n );\n if (report.failed.length > 0) {\n p.note(\n [\n report.failed.map((f) => `${pc.red('•')} ${f.pkg.name}: ${f.reason}`).join('\\n'),\n '',\n pc.dim('A partial install usually fails downstream (Docker / Ollama / compose).'),\n pc.dim('Install the failed packages manually and re-run with --skip-brew.'),\n ].join('\\n'),\n 'Brew failures',\n );\n const cont = unwrap(\n await p.confirm({\n message: 'Continue anyway? (Default no — recommended to fix and re-run.)',\n initialValue: false,\n }),\n );\n if (!cont) process.exit(1);\n }\n}\n\n// ---- Phase 4: Locate / clone the region repo (fail-fast — S6 review fix) ----\n// Moved up from Phase 8: a repo-not-found error after 5-10 minutes of\n// brew + Ollama work is operator-hostile. The clone only needs `gh`\n// (Phase 3), so we can validate the repo exists early and bail before\n// the slow stuff if it doesn't.\nasync function locateRegionRepoPhase(\n opts: BootstrapOptions,\n owner: string,\n repoName: string,\n): Promise<string> {\n const repoSpin = p.spinner();\n repoSpin.start('Locating your region node repo…');\n const located = await locateOrCloneRepo({\n owner,\n name: repoName,\n cwd: process.cwd(),\n ...(opts.repoDir ? { explicit: opts.repoDir } : {}),\n });\n const repoPath = repoPathFromLocate(located);\n if (!repoPath) {\n repoSpin.stop(pc.red('✗ Couldn\\'t locate or clone the region repo.'));\n handleLocateError(located, owner, repoName);\n process.exit(1);\n }\n repoSpin.stop(\n located.kind === 'cloned'\n ? pc.green(`✓ Cloned ${owner}/${repoName} to ${repoPath}`)\n : pc.green(`✓ Found region repo at ${repoPath}`),\n );\n return repoPath;\n}\n\n// ---- Phase 5: keychain availability + SSH unlock ----\n//\n// The Keychain item is local to the machine that wrote it (`init` on the\n// laptop). On a fresh Studio, both items will be missing on first run —\n// bootstrap prompts the operator to paste, validates the format, and writes\n// to the Studio's local Keychain for re-runs.\nasync function unlockKeychainPhase(): Promise<void> {\n const keychain = await detectKeychain();\n if (!keychain.available) {\n p.cancel(\n `${keychain.reason ?? 'Keychain unavailable'}. Bootstrap requires the macOS Keychain.`,\n );\n process.exit(1);\n }\n\n // SSH sessions don't auto-unlock the login keychain at session start.\n // When the operator is over SSH AND the keychain is currently locked,\n // every `security add-generic-password` call will fail with exit 36\n // (errSecInteractionNotAllowed). Prompt for the login password once\n // up front, unlock, then proceed — much better UX than 9 identical\n // failures (one per secret) before the operator figures it out.\n if (isSshSession() && (await isKeychainLocked())) {\n p.note(\n [\n 'SSH session detected with a locked login keychain.',\n 'macOS keychain operations require an unlocked keychain — your',\n 'login password will be used once to unlock it for this session.',\n 'The keychain remains unlocked until the session ends or it',\n 'idle-locks. To skip and unlock manually, press Ctrl+C and run',\n '`security unlock-keychain` yourself.',\n ].join('\\n'),\n 'Keychain unlock required',\n );\n const pw = unwrap(\n await p.password({\n message: 'macOS login password (for `security unlock-keychain`):',\n validate: (v) => (v && v.length > 0 ? undefined : 'password required'),\n }),\n );\n const unlock = await unlockKeychain(pw);\n if (!unlock.ok) {\n p.cancel(unlock.reason ?? 'security unlock-keychain failed.');\n process.exit(1);\n }\n p.note(`${pc.green('✓')} Keychain unlocked for this session.`, 'Keychain');\n }\n}\n\n// ---- Phase 5a: pgsodium key, tunnel token, and Supabase self-hosted creds ----\n//\n// In --local-only mode there's no Tunnel token at all (cloudflared stays\n// down via compose profile gating). The pgsodium key is still required\n// since the data services use it; if missing, we generate a fresh one\n// inline rather than requiring an `init` call first.\n//\n// The five Supabase values (postgres password, JWT secret, anon +\n// service_role JWTs, dashboard password) are auto-generated on first run\n// via the same `loadSecret` path used for the pgsodium key. The two JWTs\n// are derived from JWT_SECRET and re-validated against it so a stale token\n// cached from a prior bootstrap can't silently break auth.\nasync function collectCoreSecrets(args: {\n region: string;\n opts: BootstrapOptions;\n}): Promise<Omit<CollectedSecrets, 'promptServiceUrl' | 'supabaseUrl'>> {\n const { region, opts } = args;\n const pgsodiumKey = await loadSecret({\n region,\n account: 'pgsodium-root-key',\n label: 'pgsodium master key',\n validate: (v) =>\n PGSODIUM_KEY_RE.test(v) ? undefined : 'must be exactly 64 lowercase hex characters',\n ...(opts.localOnly ? { generate: generatePgsodiumRootKey } : {}),\n });\n\n const tunnelToken = opts.localOnly\n ? undefined\n : await loadSecret({\n region,\n account: 'tunnel-token',\n label: 'Cloudflare Tunnel token',\n placeholder: 'JWT-style base64url string from `terraform output tunnel_token`',\n validate: (v) =>\n TUNNEL_TOKEN_RE.test(v) ? undefined : 'tunnel token must be a base64-url JWT',\n });\n\n const postgresPassword = await loadSecret({\n region,\n account: 'postgres-password',\n label: 'Postgres password',\n // URL-safe alphabet required — value lands in postgres:// URIs where\n // `+`/`/`/`=` cause parser ambiguity in gotrue/postgrest/storage.\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generatePostgresPassword,\n });\n\n const jwtSecret = await loadSecret({\n region,\n account: 'jwt-secret',\n label: 'JWT signing secret',\n validate: (v) =>\n SAFE_LAUNCHCTL_VALUE_RE.test(v) && v.length >= 32\n ? undefined\n : 'must be ≥32 base64 characters',\n generate: generateJwtSecret,\n });\n\n // Derived JWTs MUST match the current jwtSecret's signature — otherwise\n // a stale anon/service_role token (cached from a previous bootstrap with\n // a different JWT_SECRET) sails past the shape check and breaks every\n // auth call silently. verifySupabaseJwt re-runs the HMAC and rejects on\n // mismatch, triggering regeneration with the current secret.\n const supabaseAnonKey = await loadSecret({\n region,\n account: 'supabase-anon-key',\n label: 'Supabase anon key',\n validate: (v) =>\n SAFE_LAUNCHCTL_VALUE_RE.test(v) && verifySupabaseJwt(v, jwtSecret)\n ? undefined\n : 'must be a base64url JWT signed by the current JWT_SECRET',\n generate: () => signSupabaseJwt({ role: 'anon', secret: jwtSecret }),\n });\n\n const supabaseServiceRoleKey = await loadSecret({\n region,\n account: 'supabase-service-role-key',\n label: 'Supabase service role key',\n validate: (v) =>\n SAFE_LAUNCHCTL_VALUE_RE.test(v) && verifySupabaseJwt(v, jwtSecret)\n ? undefined\n : 'must be a base64url JWT signed by the current JWT_SECRET',\n generate: () => signSupabaseJwt({ role: 'service_role', secret: jwtSecret }),\n });\n\n const dashboardPassword = await loadSecret({\n region,\n account: 'dashboard-password',\n label: 'Supabase Studio dashboard password',\n // URL-safe alphabet required — value lands in basic-auth headers via\n // kong's declarative config. Avoid `+`/`/`/`=` for the same reasons.\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generateDashboardPassword,\n });\n\n return {\n pgsodiumKey,\n tunnelToken,\n postgresPassword,\n jwtSecret,\n supabaseAnonKey,\n supabaseServiceRoleKey,\n dashboardPassword,\n };\n}\n\n// ---- Phase 5b: prompt-service credentials + URL ----\n//\n// Branches on nodeType:\n// `region-with-prompts` — operator owns both ends. Generate all three\n// secrets (DB password + HMAC + admin HMAC); the colocated overlay\n// consumes them via env.\n// `region` — operator's prompt-service is REMOTE. They received an HMAC\n// key from the prompts team; bootstrap prompts them to paste it. The DB\n// password + admin key are skipped (no local DB, no admin access).\nasync function collectPromptServiceSecrets(args: {\n region: string;\n nodeType: NodeType;\n opts: BootstrapOptions;\n}): Promise<string> {\n const { region, nodeType, opts } = args;\n if (nodeType === 'region-with-prompts') {\n await loadSecret({\n region,\n account: 'prompts-db-password',\n label: 'prompt-service Postgres password',\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generatePostgresPassword,\n });\n\n await loadSecret({\n region,\n account: 'prompt-service-api-key',\n label: 'prompt-service HMAC API key',\n // Same URL-safe alphabet as other HMAC keys; embedded in the\n // `<region>:<key>` API_KEYS list and in Authorization headers.\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generateHmacApiKey,\n });\n\n await loadSecret({\n region,\n account: 'prompt-service-admin-api-key',\n label: 'prompt-service admin API key',\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generateHmacApiKey,\n });\n } else {\n // nodeType === 'region': paste-only path. No `generate`, so loadSecret\n // falls through to the operator-paste prompt.\n await loadSecret({\n region,\n account: 'prompt-service-api-key',\n label: 'prompt-service HMAC API key (issued by the prompts team)',\n placeholder: 'paste the region-specific HMAC key',\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n });\n }\n\n // Remote prompt-service URL — only resolved when NOT colocating.\n // For region-with-prompts the overlay hardcodes http://opuspopuli-prompts:3210\n // on the relevant services; no shell env needed.\n const promptServiceUrl =\n nodeType === 'region-with-prompts'\n ? // eslint-disable-next-line sonarjs/no-clear-text-protocols -- in-network (docker) prompt-service URL is legitimately plaintext http; no TLS on the internal bridge\n 'http://opuspopuli-prompts:3210'\n : (opts.promptServiceUrl ?? 'https://prompts.opuspopuli.org');\n if (!SAFE_URL_RE.test(promptServiceUrl)) {\n p.cancel(\n `--prompt-service-url ${JSON.stringify(promptServiceUrl)} contains characters outside the allowed URL set`,\n );\n process.exit(1);\n }\n return promptServiceUrl;\n}\n\n// SUPABASE_URL gets baked into gotrue's API_EXTERNAL_URL and into every\n// magic-link callback gotrue emails to users. localhost is only correct\n// in --local-only mode; for a Tunnel-exposed production node, emailing\n// links pointing at http://localhost:8000 silently breaks signups.\n//\n// Resolution order:\n// --local-only mode → default http://localhost:8000 (no prompt)\n// non-local-only → require --supabase-url OR prompt for the\n// public-facing URL.\nasync function resolveSupabaseUrl(opts: BootstrapOptions): Promise<string> {\n let supabaseUrl: string;\n if (opts.supabaseUrl) {\n supabaseUrl = opts.supabaseUrl;\n } else if (opts.localOnly) {\n supabaseUrl = 'http://localhost:8000';\n } else {\n supabaseUrl = unwrap(\n await p.text({\n message: 'Public-facing Supabase URL (what browsers + microservices use to reach kong)?',\n placeholder: 'https://supabase.civicfeed.tx',\n validate: (v) => {\n if (!v) return 'required';\n return SAFE_URL_RE.test(v)\n ? undefined\n : 'contains characters outside the allowed URL set';\n },\n }),\n );\n }\n if (!SAFE_URL_RE.test(supabaseUrl)) {\n p.cancel(\n `--supabase-url ${JSON.stringify(supabaseUrl)} contains characters outside the allowed URL set`,\n );\n process.exit(1);\n }\n return supabaseUrl;\n}\n\n// Phase 5 aggregate: run all secret-collection sub-phases in order.\nasync function collectSecretsPhase(args: {\n region: string;\n nodeType: NodeType;\n opts: BootstrapOptions;\n}): Promise<CollectedSecrets> {\n const core = await collectCoreSecrets({ region: args.region, opts: args.opts });\n const promptServiceUrl = await collectPromptServiceSecrets(args);\n const supabaseUrl = await resolveSupabaseUrl(args.opts);\n return { ...core, promptServiceUrl, supabaseUrl };\n}\n\n// ---- Phase 6: LaunchAgent ----\nasync function runLaunchAgentPhase(args: {\n opts: BootstrapOptions;\n secrets: CollectedSecrets;\n llmModel: string;\n embeddingModel: string;\n}): Promise<void> {\n const { opts, secrets, llmModel, embeddingModel } = args;\n if (opts.skipLaunchAgent) return;\n\n const laSpin = p.spinner();\n laSpin.start('Writing pgsodium key file + LaunchAgent plist…');\n const la = await setupLaunchAgent({\n pgsodiumKey: secrets.pgsodiumKey,\n ...(secrets.tunnelToken !== undefined ? { tunnelToken: secrets.tunnelToken } : {}),\n llmModel,\n embeddingModel,\n postgresPassword: secrets.postgresPassword,\n jwtSecret: secrets.jwtSecret,\n supabaseAnonKey: secrets.supabaseAnonKey,\n supabaseServiceRoleKey: secrets.supabaseServiceRoleKey,\n dashboardPassword: secrets.dashboardPassword,\n supabaseUrl: secrets.supabaseUrl,\n });\n if (!la.ok) {\n laSpin.stop(pc.red(`✗ LaunchAgent step ${la.step} failed.`));\n p.cancel(la.reason ?? 'LaunchAgent setup failed.');\n process.exit(1);\n }\n laSpin.stop(\n pc.green(\n `✓ LaunchAgent loaded (${la.paths.plistFile})${opts.localOnly ? ' — local-only mode, no TUNNEL_TOKEN set' : ''}.`,\n ),\n );\n}\n\n// ---- Phase 6b: install op-compose wrapper ----\n//\n// launchctl setenv doesn't reach pre-existing shells or sshd children, so\n// operator-driven `docker compose` invocations would hard-fail on the\n// `${VAR:?…}` enforcement in the template even though the values sit safely\n// in Keychain. The wrapper reads Keychain on every invocation and exports\n// the values only into the docker compose subprocess's env.\nasync function installWrapperPhase(args: {\n repoPath: string;\n region: string;\n promptServiceUrl: string;\n}): Promise<void> {\n const { repoPath, region, promptServiceUrl } = args;\n const wrapperSpin = p.spinner();\n wrapperSpin.start('Installing bin/op-compose wrapper…');\n const wrapper = await installOpComposeWrapper({ repoDir: repoPath, region, promptServiceUrl });\n if (!wrapper.ok) {\n wrapperSpin.stop(pc.red('✗ op-compose wrapper install failed.'));\n p.cancel(wrapper.reason ?? 'op-compose wrapper install failed.');\n process.exit(1);\n }\n wrapperSpin.stop(pc.green(`✓ Installed ${wrapper.path} (mode 0755).`));\n}\n\n// ---- Phase 7: ghcr.io login ----\nasync function loginGhcrPhase(): Promise<void> {\n const ghcrSpin = p.spinner();\n ghcrSpin.start('Authenticating Docker to ghcr.io…');\n const ghcr = await loginToGhcr();\n if (!ghcr.ok) {\n ghcrSpin.stop(pc.red('✗ ghcr.io login failed.'));\n p.cancel(ghcr.reason ?? 'ghcr.io login failed.');\n process.exit(1);\n }\n ghcrSpin.stop(pc.green('✓ Logged in to ghcr.io.'));\n}\n\n// ---- Phase 8: Ollama ----\nasync function runOllamaPhase(args: {\n opts: BootstrapOptions;\n embeddingModel: string;\n llmModel: string;\n}): Promise<void> {\n const { opts, embeddingModel, llmModel } = args;\n if (opts.skipOllama) return;\n\n const olSpin = p.spinner();\n olSpin.start(`Pulling + warming Ollama models… (${estimatedPullTime(llmModel)})`);\n let olHealth = await checkOllamaHealth();\n if (!olHealth.reachable) {\n // S5 review fix: try to start the service before bailing. The\n // operator's pretty much always going to want this anyway, and\n // `brew services start` is no-op-safe.\n olSpin.message('Ollama not reachable — running `brew services start ollama`…');\n const start = await startOllamaService();\n if (!start.ok) {\n olSpin.stop(pc.red('✗ Couldn\\'t start Ollama service.'));\n p.cancel(\n `${start.reason ?? 'unknown'} — start it manually with \\`brew services start ollama\\` and re-run with --skip-brew --skip-launch-agent.`,\n );\n process.exit(1);\n }\n // Brew services start returns immediately; the daemon needs a few\n // seconds before /api/tags responds. Quick wait + re-probe.\n await new Promise((res) => setTimeout(res, 3000));\n olHealth = await checkOllamaHealth();\n if (!olHealth.reachable) {\n olSpin.stop(\n pc.yellow('⚠ Ollama service started but daemon not yet answering on :11434.'),\n );\n p.cancel(\n 'Give it another few seconds, then re-run with --skip-brew --skip-launch-agent.',\n );\n process.exit(1);\n }\n }\n const modelReport = await setupModels([embeddingModel, llmModel], (model, status) => {\n olSpin.message(`${status}: ${model}`);\n });\n olSpin.stop(\n modelReport.failed.length === 0\n ? pc.green(\n `✓ ${modelReport.pulled.length} pulled, ${modelReport.alreadyPresent.length} present, ${modelReport.warmed.length} warmed`,\n )\n : pc.yellow(`⚠ ${modelReport.failed.length} model pull(s) failed`),\n );\n const probe = await probeHostDockerInternal();\n if (!probe.ok) {\n p.note(`${pc.yellow('⚠')} ${probe.reason}`, 'Docker host networking');\n }\n}\n\n// Hydrate every `${VAR:?…}`-enforced env var on the compose subprocess.\n// launchctl setenv doesn't reach pre-existing shells or sshd children, so\n// bootstrap's own compose calls would otherwise hard-fail even though every\n// value sits in process scope from the loadSecret pass. Pure builder — kept\n// separate so the env-hydration rule stays unit-testable.\nexport function buildComposeEnv(args: {\n secrets: CollectedSecrets;\n llmModel: string;\n embeddingModel: string;\n}): NodeJS.ProcessEnv {\n const { secrets, llmModel, embeddingModel } = args;\n return {\n PGSODIUM_ROOT_KEY: secrets.pgsodiumKey,\n POSTGRES_PASSWORD: secrets.postgresPassword,\n JWT_SECRET: secrets.jwtSecret,\n SUPABASE_ANON_KEY: secrets.supabaseAnonKey,\n SUPABASE_SERVICE_ROLE_KEY: secrets.supabaseServiceRoleKey,\n DASHBOARD_PASSWORD: secrets.dashboardPassword,\n SUPABASE_URL: secrets.supabaseUrl,\n AUTH_JWT_SECRET: process.env['AUTH_JWT_SECRET'] ?? secrets.jwtSecret,\n ...(secrets.tunnelToken !== undefined ? { TUNNEL_TOKEN: secrets.tunnelToken } : {}),\n ...(llmModel ? { LLM_MODEL: llmModel } : {}),\n ...(embeddingModel ? { EMBEDDINGS_MODEL: embeddingModel } : {}),\n };\n}\n\n// ---- Phase 9 + 10: docker compose pull + up, then health-check loop ----\nasync function runStackPhase(args: {\n opts: BootstrapOptions;\n repoPath: string;\n region: string;\n composeFile: string[];\n secrets: CollectedSecrets;\n llmModel: string;\n embeddingModel: string;\n}): Promise<void> {\n const { opts, repoPath, region, composeFile, secrets, llmModel, embeddingModel } = args;\n\n if (opts.skipStack) {\n const profileFlag = opts.localOnly ? '' : '--profile public ';\n p.outro(\n pc.cyan(\n `Stack-up skipped. Run \\`./bin/op-compose -f ${composeFile.join(' -f ')} ${profileFlag}pull && ./bin/op-compose -f ${composeFile.join(' -f ')} ${profileFlag}up -d\\` from ${repoPath} when ready. (op-compose hydrates Keychain secrets per-invocation; use it instead of raw \\`docker compose\\`.)`,\n ),\n );\n return;\n }\n\n const composeFiles = resolveComposeFiles(repoPath, composeFile);\n const composeEnv = buildComposeEnv({ secrets, llmModel, embeddingModel });\n // In production mode, activate the `public` compose profile so cloudflared\n // starts. In --local-only mode pass no profiles — the template gates\n // cloudflared behind `public`, so an empty profiles array keeps it down.\n const composeOpts = {\n files: composeFiles,\n cwd: repoPath,\n ...(opts.envFile ? { envFile: opts.envFile } : {}),\n profiles: opts.localOnly ? LOCAL_PROFILES : PUBLIC_PROFILES,\n env: composeEnv,\n };\n\n // In --local-only mode, evict any cloudflared container left over from a\n // prior public bootstrap on this Studio. Without this, `compose ps` would\n // still list cloudflared and the health-check loop would demand it reach\n // healthy with no TUNNEL_TOKEN — hanging until timeout. (review S3)\n if (opts.localOnly) {\n const evict = p.spinner();\n evict.start('Evicting any cloudflared from a prior public bootstrap…');\n const rm = await composeRemoveService(\n { ...composeOpts, profiles: PUBLIC_PROFILES },\n 'cloudflared',\n );\n evict.stop(\n rm.ok\n ? pc.green('✓ cloudflared not present (or removed).')\n : pc.yellow(`⚠ cloudflared eviction reported: ${rm.reason ?? 'unknown'} — continuing.`),\n );\n }\n\n const pullSpin = p.spinner();\n pullSpin.start('Pulling images from ghcr.io… (~5–15 min first run, < 1 min cached)');\n const pull = await composePull(composeOpts);\n if (!pull.ok) {\n pullSpin.stop(pc.red('✗ compose pull failed.'));\n p.cancel(pull.reason ?? 'compose pull failed.');\n process.exit(1);\n }\n pullSpin.stop(pc.green('✓ Images pulled.'));\n\n const upSpin = p.spinner();\n upSpin.start('Starting the stack…');\n const up = await composeUp(composeOpts);\n if (!up.ok) {\n upSpin.stop(pc.red('✗ compose up failed.'));\n p.cancel(up.reason ?? 'compose up failed.');\n process.exit(1);\n }\n upSpin.stop(pc.green('✓ Containers started — waiting for healthy…'));\n\n // ---- Phase 10: health-check loop ----\n const healthSpin = p.spinner();\n healthSpin.start('Polling for healthy containers… (every 5s, up to 5 min)');\n const outcome = await waitForHealthy(composeOpts, {\n onPoll: (snaps) => {\n const healthy = snaps.filter((s) => s.health === 'healthy').length;\n const running = snaps.filter((s) => s.state === 'running').length;\n healthSpin.message(`${healthy}/${running} healthy`);\n },\n });\n healthSpin.stop(healthOutcomeHeadline(outcome));\n finishHealthOutcome(outcome, { region, opts, composeFiles });\n}\n\n// Spinner headline for the terminal state of the health loop.\nfunction healthOutcomeHeadline(\n outcome: Awaited<ReturnType<typeof waitForHealthy>>,\n): string {\n switch (outcome.kind) {\n case 'healthy':\n return pc.green(`✓ All ${outcome.snapshots.length} containers healthy.`);\n case 'unhealthy':\n return pc.red(`✗ ${outcome.problem}`);\n case 'timeout':\n return pc.yellow('⚠ Timed out waiting for all containers to report healthy.');\n default:\n return assertNever(outcome) as never;\n }\n}\n\n// Print the outro / diagnostics and exit for the terminal health state.\nfunction finishHealthOutcome(\n outcome: Awaited<ReturnType<typeof waitForHealthy>>,\n args: { region: string; opts: BootstrapOptions; composeFiles: string[] },\n): void {\n const { region, opts, composeFiles } = args;\n switch (outcome.kind) {\n case 'healthy':\n if (opts.localOnly) {\n p.outro(\n pc.cyan(\n [\n `Region ${region} is up locally (no public Cloudflare Tunnel — cloudflared stays down).`,\n `Access from your laptop over Tailscale at this Studio's tailnet IP.`,\n `When you're ready to expose publicly, re-run \\`bootstrap\\` without --local-only.`,\n ].join('\\n'),\n ),\n );\n } else {\n p.outro(\n pc.cyan(\n `Region ${region} is up. Next: verify off-LAN with \\`npx create-op-node verify --domain <your-domain>\\`.`,\n ),\n );\n }\n return;\n case 'unhealthy':\n // Surface the full snapshot table for diagnosis — N10 review fix.\n p.note(\n outcome.snapshots\n .map((s) => ` ${kvHealth(s.health)} ${s.name} (${s.state})`)\n .join('\\n'),\n 'Container state',\n );\n p.cancel(\n `Inspect with \\`docker compose -f ${composeFiles.join(' -f ')} logs\\`. Fix and re-run.`,\n );\n process.exit(1);\n // eslint-disable-next-line no-fallthrough\n case 'timeout':\n p.note(\n outcome.snapshots\n .map((s) => ` ${kvHealth(s.health)} ${s.name} (${s.state})`)\n .join('\\n'),\n 'Container state at timeout',\n );\n // B1 review fix: don't print the success outro. The stack hasn't\n // settled and `verify` would mislead — instruct the operator to\n // re-poll and exit non-zero.\n p.cancel(\n `Re-run \\`create-op-node bootstrap --skip-brew --skip-launch-agent --skip-ollama\\` to skip the already-done phases and poll again once containers settle.`,\n );\n process.exit(1);\n // eslint-disable-next-line no-fallthrough\n default:\n // Exhaustiveness check — adding a new HealthOutcome variant without\n // updating this switch fails the type check.\n assertNever(outcome);\n return;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n/**\n * Resolve the compose-file paths the wizard will pass to docker. Absolute\n * paths pass through; relative paths are resolved against `repoPath`. Pure\n * helper for unit testing — keeps the path-resolution rule in one place.\n */\nexport function resolveComposeFiles(\n repoPath: string,\n composeFile: string[] | undefined,\n): string[] {\n const inputs = composeFile ?? ['docker-compose-prod.yml'];\n return inputs.map((f) => (f.startsWith('/') ? f : join(repoPath, f)));\n}\n\n/**\n * Resolve the Ollama model identifiers from operator flags + defaults.\n * Pure helper — mirrors `resolveComposeFiles` so the flag-resolution rule\n * lives in one place and stays unit-testable.\n *\n * Returned in the order Ollama pulls + warms them: `[embedding, llm]`.\n * The embedding model is typically tiny (~500 MB), so emitting it first\n * gives the operator a visible \"✓ pulled\" milestone before the LLM's\n * potentially-tens-of-gigabytes download dominates the spinner. (S3)\n */\nexport function resolveModels(opts: {\n llmModel?: string;\n embeddingModel?: string;\n}): readonly [embedding: string, llm: string] {\n return [\n opts.embeddingModel ?? DEFAULT_EMBEDDING_MODEL,\n opts.llmModel ?? DEFAULT_LLM_MODEL,\n ] as const;\n}\n\n/** Curated LLM choices shown in the interactive picker. Qwen-only because\n * the Opus Populi platform serves Spanish-speaking civic users and Qwen\n * has the strongest Spanish (and broader multilingual) capability of the\n * open-weight models in this tier. Other Ollama models are still\n * reachable via the \"Other…\" sentinel. Sized per\n * docs/docker-resources.md in the opuspopuli-node template.\n * Order = display order. */\nexport const LLM_MODEL_CHOICES = [\n {\n value: 'qwen2.5:72b',\n label: 'qwen2.5:72b',\n hint: '72B, ~50 GB Ollama RAM. Pre-selected on 96 GB+ Studios. Best Spanish + multilingual quality. Pull ~40 GB, 30–60 min.',\n },\n {\n value: 'qwen2.5:32b',\n label: 'qwen2.5:32b',\n hint: '32B, ~22 GB Ollama RAM. Pre-selected on 48–95 GB Studios. Solid Spanish, faster than 72B. Pull ~20 GB, 15–30 min.',\n },\n {\n value: 'qwen3.5:9b',\n label: 'qwen3.5:9b',\n hint: '9B, ~8 GB Ollama RAM. Pre-selected on smaller Studios (< 48 GB); also the -y / scripted default. Pull ~5 GB, 3–5 min.',\n },\n] as const;\n\nconst OTHER_SENTINEL = '__OTHER__';\n\n/**\n * Pick the LLM that fits the operator's unified-memory budget. Ollama uses\n * roughly the model's parameter count in GB (in q4 quantization), plus a\n * context-window buffer. The Studio also needs RAM for macOS + Docker +\n * the data services. Thresholds below leave 30–40 GB headroom for that.\n *\n * Returns null when `ramGB` is null (sysctl unavailable) so the caller\n * falls back to the platform-default recommendation. (Pure helper —\n * exported for unit tests.)\n */\nexport function recommendLlmModel(ramGB: number | null): string | null {\n if (ramGB === null) return null;\n if (ramGB >= 96) return 'qwen2.5:72b';\n if (ramGB >= 48) return 'qwen2.5:32b';\n return 'qwen3.5:9b';\n}\n\n/**\n * Prompt the operator to pick an LLM model. Skipped when `--yes` is set\n * (returns the conservative default) or when `--llm-model` was passed\n * (caller short-circuits before this is reached).\n *\n * Pre-selects based on the Studio's detected unified memory — 128 GB\n * studios get qwen2.5:72b, 64 GB get qwen2.5:32b, smaller fall back to\n * qwen3.5:9b. When detection fails (non-macOS, sysctl missing), defaults\n * to qwen2.5:72b (the documented platform target).\n *\n * \"Other...\" branches to a text input validated against the same\n * MODEL_NAME_RE the LaunchAgent uses for setenv injection safety.\n */\nasync function selectLlmModel(opts: { yes?: boolean }): Promise<string> {\n if (opts.yes) return DEFAULT_LLM_MODEL;\n\n const ramGB = await detectUnifiedMemoryGB();\n const recommended = recommendLlmModel(ramGB) ?? 'qwen2.5:72b';\n const ramNote = ramGB !== null\n ? `Detected ${ramGB} GB unified memory — pre-selecting ${recommended}.`\n : `Couldn't detect Studio memory — defaulting to ${recommended} (override if your config differs).`;\n\n p.note(ramNote, 'Hardware');\n\n const choice = unwrap(\n await p.select({\n message: 'Choose the LLM model to pull + run',\n initialValue: recommended,\n options: [\n ...LLM_MODEL_CHOICES.map((c) => ({ value: c.value, label: c.label, hint: c.hint })),\n {\n value: OTHER_SENTINEL,\n label: 'Other…',\n hint: 'Specify any Ollama model name (e.g. mistral-small:24b)',\n },\n ],\n }),\n );\n\n if (choice !== OTHER_SENTINEL) return choice;\n\n return unwrap(\n await p.text({\n message: 'Ollama model name',\n placeholder: 'e.g. mistral-small:24b',\n validate: (v) =>\n /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/.test(v ?? '')\n ? undefined\n : 'Letters, digits, `.`, `:`, `_`, `-`, `/` only; must start with alphanumeric',\n }),\n );\n}\n\n/** Rough wall-clock estimate for pulling an Ollama model, based on the\n * size suffix in the tag. Used to populate the Ollama-pull spinner so\n * the operator knows whether to wait or step away. Estimates assume a\n * ~100 Mbps connection; faster networks finish proportionally sooner.\n *\n * Sparse-MoE shapes (`8x22b`) are matched before the plain `Nb` parse\n * because their size suffix in the tag refers to per-expert size, not\n * the total model footprint. */\nexport function estimatedPullTime(model: string): string {\n // Bounded digit runs (real Ollama tags never exceed 3-digit expert counts\n // / 4-digit sizes) so the search can't backtrack super-linearly on a long\n // input.\n if (/\\d{1,3}x\\d{1,3}b/i.test(model)) return '~60+ min for frontier MoE';\n const match = /(\\d{1,4})b\\b/i.exec(model);\n if (!match) return 'time depends on model size';\n const size = Number.parseInt(match[1]!, 10);\n if (size <= 13) return '~3–5 min for ≤ 13B-class';\n if (size <= 35) return '~15–30 min for ~32B-class';\n if (size <= 80) return '~30–60 min for 70B-class';\n return '~60+ min for frontier-class';\n}\n\nfunction kvBool(b: boolean): string {\n return b ? pc.green('on') : pc.yellow('off');\n}\n\nfunction kvFileVault(v: boolean | 'unknown'): string {\n if (v === 'unknown') return pc.dim('unknown');\n return v ? pc.green('on') : pc.dim('off');\n}\n\nfunction kvHealth(h: 'healthy' | 'unhealthy' | 'starting' | 'none'): string {\n switch (h) {\n case 'healthy':\n return pc.green('✓');\n case 'unhealthy':\n return pc.red('✗');\n case 'starting':\n return pc.yellow('…');\n case 'none':\n return pc.dim('-');\n }\n}\n\nfunction repoPathFromLocate(out: LocateOutcome): string | null {\n if (out.kind === 'found' || out.kind === 'cloned') return out.path;\n return null;\n}\n\nfunction handleLocateError(out: LocateOutcome, owner: string, name: string): void {\n switch (out.kind) {\n case 'explicit-not-a-node-repo':\n p.cancel(\n `${out.path} doesn't look like a node repo (missing one of docker-compose-prod.yml / supabase/init/pgsodium_getkey_env.sh). Point --repo-dir at the right place.`,\n );\n return;\n case 'gh-not-installed':\n p.cancel('`gh` not installed — install via `brew install gh` and re-run.');\n return;\n case 'clone-failed':\n p.cancel(\n `Couldn't clone ${owner}/${name}: ${out.reason}. Check repo exists + you have access.`,\n );\n return;\n case 'clone-disallowed':\n p.cancel(\n 'No checked-out node repo found and --no-clone (or similar) was set. Provide --repo-dir.',\n );\n return;\n case 'found':\n case 'cloned':\n // Success cases — handleLocateError shouldn't be called for them, but\n // listing here makes the switch exhaustive so the `never` check below\n // catches any new variant added to LocateOutcome.\n return;\n default: {\n // Compile-time exhaustiveness — if LocateOutcome gains a new variant\n // and isn't handled above, TypeScript fails this assignment.\n assertNever(out);\n return;\n }\n }\n}\n\n/**\n * Verify `gh` is signed in. If not, surface the one-line command to fix and\n * wait for the operator. Doesn't auto-run `gh auth login` since it opens a\n * browser flow and we don't want to fight it. Surfaces `gh auth status`'s\n * stderr so a wrong-account / missing-scope situation isn't silent.\n */\nasync function ensureGhAuth(): Promise<void> {\n const status = await safeExeca('gh', ['auth', 'status']);\n if (status === null) {\n p.cancel('`gh` not on PATH. Install via `brew install gh` and re-run.');\n process.exit(1);\n }\n if (status.exitCode === 0) return;\n\n const detail = (status.stderr || status.stdout).trim();\n p.note(\n [\n '`gh` is not signed in (or signed in to a different account / missing scope).',\n detail ? '' : undefined,\n detail ? pc.dim(detail) : undefined,\n '',\n 'In another shell:',\n '',\n pc.cyan('gh auth login --web'),\n '',\n pc.dim('Then come back and press Enter.'),\n ]\n .filter((l): l is string => typeof l === 'string')\n .join('\\n'),\n 'Manual step',\n );\n unwrap(await p.confirm({ message: 'gh signed in?', initialValue: true }));\n}\n\n/**\n * Tailscale needs an interactive browser signin. We surface the command +\n * wait for confirmation rather than spawning it ourselves — operators run\n * different node setups (start at login vs. on-demand) and we don't want\n * to second-guess. Tailscale is optional; the rest of the bootstrap\n * continues without it (out-of-band SSH is just less convenient).\n */\nasync function promptTailscaleSignin(): Promise<void> {\n const status = await safeExeca('tailscale', ['status']);\n if (status !== null && status.exitCode === 0) return;\n\n p.note(\n [\n 'Tailscale needs to be signed in (or you can skip — Tailscale is',\n 'optional; it provides out-of-band SSH from your laptop. The rest',\n 'of the bootstrap continues without it).',\n '',\n 'In another shell:',\n '',\n pc.cyan('tailscale up'),\n '',\n pc.dim('Accept the device on your tailnet, then come back and press Enter.'),\n ].join('\\n'),\n 'Manual step',\n );\n unwrap(await p.confirm({ message: 'Tailscale signed in (or skipped)?', initialValue: true }));\n}\n\ninterface LoadSecretInput {\n region: string;\n account: SecretAccount;\n /** Friendly name for prompts and notes. */\n label: string;\n /** Placeholder hint shown in the paste prompt. Ignored when `generate` is set. */\n placeholder?: string;\n /** Format check applied to both Keychain reads (so a stale-bad value is\n * treated as missing) and operator paste input. */\n validate: (v: string) => string | undefined;\n /** When set, on Keychain miss / validate-fail, generate a fresh value\n * instead of prompting. Used by `--local-only` for the pgsodium key —\n * no `init` needed.\n *\n * CRITICAL: when `generate` is set we MUST be able to persist the\n * generated value to Keychain. Otherwise the next bootstrap re-run\n * generates a different fresh key and silently destroys any data\n * encrypted under the previous key. So save failure in the generate\n * path is a hard exit, not a warning. (review B1) */\n generate?: () => string;\n}\n\n/**\n * Materialize a secret. Three paths, in order:\n *\n * 1. Keychain hit + valid → return it.\n * 2. Else if `generate` is set → generate fresh, MUST persist (hard fail\n * if save fails), return. The Keychain item is the durable record;\n * losing it later means losing whatever it encrypted.\n * 3. Else → prompt operator to paste, validate, persist with a warning\n * on save failure (the operator can paste again next time).\n *\n * If `validate` rejects an existing Keychain item, we surface the swap\n * explicitly before regenerating/reprompting — destructive overwrites\n * shouldn't be invisible. (review S1)\n */\nasync function loadSecret(input: LoadSecretInput): Promise<string> {\n const coords = { region: input.region, account: input.account };\n const spin = p.spinner();\n spin.start(`Reading ${input.label} from Keychain…`);\n const existing = await readSecret(coords);\n if (existing && input.validate(existing) === undefined) {\n spin.stop(pc.green(`✓ ${input.label} read from Keychain.`));\n return existing;\n }\n\n // Differentiate \"missing\" from \"present-but-bad-format\" — the latter is a\n // destructive replacement so we say so out loud.\n spin.stop(\n existing\n ? pc.yellow(`⚠ ${input.label} in Keychain failed format validation — will replace.`)\n : pc.dim(`· ${input.label} not in Keychain.`),\n );\n\n if (input.generate) {\n const fresh = input.generate();\n const save = await saveSecret(coords, fresh);\n if (!save.written) {\n // Hard fail (review B1) — we generated a fresh value but couldn't\n // persist it. If we continued, the next bootstrap re-run would\n // generate a DIFFERENT fresh value and destroy whatever this one\n // encrypted. Better to bail loudly and let the operator fix the\n // underlying Keychain issue.\n p.cancel(\n `Generated a fresh ${input.label} but couldn't persist it to Keychain: ${save.reason ?? 'unknown'}. ` +\n `Continuing would risk silent key rotation on the next re-run. ` +\n `Resolve the Keychain access (re-grant via Keychain Access.app or check the security CLI) and re-run.`,\n );\n process.exit(1);\n }\n p.note(`${pc.green('✓')} Generated fresh ${input.label} and stored in Keychain.`, 'Keychain');\n return fresh;\n }\n\n const pasted = unwrap(\n await p.password({\n message: `Paste the ${input.label} for region ${input.region}:`,\n validate: (v) => input.validate(v ?? ''),\n }),\n );\n const save = await saveSecret(coords, pasted);\n if (!save.written) {\n // Paste path: warning is fine since the operator can paste again on the\n // next run. The value isn't lost — it's still wherever they pasted from.\n p.note(\n `${pc.yellow('⚠')} Couldn't persist to Keychain: ${save.reason ?? 'unknown'}. You'll need to paste it again next run.`,\n 'Keychain',\n );\n } else {\n p.note(`${pc.green('✓')} Stored ${input.label} in Keychain for re-runs.`, 'Keychain');\n }\n return pasted;\n}\n","/**\n * `create-op-node reset` — reverse of bootstrap. Stops the stack, unloads\n * the LaunchAgent, removes the pgsodium key file. By default the docker\n * volumes (and therefore the database) are PRESERVED. Pass `--wipe-data`\n * for the destructive variant; it requires retyping the region label as\n * confirmation.\n *\n * Reset does NOT touch cloud-side state (Cloudflare resources, the GitHub\n * repo, the TFC workspace). It also leaves the Keychain items in place —\n * delete those manually via Keychain Access or `security delete-generic-\n * password -s org.opuspopuli.<region> -a <account>` if you want a truly\n * clean slate.\n *\n * Accounts to wipe (under service `org.opuspopuli.<region>`):\n * pgsodium-root-key, tunnel-token, postgres-password, jwt-secret,\n * supabase-anon-key, supabase-service-role-key, dashboard-password\n *\n * Wiping pgsodium-root-key permanently destroys every value in\n * supabase_vault for this region. Wiping postgres-password locks you out\n * of the existing database. Don't do either without a backup.\n */\n\nimport { access } from 'node:fs/promises';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport { composeDown, composePs, dockerLogout, GHCR_REGISTRY } from '../lib/docker.js';\nimport { defaultPaths as defaultLaunchAgentPaths, teardownLaunchAgent } from '../lib/launchagent.js';\nimport { locateOrCloneRepo, NODE_REPO_MARKERS } from '../lib/noderepo.js';\nimport { unwrap } from '../lib/prompts.js';\nimport { assertNever } from '../lib/assert.js';\nimport type { ContainerSnapshot } from '../lib/docker.js';\nimport type { LaunchAgentPaths, TeardownResult } from '../lib/launchagent.js';\n\nimport { resolveComposeFiles } from './bootstrap.js';\n\ninterface ResetOptions {\n region?: string;\n owner?: string;\n repoDir?: string;\n composeFile?: string[];\n envFile?: string;\n wipeData?: boolean;\n wipeImages?: boolean;\n removeOrphans?: boolean;\n skipStack?: boolean;\n skipLaunchAgent?: boolean;\n keepKeyFile?: boolean;\n skipDockerLogout?: boolean;\n registry?: string;\n dryRun?: boolean;\n yes?: boolean;\n}\n\nconst REGION_RE = /^[a-z0-9-]{2,32}$/;\n\n/* ------------------------------------------------------------------ *\n * Phase-name constants (review S4 / N7) *\n * *\n * Exported so the CLI wrapper, runReset, and tests all share one *\n * source of truth — renames flow through automatically instead of *\n * drifting between the CLI's spinner setup and the orchestration's *\n * emitted phase names. *\n * ------------------------------------------------------------------ */\n\nexport const RESET_PHASES = {\n STOP_STACK: 'Stop stack',\n LAUNCH_AGENT: 'LaunchAgent',\n DOCKER_LOGOUT: 'docker logout',\n} as const;\n\ntype ResetPhaseName = (typeof RESET_PHASES)[keyof typeof RESET_PHASES];\n\n/* ------------------------------------------------------------------ *\n * Orchestration *\n * ------------------------------------------------------------------ */\n\nexport interface ResetPhase {\n readonly name: string;\n /** `dry-run` is reset-specific — verify uses `skipped` for both\n * \"configured-off\" and \"would-do-but-not-running\" because verify\n * has no preview mode. Reset's preview mode wants a distinct icon. */\n readonly status: 'ok' | 'warn' | 'fail' | 'skipped' | 'dry-run';\n readonly detail: string;\n}\n\nexport interface ResetReport {\n readonly phases: ReadonlyArray<ResetPhase>;\n}\n\nexport interface ResetDeps {\n composeDown: typeof composeDown;\n teardownLaunchAgent: typeof teardownLaunchAgent;\n dockerLogout: typeof dockerLogout;\n /** Notification fan-out — lets the CLI render spinners. */\n onPhase?: (phase: ResetPhase) => void;\n}\n\nexport interface ResetInput {\n /** Set when we have a repo path + compose files. When missing the stack\n * phase is reported as skipped. */\n stack?: {\n repoPath: string;\n composeFiles: string[];\n envFile?: string;\n wipeVolumes: boolean;\n /** When true, also remove all images referenced by the compose files\n * (passes `--rmi all` to compose down). Forces a fresh pull on the\n * next bootstrap — used for \"wipe everything and start over\" loops. */\n wipeImages: boolean;\n removeOrphans: boolean;\n };\n launchAgent?: {\n paths: LaunchAgentPaths;\n keepKeyFile: boolean;\n };\n /** Set when the docker-logout phase should run. The registry value is\n * the argument passed to `docker logout <registry>`. */\n dockerLogout?: { registry: string };\n dryRun: boolean;\n}\n\nconst DEFAULT_DEPS: ResetDeps = {\n composeDown,\n teardownLaunchAgent,\n dockerLogout,\n};\n\n/**\n * Run the three reset phases in reverse-bootstrap order.\n *\n * **Continue-on-failure policy**: each phase runs independently — a\n * `composeDown` failure does NOT short-circuit the LaunchAgent or\n * docker-logout phases. This is intentional: reset is best-effort\n * cleanup, and the operator usually wants the LaunchAgent gone even if\n * the docker daemon is down. Use the returned `ResetReport` to inspect\n * which phases failed.\n *\n * Each phase calls `deps.onPhase` exactly once before runReset moves\n * on, so a CLI consumer can render spinners in lockstep.\n */\nexport async function runReset(input: ResetInput, deps: ResetDeps = DEFAULT_DEPS): Promise<ResetReport> {\n // Each phase computes its ResetPhase; push() records it and fires onPhase\n // in lockstep (same order + timing as the original inline loop) so CLI\n // consumers can render spinners one at a time.\n const phases: ResetPhase[] = [];\n const push = (ph: ResetPhase): void => {\n phases.push(ph);\n deps.onPhase?.(ph);\n };\n\n push(await resetStopStackPhase(input, deps));\n push(await resetLaunchAgentPhase(input, deps));\n push(await resetDockerLogoutPhase(input, deps));\n\n return { phases };\n}\n\n// ---- Phase 1: stop the stack ---------------------------------------\nasync function resetStopStackPhase(input: ResetInput, deps: ResetDeps): Promise<ResetPhase> {\n if (!input.stack) {\n return {\n name: RESET_PHASES.STOP_STACK,\n status: 'skipped',\n detail: '--skip-stack or no repo path resolved',\n };\n }\n if (input.dryRun) {\n return {\n name: RESET_PHASES.STOP_STACK,\n status: 'dry-run',\n detail: `would run: docker compose -f ${input.stack.composeFiles.join(' -f ')} down${input.stack.wipeVolumes ? ' -v' : ''}${input.stack.removeOrphans ? ' --remove-orphans' : ''}${input.stack.wipeImages ? ' --rmi all' : ''}`,\n };\n }\n const result = await deps.composeDown({\n files: input.stack.composeFiles,\n cwd: input.stack.repoPath,\n ...(input.stack.envFile ? { envFile: input.stack.envFile } : {}),\n wipeVolumes: input.stack.wipeVolumes,\n removeOrphans: input.stack.removeOrphans,\n ...(input.stack.wipeImages ? { removeImages: 'all' as const } : {}),\n });\n if (!result.ok) {\n return { name: RESET_PHASES.STOP_STACK, status: 'fail', detail: result.reason ?? 'unknown failure' };\n }\n const bits = [\n input.stack.wipeVolumes ? 'volumes destroyed' : 'containers stopped, volumes preserved',\n input.stack.wipeImages ? 'images removed (next bootstrap will re-pull)' : null,\n ].filter(Boolean);\n return { name: RESET_PHASES.STOP_STACK, status: 'ok', detail: bits.join('; ') };\n}\n\n// ---- Phase 2: LaunchAgent ------------------------------------------\nasync function resetLaunchAgentPhase(input: ResetInput, deps: ResetDeps): Promise<ResetPhase> {\n if (!input.launchAgent) {\n return { name: RESET_PHASES.LAUNCH_AGENT, status: 'skipped', detail: '--skip-launch-agent or no plist found' };\n }\n if (input.dryRun) {\n return {\n name: RESET_PHASES.LAUNCH_AGENT,\n status: 'dry-run',\n detail: `would unload ${input.launchAgent.paths.plistFile}, rm plist${\n input.launchAgent.keepKeyFile ? '' : ' + key file'\n }`,\n };\n }\n const result: TeardownResult = await deps.teardownLaunchAgent(\n input.launchAgent.paths,\n { keepKeyFile: input.launchAgent.keepKeyFile },\n );\n if (!result.ok) {\n const fail = result.steps.find((s) => !s.ok);\n return {\n name: RESET_PHASES.LAUNCH_AGENT,\n status: 'fail',\n detail: `${fail?.step}: ${fail?.reason ?? 'unknown'}`,\n };\n }\n const removed = result.steps.filter((s) => s.step !== 'unload').map((s) => s.step).join(', ');\n return { name: RESET_PHASES.LAUNCH_AGENT, status: 'ok', detail: `unloaded + ${removed}` };\n}\n\n// ---- Phase 3: docker logout ----------------------------------------\nasync function resetDockerLogoutPhase(input: ResetInput, deps: ResetDeps): Promise<ResetPhase> {\n if (!input.dockerLogout) {\n return { name: RESET_PHASES.DOCKER_LOGOUT, status: 'skipped', detail: '--skip-docker-logout' };\n }\n if (input.dryRun) {\n return {\n name: RESET_PHASES.DOCKER_LOGOUT,\n status: 'dry-run',\n detail: `would run: docker logout ${input.dockerLogout.registry}`,\n };\n }\n const result = await deps.dockerLogout(input.dockerLogout.registry);\n if (result.ok) {\n return {\n name: RESET_PHASES.DOCKER_LOGOUT,\n status: 'ok',\n detail: `credentials removed from ${input.dockerLogout.registry}`,\n };\n }\n // See dockerLogout() docstring — older Docker versions return non-zero\n // when not currently logged in. Render as warn so reset doesn't fail\n // overall when the operator wasn't logged in to begin with.\n return { name: RESET_PHASES.DOCKER_LOGOUT, status: 'warn', detail: result.reason ?? 'unknown' };\n}\n\n/* ------------------------------------------------------------------ *\n * CLI wrapper *\n * ------------------------------------------------------------------ */\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction phaseIcon(ph: ResetPhase): string {\n switch (ph.status) {\n case 'ok': return pc.green('✓');\n case 'warn': return pc.yellow('⚠');\n case 'skipped': return pc.dim('·');\n case 'dry-run': return pc.cyan('?');\n case 'fail': return pc.red('✗');\n }\n}\n\nexport const resetCommand = new Command('reset')\n .description(\n 'Reverse the Mac Studio side of bootstrap: stop containers, unload the LaunchAgent, ' +\n 'remove the pgsodium key file. Preserves docker volumes by default — pass --wipe-data ' +\n 'for a full data nuke (requires retyping the region label).',\n )\n .addOption(new Option('--region <slug>', 'Region label (used for --wipe-data confirmation + finding the repo)'))\n .addOption(new Option('--owner <owner>', 'GitHub owner for the node repo').default('OpusPopuli'))\n .addOption(new Option('--repo-dir <path>', 'Explicit path to a checked-out node repo'))\n .addOption(\n new Option(\n '--compose-file <path>',\n 'Repeatable. Compose file relative to repo root. Default: docker-compose-prod.yml',\n ).default(['docker-compose-prod.yml'] as string[]),\n )\n .addOption(new Option('--env-file <path>', 'Compose --env-file. Default: .env.production'))\n .addOption(\n new Option(\n '--wipe-data',\n 'DESTROYS docker volumes (adds -v to `compose down`). Requires retyping the region label as confirmation. Default off — volumes preserved.',\n ).default(false),\n )\n .addOption(\n new Option(\n '--wipe-images',\n 'ALSO remove all docker images referenced by the compose file (adds --rmi all). Forces a fresh pull on next bootstrap. Implies --wipe-data semantics for the iteration loop (\"wipe everything and start over\"). Default off.',\n ).default(false),\n )\n .addOption(\n new Option(\n '--no-remove-orphans',\n 'Do NOT pass --remove-orphans to compose down. Preserves containers from compose files no longer included.',\n ),\n )\n .addOption(new Option('--skip-stack', \"Don't touch docker compose\").default(false))\n .addOption(new Option('--skip-launch-agent', \"Don't touch the LaunchAgent\").default(false))\n .addOption(\n new Option(\n '--keep-key-file',\n \"Preserve the pgsodium key file (only matters when LaunchAgent teardown runs). Useful as belt-and-suspenders backup before a wipe-data run.\",\n ).default(false),\n )\n .addOption(new Option('--skip-docker-logout', \"Don't run `docker logout`\").default(false))\n .addOption(new Option('--registry <registry>', 'Registry to log out of').default(GHCR_REGISTRY))\n .addOption(new Option('--dry-run', 'Show what would happen without acting').default(false))\n .addOption(new Option('-y, --yes', 'Skip non-destructive confirmations (wipe still confirms)').default(false))\n .action(async (opts: ResetOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node reset ')));\n\n const wipeImages = opts.wipeImages ?? false;\n // --wipe-images implies --wipe-data — \"wipe everything\" semantics: no\n // point keeping data tied to images that are about to disappear.\n const wipeData = (opts.wipeData ?? false) || wipeImages;\n const removeOrphans = opts.removeOrphans ?? true; // commander --no-remove-orphans sets this to false\n\n const region = await resolveResetRegion(opts);\n const owner = opts.owner ?? 'OpusPopuli';\n const repoName = `opuspopuli-node-${region}`;\n\n const launchAgentPaths = defaultLaunchAgentPaths();\n const plistExists = await fileExists(launchAgentPaths.plistFile);\n const keyFileExists = await fileExists(launchAgentPaths.keyFile);\n const { repoPath, stackSkipReason } = await locateResetRepo(opts, owner, repoName);\n\n const runningContainers = repoPath\n ? await composePs({\n files: resolveComposeFiles(repoPath, opts.composeFile),\n cwd: repoPath,\n ...(opts.envFile ? { envFile: opts.envFile } : {}),\n })\n : null;\n\n renderSnapshotNote({\n region,\n repoPath,\n stackSkipReason,\n runningContainers,\n plistExists,\n keyFileExists,\n launchAgentPaths,\n opts,\n wipeData,\n wipeImages,\n });\n\n await confirmReset({ opts, region, wipeData });\n\n const input = buildResetInput({\n opts,\n repoPath,\n plistExists,\n launchAgentPaths,\n wipeData,\n wipeImages,\n removeOrphans,\n });\n await runResetWithSpinners({ opts, region, wipeData, input });\n });\n\n// ----------------------------------------------------------------------------\n// Reset command phases\n// ----------------------------------------------------------------------------\n// The action delegates to these so no single function exceeds the\n// cognitive-complexity budget. Behavior-preserving: interactive prompts,\n// spinners, and process.exit calls are relocated verbatim.\n\n// ---- Region (needed for confirmation phrase + repo discovery) ----\nasync function resolveResetRegion(opts: ResetOptions): Promise<string> {\n const region = opts.region\n ? opts.region\n : unwrap(\n await p.text({\n message: 'Region label (the slug used during init — e.g. us-ca)?',\n placeholder: 'us-ca',\n validate: (v) =>\n REGION_RE.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens; 2–32 chars',\n }),\n );\n if (!REGION_RE.test(region)) {\n p.cancel(`--region ${JSON.stringify(region)} is not a valid region slug.`);\n process.exit(2);\n }\n return region;\n}\n\n// ---- Locate the node repo (or explain why the stack phase is skipped) ----\n// Exhaustive: every LocateOutcome variant has a deliberate path —\n// operator-supplied --repo-dir mismatch is HARD-fail, ambient cwd miss is\n// SOFT-skip with a visible reason. (review B1)\nasync function locateResetRepo(\n opts: ResetOptions,\n owner: string,\n repoName: string,\n): Promise<{ repoPath?: string; stackSkipReason?: string }> {\n if (opts.skipStack) {\n return { stackSkipReason: '--skip-stack' };\n }\n const located = await locateOrCloneRepo({\n owner,\n name: repoName,\n cwd: process.cwd(),\n allowClone: false,\n ...(opts.repoDir ? { explicit: opts.repoDir } : {}),\n });\n switch (located.kind) {\n case 'found':\n return { repoPath: located.path };\n case 'explicit-not-a-node-repo':\n p.cancel(\n `--repo-dir ${JSON.stringify(located.path)} doesn't look like a node repo ` +\n `(missing one of: ${NODE_REPO_MARKERS.join(', ')}). ` +\n `Verify the path or drop --repo-dir to let reset search the cwd.`,\n );\n return process.exit(2);\n case 'clone-disallowed':\n return { stackSkipReason: `no checkout found at ${process.cwd()}; pass --repo-dir to target one` };\n case 'cloned':\n case 'gh-not-installed':\n case 'clone-failed':\n // Should not be reachable — allowClone: false above. Treat as\n // soft-skip if it ever happens.\n return {\n stackSkipReason: `unexpected outcome ${located.kind} from locateOrCloneRepo with allowClone=false`,\n };\n default:\n return assertNever(located) as never;\n }\n}\n\n// ---- Snapshot note: what's currently present ----\nfunction renderSnapshotNote(args: {\n region: string;\n repoPath: string | undefined;\n stackSkipReason: string | undefined;\n runningContainers: ContainerSnapshot[] | null;\n plistExists: boolean;\n keyFileExists: boolean;\n launchAgentPaths: LaunchAgentPaths;\n opts: ResetOptions;\n wipeData: boolean;\n wipeImages: boolean;\n}): void {\n const {\n region,\n repoPath,\n stackSkipReason,\n runningContainers,\n plistExists,\n keyFileExists,\n launchAgentPaths,\n opts,\n wipeData,\n wipeImages,\n } = args;\n\n let runningContainersLabel: string;\n if (runningContainers === null) {\n runningContainersLabel = pc.dim('unknown');\n } else if (runningContainers.length === 0) {\n runningContainersLabel = pc.dim('none');\n } else {\n runningContainersLabel = pc.cyan(`${runningContainers.length} listed by compose ps`);\n }\n\n p.note(\n [\n `Region: ${pc.cyan(region)}`,\n `Repo path: ${\n repoPath\n ? pc.cyan(repoPath)\n : pc.dim(`not used (${stackSkipReason ?? 'no repo path resolved'})`)\n }`,\n `Running containers: ${runningContainersLabel}`,\n `LaunchAgent plist: ${plistExists ? pc.cyan(launchAgentPaths.plistFile) : pc.dim('not present')}`,\n `pgsodium key file: ${keyFileExists ? pc.cyan(launchAgentPaths.keyFile) : pc.dim('not present')}`,\n `Registry to log out: ${pc.cyan(opts.registry ?? GHCR_REGISTRY)}`,\n `Volume policy: ${wipeData ? pc.red('WIPE') : pc.green('preserve (default)')}`,\n `Image policy: ${wipeImages ? pc.red('WIPE (re-pull on next bootstrap)') : pc.green('keep (default)')}`,\n `Dry run: ${opts.dryRun ? pc.yellow('yes') : pc.dim('no')}`,\n ].join('\\n'),\n 'Snapshot',\n );\n}\n\n// ---- Confirmation gates ----\n// wipe-data requires retyping the region label (modeled on `terraform\n// destroy` — the friction is the point, review B2); otherwise a plain\n// proceed confirm unless --yes / --dry-run.\nasync function confirmReset(args: {\n opts: ResetOptions;\n region: string;\n wipeData: boolean;\n}): Promise<void> {\n const { opts, region, wipeData } = args;\n if (wipeData && !opts.dryRun) {\n unwrap(\n await p.text({\n message: pc.red(`Type the region label to confirm WIPING all volumes (the slug you'd use with --region):`),\n validate: (v) => (v === region ? undefined : `must match the region label exactly`),\n }),\n );\n return;\n }\n if (!opts.dryRun && !opts.yes) {\n const cont = unwrap(\n await p.confirm({\n message: 'Proceed with reset? (volumes will be preserved)',\n initialValue: true,\n }),\n );\n if (!cont) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n }\n}\n\n// ---- Build the runReset input from the resolved snapshot + flags ----\nexport function buildResetInput(args: {\n opts: ResetOptions;\n repoPath: string | undefined;\n plistExists: boolean;\n launchAgentPaths: LaunchAgentPaths;\n wipeData: boolean;\n wipeImages: boolean;\n removeOrphans: boolean;\n}): ResetInput {\n const { opts, repoPath, plistExists, launchAgentPaths, wipeData, wipeImages, removeOrphans } = args;\n const stack = repoPath\n ? {\n repoPath,\n composeFiles: resolveComposeFiles(repoPath, opts.composeFile),\n wipeVolumes: wipeData,\n wipeImages,\n removeOrphans,\n ...(opts.envFile ? { envFile: opts.envFile } : {}),\n }\n : undefined;\n const launchAgent =\n plistExists && !opts.skipLaunchAgent\n ? {\n paths: launchAgentPaths,\n keepKeyFile: opts.keepKeyFile ?? false,\n }\n : undefined;\n const dockerLogoutInput = !opts.skipDockerLogout\n ? { registry: opts.registry ?? GHCR_REGISTRY }\n : undefined;\n return {\n ...(stack ? { stack } : {}),\n ...(launchAgent ? { launchAgent } : {}),\n ...(dockerLogoutInput ? { dockerLogout: dockerLogoutInput } : {}),\n dryRun: opts.dryRun ?? false,\n };\n}\n\n// ---- Run runReset with a spinner per acting phase, then report ----\nasync function runResetWithSpinners(args: {\n opts: ResetOptions;\n region: string;\n wipeData: boolean;\n input: ResetInput;\n}): Promise<void> {\n const { opts, region, wipeData, input } = args;\n\n // Start a spinner per phase that will actually act (not skipped, not\n // dry-run). The phase name comes from RESET_PHASES so it can't drift from\n // runReset's emitted names. (review S4 / N7)\n const phaseSpins = new Map<ResetPhaseName, ReturnType<typeof p.spinner>>();\n const actingPhases: ResetPhaseName[] = [];\n if (input.stack && !input.dryRun) actingPhases.push(RESET_PHASES.STOP_STACK);\n if (input.launchAgent && !input.dryRun) actingPhases.push(RESET_PHASES.LAUNCH_AGENT);\n if (input.dockerLogout && !input.dryRun) actingPhases.push(RESET_PHASES.DOCKER_LOGOUT);\n for (const name of actingPhases) {\n const s = p.spinner();\n s.start(`${name}…`);\n phaseSpins.set(name, s);\n }\n\n const renderPhase = (ph: ResetPhase): void => {\n const spin = phaseSpins.get(ph.name as ResetPhaseName);\n const line = `${phaseIcon(ph)} ${ph.name}: ${pc.dim(ph.detail)}`;\n if (spin) {\n spin.stop(line);\n phaseSpins.delete(ph.name as ResetPhaseName);\n } else {\n p.log.info(line);\n }\n };\n\n const report = await runReset(input, { ...DEFAULT_DEPS, onPhase: renderPhase });\n\n // Belt-and-suspenders: stop any orphan spinners runReset didn't fire\n // onPhase for. Shouldn't happen given the constants-based wiring above.\n for (const [, spin] of phaseSpins) spin.stop(pc.dim('— skipped'));\n\n reportResetOutcome({ report, opts, wipeData, region });\n}\n\n// ---- Final outro / exit code ----\nfunction reportResetOutcome(args: {\n report: ResetReport;\n opts: ResetOptions;\n wipeData: boolean;\n region: string;\n}): void {\n const { report, opts, wipeData, region } = args;\n const failed = report.phases.filter((ph) => ph.status === 'fail').length;\n if (failed > 0) {\n p.outro(pc.red(`${failed} step${failed === 1 ? '' : 's'} failed.`));\n process.exit(1);\n }\n if (opts.dryRun) {\n p.outro(pc.cyan('Dry run complete. Re-run without --dry-run to apply.'));\n return;\n }\n p.outro(\n pc.green(\n wipeData\n ? `Reset complete — volumes wiped. Re-run \\`create-op-node bootstrap --region ${region}\\` to start fresh.`\n : `Reset complete — volumes preserved. Re-run \\`create-op-node bootstrap --region ${region}\\` to bring the stack back up.`,\n ),\n );\n}\n","/**\n * `cosign verify` wrapper for the verify wizard.\n *\n * Keyless verification path: cosign maps the image to a Fulcio-issued\n * certificate, checks the certificate's identity (GitHub Actions workflow URL)\n * + OIDC issuer, AND consults the Rekor transparency log (cosign default,\n * `rekor.sigstore.dev`) for an inclusion proof. So a passing verify means\n * the image was signed by the expected workflow AND that signing event is\n * publicly logged.\n *\n * If `cosign` isn't on PATH we report it as a skip rather than a failure —\n * verify can still pass without it (TLS + GraphQL probes are load-bearing).\n */\n\nimport { safeExeca } from './exec.js';\n\nexport const COSIGN_OIDC_ISSUER = 'https://token.actions.githubusercontent.com';\n\nexport interface CosignVerifyInput {\n image: string;\n /** Glob/regex passed as `--certificate-identity-regexp`. Defaults to the\n * publishing workflow path in the opuspopuli-node template. */\n certificateIdentityRegexp?: string;\n /** OIDC issuer that signed the image. Defaults to GitHub Actions. */\n certificateOidcIssuer?: string;\n}\n\nexport type CosignVerifyResult =\n | { ok: true; output: string }\n | { ok: false; skipped: true; reason: string }\n | { ok: false; skipped: false; reason: string };\n\nexport const DEFAULT_IDENTITY_REGEXP =\n '^https://github\\\\.com/OpusPopuli/opuspopuli/\\\\.github/workflows/.*$';\n\n/**\n * Verify a single OCI image's cosign signature against the GitHub Actions\n * OIDC issuer. Returns one of three shapes:\n *\n * - `{ ok: true }` — signature valid.\n * - `{ ok: false, skipped: true }` — cosign binary not on PATH; caller\n * should render this as a warning, not a failure.\n * - `{ ok: false, skipped: false }` — cosign ran and rejected the image.\n */\nexport async function cosignVerifyImage(input: CosignVerifyInput): Promise<CosignVerifyResult> {\n const idRegex = input.certificateIdentityRegexp ?? DEFAULT_IDENTITY_REGEXP;\n const issuer = input.certificateOidcIssuer ?? COSIGN_OIDC_ISSUER;\n\n const res = await safeExeca('cosign', [\n 'verify',\n '--certificate-identity-regexp',\n idRegex,\n '--certificate-oidc-issuer',\n issuer,\n input.image,\n ]);\n\n if (res === null) {\n return {\n ok: false,\n skipped: true,\n reason: '`cosign` not on PATH (install with `brew install cosign` and rerun to enable signature checks)',\n };\n }\n if (res.exitCode !== 0) {\n return {\n ok: false,\n skipped: false,\n reason: `cosign verify ${input.image} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true, output: res.stdout || res.stderr };\n}\n","/**\n * HTTP probes for `verify`. Two helpers:\n *\n * - `httpProbe` — GET against a URL, return status + truncated body.\n * Used for the `/health` endpoint check.\n * - `graphqlProbe` — POST `{ query: \"{ __typename }\" }`, parse the\n * envelope, confirm it looks like a GraphQL response\n * rather than (say) an HTML error page from the proxy.\n *\n * Both swallow network errors into a `{ ok: false, reason }` so the verify\n * wizard reports them as a phase failure instead of crashing.\n */\n\nimport { BODY_PREVIEW_MAX, VERIFY_NETWORK_TIMEOUT_MS } from './constants.js';\n\n/** Spec-preferred GraphQL response media type. Apollo Gateway accepts plain\n * `application/json` too, but stricter or future implementations may not —\n * send both. (graphql-over-http spec) */\nconst GRAPHQL_ACCEPT = 'application/graphql-response+json, application/json';\n\n/** Slice cap when reading a response body for diagnostics. Streaming would\n * let us bail at this byte count too; for now we read the whole text and\n * cap on display, which is fine for the small bodies these endpoints\n * return. If a pathological server returns gigabytes, the AbortController\n * will fire first. */\nasync function readBodyCapped(res: Response): Promise<string> {\n const text = await res.text();\n return text.slice(0, BODY_PREVIEW_MAX);\n}\n\nexport interface HttpProbeOk {\n ok: true;\n status: number;\n /** First N chars of the response body — useful for surface-level diagnostics\n * (\"got HTML when expecting JSON\"). Capped at BODY_PREVIEW_MAX. */\n bodyPreview: string;\n}\n\nexport interface HttpProbeFailed {\n ok: false;\n reason: string;\n /** Set when we got a response back but the status was unexpected; the\n * wizard renders this in the failure block. */\n status?: number;\n}\n\nexport type HttpProbeResult = HttpProbeOk | HttpProbeFailed;\n\nexport interface HttpProbeInput {\n url: string;\n /** Default 200. Set to e.g. 204 if you're probing a no-content endpoint. */\n expectedStatus?: number;\n timeoutMs?: number;\n /** Injectable for tests. Defaults to globalThis.fetch. */\n fetchImpl?: typeof fetch;\n}\n\nexport async function httpProbe(input: HttpProbeInput): Promise<HttpProbeResult> {\n const expected = input.expectedStatus ?? 200;\n const timeoutMs = input.timeoutMs ?? VERIFY_NETWORK_TIMEOUT_MS;\n const fetchImpl = input.fetchImpl ?? fetch;\n\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), timeoutMs);\n try {\n const res = await fetchImpl(input.url, { method: 'GET', signal: ctrl.signal });\n const bodyPreview = await readBodyCapped(res);\n if (res.status !== expected) {\n // (review N5) Surface the body on a status mismatch the same way\n // graphqlProbe does, so the operator can see the actual error page.\n return {\n ok: false,\n status: res.status,\n reason: bodyPreview\n ? `expected HTTP ${expected}, got ${res.status}: ${bodyPreview}`\n : `expected HTTP ${expected}, got ${res.status}`,\n };\n }\n return { ok: true, status: res.status, bodyPreview };\n } catch (err) {\n const reason =\n (err as Error).name === 'AbortError'\n ? `GET ${input.url} timed out after ${timeoutMs}ms`\n : `GET ${input.url} failed: ${(err as Error).message}`;\n return { ok: false, reason };\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport interface GraphqlProbeOk {\n ok: true;\n /** The value of `data.__typename` from the response envelope. Usually\n * \"Query\" on a healthy Apollo Gateway. */\n typename: string;\n}\n\nexport interface GraphqlProbeFailed {\n ok: false;\n reason: string;\n status?: number;\n}\n\nexport type GraphqlProbeResult = GraphqlProbeOk | GraphqlProbeFailed;\n\nexport interface GraphqlProbeInput {\n url: string;\n timeoutMs?: number;\n fetchImpl?: typeof fetch;\n}\n\n/**\n * POST `{ \"query\": \"{ __typename }\" }` and confirm the envelope shape. Apollo\n * Federation gateways respond with `{ data: { __typename: \"Query\" } }` for\n * this; a misconfigured proxy or a 404 from a wrong path returns HTML or a\n * JSON error envelope that we surface as a failure reason.\n */\nexport async function graphqlProbe(input: GraphqlProbeInput): Promise<GraphqlProbeResult> {\n const timeoutMs = input.timeoutMs ?? VERIFY_NETWORK_TIMEOUT_MS;\n const fetchImpl = input.fetchImpl ?? fetch;\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), timeoutMs);\n try {\n const res = await fetchImpl(input.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Accept: GRAPHQL_ACCEPT },\n body: JSON.stringify({ query: '{ __typename }' }),\n signal: ctrl.signal,\n });\n const text = await readBodyCapped(res);\n if (res.status !== 200) {\n return {\n ok: false,\n status: res.status,\n reason: `expected HTTP 200, got ${res.status}: ${text}`,\n };\n }\n let envelope: unknown;\n try {\n envelope = JSON.parse(text);\n } catch {\n return {\n ok: false,\n status: res.status,\n reason: `response was not JSON: ${text}`,\n };\n }\n const data = (envelope as { data?: { __typename?: unknown } }).data;\n const typename = data?.__typename;\n if (typeof typename !== 'string') {\n return {\n ok: false,\n status: res.status,\n reason: `response missing { data: { __typename: string } }: ${text}`,\n };\n }\n return { ok: true, typename };\n } catch (err) {\n const reason =\n (err as Error).name === 'AbortError'\n ? `POST ${input.url} timed out after ${timeoutMs}ms`\n : `POST ${input.url} failed: ${(err as Error).message}`;\n return { ok: false, reason };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Off-LAN TLS handshake probe. Verify uses this to confirm `api.<domain>`\n * actually negotiates a real, in-date cert from anywhere on the internet\n * before bothering with HTTP probes.\n *\n * We use `tls.connect` rather than just letting fetch do its thing because\n * fetch swallows cert-chain details — we want to surface days-to-expiry so\n * the operator can see \"TLS green, but cert expires in 12 days\" as a soft\n * warning, not just \"fetch failed.\"\n */\n\nimport * as tls from 'node:tls';\n\nimport { VERIFY_NETWORK_TIMEOUT_MS } from './constants.js';\n\nexport interface TlsHandshakeOk {\n ok: true;\n /** Negotiated subject CN (from the leaf cert). */\n subject: string;\n /** Issuer organization (e.g. \"Let's Encrypt\"). */\n issuer: string;\n /** Whole days until the leaf cert's `notAfter` field. Negative when the\n * cert is already expired but the server still happened to return one. */\n daysToExpiry: number;\n}\n\nexport interface TlsHandshakeFailed {\n ok: false;\n reason: string;\n}\n\nexport type TlsHandshakeResult = TlsHandshakeOk | TlsHandshakeFailed;\n\nexport interface TlsProbeInput {\n host: string;\n port?: number;\n /** Socket-level timeout in milliseconds. Anything that doesn't ALPN/SNI\n * within this window is reported as a timeout reason, not a hang. */\n timeoutMs?: number;\n /** Injectable for tests. Defaults to the real `tls.connect`. */\n connect?: typeof tls.connect;\n /** Reference time for daysToExpiry math. Injectable for tests so the\n * expected value doesn't drift. */\n now?: Date;\n}\n\n/** Cert subject/issuer fields can be string or string[] (multi-valued RDNs).\n * We render the first item for display. */\nfunction first(v: string | string[] | undefined): string | undefined {\n if (v === undefined) return undefined;\n return Array.isArray(v) ? v[0] : v;\n}\n\n/**\n * One-shot TLS handshake. Returns the result rather than throwing — the\n * verify wizard wants to fold every failure into a single report.\n */\nexport function tlsHandshake(input: TlsProbeInput): Promise<TlsHandshakeResult> {\n const host = input.host;\n const port = input.port ?? 443;\n const timeoutMs = input.timeoutMs ?? VERIFY_NETWORK_TIMEOUT_MS;\n const connect = input.connect ?? tls.connect;\n const now = input.now ?? new Date();\n\n return new Promise<TlsHandshakeResult>((resolve) => {\n let socket: tls.TLSSocket;\n let settled = false;\n const settle = (r: TlsHandshakeResult): void => {\n if (settled) return;\n settled = true;\n socket?.destroy();\n resolve(r);\n };\n\n // `tls.connect` is async by contract, but the injectable `connect` plus\n // certain pathological options (bad servername length, etc.) can throw\n // synchronously. Convert that into a failure result so callers keep\n // seeing the discriminated union instead of a rejection. (review B2)\n try {\n socket = connect({\n host,\n port,\n servername: host,\n timeout: timeoutMs,\n });\n } catch (err) {\n settle({ ok: false, reason: `tls.connect to ${host}:${port} threw: ${(err as Error).message}` });\n return;\n }\n\n socket.once('secureConnect', () => {\n const cert = socket.getPeerCertificate(false);\n if (!cert || Object.keys(cert).length === 0) {\n settle({ ok: false, reason: 'TLS connected but peer presented no certificate' });\n return;\n }\n const notAfter = new Date(cert.valid_to);\n if (Number.isNaN(notAfter.getTime())) {\n settle({ ok: false, reason: `cert presented an unparseable notAfter: ${cert.valid_to}` });\n return;\n }\n const msPerDay = 1000 * 60 * 60 * 24;\n const daysToExpiry = Math.floor((notAfter.getTime() - now.getTime()) / msPerDay);\n const subject = first(cert.subject?.CN) ?? '<no CN>';\n const issuer = first(cert.issuer?.O) ?? first(cert.issuer?.CN) ?? '<no issuer>';\n settle({ ok: true, subject, issuer, daysToExpiry });\n });\n\n socket.once('timeout', () => {\n settle({ ok: false, reason: `TLS handshake to ${host}:${port} timed out after ${timeoutMs}ms` });\n });\n\n socket.once('error', (err) => {\n settle({ ok: false, reason: `TLS handshake to ${host}:${port} failed: ${err.message}` });\n });\n });\n}\n","import { readFileSync } from 'node:fs';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport { tunnelStatus, type TunnelStatusInput, type TunnelStatusResult } from '../lib/cloudflare.js';\nimport { cosignVerifyImage, type CosignVerifyInput, type CosignVerifyResult } from '../lib/cosign.js';\nimport { graphqlProbe, httpProbe, type GraphqlProbeInput, type GraphqlProbeResult, type HttpProbeInput, type HttpProbeResult } from '../lib/http.js';\nimport { unwrap } from '../lib/prompts.js';\nimport { tlsHandshake, type TlsProbeInput, type TlsHandshakeResult } from '../lib/tls.js';\n\ninterface VerifyOptions {\n domain?: string;\n apiHost?: string;\n cfToken?: string;\n cfTokenFile?: string;\n cfAccountId?: string;\n tunnelId?: string;\n image?: string[];\n certWarnDays?: string;\n showSkipped?: boolean;\n}\n\nconst DOMAIN_RE = /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i;\n\nexport interface VerifyPhase {\n readonly name: string;\n readonly status: 'ok' | 'warn' | 'fail' | 'skipped';\n readonly detail: string;\n}\n\nexport interface VerifyReport {\n readonly phases: ReadonlyArray<VerifyPhase>;\n}\n\nexport function summarize(report: VerifyReport): { ok: boolean; failed: number; warned: number } {\n let failed = 0;\n let warned = 0;\n for (const ph of report.phases) {\n if (ph.status === 'fail') failed++;\n if (ph.status === 'warn') warned++;\n }\n return { ok: failed === 0, failed, warned };\n}\n\nfunction formatExpiry(days: number): string {\n if (days < 0) return `expired ${-days}d ago`;\n if (days === 0) return 'expires today';\n return `${days}d to expiry`;\n}\n\n/* ------------------------------------------------------------------ *\n * Injectable orchestration (review S3) *\n * ------------------------------------------------------------------ */\n\nexport interface VerifyDeps {\n tls: (input: TlsProbeInput) => Promise<TlsHandshakeResult>;\n http: (input: HttpProbeInput) => Promise<HttpProbeResult>;\n graphql: (input: GraphqlProbeInput) => Promise<GraphqlProbeResult>;\n tunnel: (input: TunnelStatusInput) => Promise<TunnelStatusResult>;\n cosign: (input: CosignVerifyInput) => Promise<CosignVerifyResult>;\n /** Called once per phase as it resolves — lets the CLI render spinners.\n * Pass a no-op for tests that just want the report. */\n onPhase?: (phase: VerifyPhase) => void;\n}\n\nexport interface VerifyInput {\n apiHost: string;\n certWarnDays: number;\n /** All three OR none. Mid-set is treated as a `warn` phase by runVerify. */\n cf?: {\n token?: string;\n accountId?: string;\n tunnelId?: string;\n };\n images: ReadonlyArray<string>;\n}\n\nconst DEFAULT_DEPS: VerifyDeps = {\n tls: tlsHandshake,\n http: httpProbe,\n graphql: graphqlProbe,\n tunnel: tunnelStatus,\n cosign: cosignVerifyImage,\n};\n\ntype PushVerifyPhase = (ph: VerifyPhase) => void;\n\nexport async function runVerify(input: VerifyInput, deps: VerifyDeps = DEFAULT_DEPS): Promise<VerifyReport> {\n // Each phase pushes its result(s) via push(), which records + fires onPhase\n // in lockstep. push is threaded into the phase helpers (rather than having\n // them return arrays) so the cosign loop keeps firing onPhase per-image,\n // interleaved with its async calls — exactly as the original inline loop.\n const phases: VerifyPhase[] = [];\n const push: PushVerifyPhase = (ph) => {\n phases.push(ph);\n deps.onPhase?.(ph);\n };\n\n await verifyTlsPhase(input, deps, push);\n await verifyHealthPhase(input, deps, push);\n await verifyGraphqlPhase(input, deps, push);\n await verifyCloudflarePhase(input, deps, push);\n await verifyCosignPhase(input, deps, push);\n\n return { phases };\n}\n\n// ---- Phase 1: TLS handshake ---------------------------------------\nasync function verifyTlsPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const tls = await deps.tls({ host: input.apiHost });\n if (!tls.ok) {\n push({ name: 'TLS handshake', status: 'fail', detail: tls.reason });\n return;\n }\n const line = `subject=${tls.subject}, issuer=${tls.issuer}, ${formatExpiry(tls.daysToExpiry)}`;\n if (tls.daysToExpiry < input.certWarnDays) {\n push({\n name: 'TLS handshake',\n status: 'warn',\n detail: tls.daysToExpiry < 0 ? line : `${line} (< warn threshold ${input.certWarnDays}d)`,\n });\n return;\n }\n push({ name: 'TLS handshake', status: 'ok', detail: line });\n}\n\n// ---- Phase 2: GET /health ------------------------------------------\nasync function verifyHealthPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const health = await deps.http({ url: `https://${input.apiHost}/health` });\n if (health.ok) {\n push({ name: 'GET /health', status: 'ok', detail: `HTTP ${health.status}` });\n } else {\n push({ name: 'GET /health', status: 'fail', detail: health.reason });\n }\n}\n\n// ---- Phase 3: GraphQL { __typename } -------------------------------\nasync function verifyGraphqlPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const gql = await deps.graphql({ url: `https://${input.apiHost}/api` });\n if (gql.ok) {\n push({ name: 'GraphQL { __typename }', status: 'ok', detail: `typename=${gql.typename}` });\n } else {\n push({ name: 'GraphQL { __typename }', status: 'fail', detail: gql.reason });\n }\n}\n\n// ---- Phase 4: Cloudflare Tunnel status (optional) ------------------\nasync function verifyCloudflarePhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const cfFields: ReadonlyArray<[string, string | undefined]> = [\n ['--cf-token', input.cf?.token],\n ['--cf-account-id', input.cf?.accountId],\n ['--tunnel-id', input.cf?.tunnelId],\n ];\n const cfSet = cfFields.filter(([, v]) => v !== undefined && v !== '');\n if (cfSet.length === 0) {\n push({\n name: 'Cloudflare Tunnel',\n status: 'skipped',\n detail: 'pass --cf-token + --cf-account-id + --tunnel-id to enable',\n });\n return;\n }\n if (cfSet.length < cfFields.length) {\n // (review S1) Partial config is operator-hostile — they almost certainly\n // meant to enable the check. Warn so the missing flag names are visible.\n const missing = cfFields.filter(([, v]) => v === undefined || v === '').map(([name]) => name).join(', ');\n push({\n name: 'Cloudflare Tunnel',\n status: 'warn',\n detail: `partial CF config — missing ${missing}; check skipped`,\n });\n return;\n }\n const tun = await deps.tunnel({\n token: input.cf!.token!,\n accountId: input.cf!.accountId!,\n tunnelId: input.cf!.tunnelId!,\n });\n if (!tun.ok) {\n push({ name: 'Cloudflare Tunnel', status: 'fail', detail: tun.reason });\n } else if (tun.connections === 0) {\n push({\n name: 'Cloudflare Tunnel',\n status: 'warn',\n detail: `status=${tun.status}, 0 connections — cloudflared on the Studio appears offline`,\n });\n } else {\n push({\n name: 'Cloudflare Tunnel',\n status: 'ok',\n detail: `${tun.connections} connections, status=${tun.status}`,\n });\n }\n}\n\n// ---- Phase 5: cosign signature check (optional) --------------------\nasync function verifyCosignPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n if (input.images.length === 0) {\n push({\n name: 'cosign verify',\n status: 'skipped',\n detail: 'pass --image <ref> (repeatable) to enable',\n });\n return;\n }\n for (const image of input.images) {\n const cos = await deps.cosign({ image });\n if (cos.ok) {\n push({ name: `cosign verify ${image}`, status: 'ok', detail: 'signature valid' });\n } else if (cos.skipped) {\n push({ name: `cosign verify ${image}`, status: 'skipped', detail: cos.reason });\n } else {\n push({ name: `cosign verify ${image}`, status: 'fail', detail: cos.reason });\n }\n }\n}\n\n/* ------------------------------------------------------------------ *\n * CLI wrapper *\n * ------------------------------------------------------------------ */\n\nfunction readTokenFile(path: string): string {\n const raw = readFileSync(path, 'utf8').trim();\n if (!raw) throw new Error(`--cf-token-file ${path} was empty`);\n return raw;\n}\n\nexport const verifyCommand = new Command('verify')\n .description(\n 'Off-LAN health probe of a live node — TLS, Apollo Federation reachability, GraphQL smoke. ' +\n 'Run from anywhere with internet access.',\n )\n .addOption(\n new Option('--domain <domain>', 'Domain to probe (e.g. example.org → checks api.example.org)'),\n )\n .addOption(new Option('--api-host <host>', 'Override the API hostname (default: api.<domain>)'))\n .addOption(new Option('--cf-token <token>', 'Cloudflare API token (enables tunnel-status probe)'))\n .addOption(\n new Option('--cf-token-file <path>', 'Read CF token from a file (avoids exposing it via ps)'),\n )\n .addOption(new Option('--cf-account-id <id>', 'Cloudflare account ID (required with --cf-token)'))\n .addOption(\n new Option('--tunnel-id <id>', 'Cloudflare Tunnel ID to query (required with --cf-token)'),\n )\n .addOption(\n new Option('--image <ref>', 'Repeatable. Image to cosign-verify (e.g. ghcr.io/opuspopuli/api:tag)').default(\n [] as string[],\n ),\n )\n .addOption(\n new Option('--cert-warn-days <n>', 'Warn if cert expires within N days').default('14'),\n )\n .addOption(\n new Option('--show-skipped', 'Include skipped phases in the summary').default(false),\n )\n .action(async (opts: VerifyOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node verify ')));\n\n const domain = await resolveDomain(opts);\n const certWarnDays = resolveCertWarnDays(opts);\n const cfToken = resolveCfToken(opts);\n\n const apiHost = opts.apiHost ?? `api.${domain}`;\n const images = opts.image ?? [];\n const totalPhases = 4 + (images.length === 0 ? 1 : images.length);\n\n const report = await runVerifyWithSpinner({\n apiHost,\n certWarnDays,\n cfToken,\n opts,\n images,\n totalPhases,\n });\n\n renderVerifySummary(report, { opts, totalPhases });\n reportVerifyOutcome(report);\n });\n\nfunction phaseIcon(ph: VerifyPhase): string {\n switch (ph.status) {\n case 'ok': return pc.green('✓');\n case 'warn': return pc.yellow('⚠');\n case 'skipped': return pc.dim('·');\n case 'fail': return pc.red('✗');\n }\n}\n\nfunction phaseColor(status: VerifyPhase['status']): (text: string) => string {\n switch (status) {\n case 'ok': return pc.green;\n case 'warn': return pc.yellow;\n case 'skipped': return pc.dim;\n case 'fail': return pc.red;\n }\n}\n\nfunction formatPhaseLine(prefix: string, ph: VerifyPhase): string {\n const icon = phaseIcon(ph);\n const colorize = phaseColor(ph.status);\n return colorize(`${icon} ${prefix}: ${ph.detail}`);\n}\n\n// ----------------------------------------------------------------------------\n// Verify command phases\n// ----------------------------------------------------------------------------\n// The action delegates to these so no single function exceeds the\n// cognitive-complexity budget. Behavior-preserving: interactive prompts,\n// spinners, and process.exit calls are relocated verbatim.\n\nasync function resolveDomain(opts: VerifyOptions): Promise<string> {\n const domain = opts.domain\n ? opts.domain\n : unwrap(\n await p.text({\n message: 'Public domain of the node?',\n placeholder: 'yournode.example.org',\n validate: (v) =>\n DOMAIN_RE.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens, dots; must contain a dot and a TLD',\n }),\n );\n if (!DOMAIN_RE.test(domain)) {\n p.cancel(`--domain ${JSON.stringify(domain)} doesn't look like a domain.`);\n process.exit(2);\n }\n return domain;\n}\n\n// (review B1) Validate --cert-warn-days to a non-negative integer.\nfunction resolveCertWarnDays(opts: VerifyOptions): number {\n const rawDays = opts.certWarnDays ?? '14';\n const certWarnDays = Number.parseInt(rawDays, 10);\n if (!Number.isFinite(certWarnDays) || certWarnDays < 0 || !/^\\d+$/.test(rawDays)) {\n p.cancel(`--cert-warn-days must be a non-negative integer (got ${JSON.stringify(rawDays)}).`);\n process.exit(2);\n }\n return certWarnDays;\n}\n\n// Resolve the CF token from --cf-token or --cf-token-file (mutually exclusive).\nfunction resolveCfToken(opts: VerifyOptions): string | undefined {\n if (opts.cfToken && opts.cfTokenFile) {\n p.cancel('Pass either --cf-token or --cf-token-file, not both.');\n process.exit(2);\n }\n if (opts.cfToken) return opts.cfToken;\n if (!opts.cfTokenFile) return undefined;\n try {\n return readTokenFile(opts.cfTokenFile);\n } catch (err) {\n p.cancel((err as Error).message);\n process.exit(2);\n }\n}\n\n// Run the checks behind a single spinner that advances per phase.\nasync function runVerifyWithSpinner(args: {\n apiHost: string;\n certWarnDays: number;\n cfToken: string | undefined;\n opts: VerifyOptions;\n images: string[];\n totalPhases: number;\n}): Promise<VerifyReport> {\n const { apiHost, certWarnDays, cfToken, opts, images, totalPhases } = args;\n\n let phaseIndex = 0;\n let activeSpin: ReturnType<typeof p.spinner> | null = null;\n const renderPhase = (ph: VerifyPhase): void => {\n phaseIndex++;\n const prefix = `[${phaseIndex}/${totalPhases}] ${ph.name}`;\n activeSpin?.stop(formatPhaseLine(prefix, ph));\n activeSpin = null;\n };\n\n const deps: VerifyDeps = { ...DEFAULT_DEPS, onPhase: renderPhase };\n\n activeSpin = p.spinner();\n activeSpin.start('Running checks…');\n\n const report = await runVerify(\n {\n apiHost,\n certWarnDays,\n cf: {\n ...(cfToken ? { token: cfToken } : {}),\n ...(opts.cfAccountId ? { accountId: opts.cfAccountId } : {}),\n ...(opts.tunnelId ? { tunnelId: opts.tunnelId } : {}),\n },\n images,\n },\n deps,\n );\n // If `runVerify` finished without firing onPhase for some pathological\n // reason, stop the spinner cleanly.\n activeSpin?.stop('Done.');\n return report;\n}\n\n// Render the per-phase summary note (hiding skipped phases unless asked).\nfunction renderVerifySummary(\n report: VerifyReport,\n args: { opts: VerifyOptions; totalPhases: number },\n): void {\n const { opts, totalPhases } = args;\n const visible = (opts.showSkipped ?? false)\n ? report.phases\n : report.phases.filter((ph) => ph.status !== 'skipped');\n const lines = visible.map((ph) => {\n const idx = report.phases.indexOf(ph) + 1;\n return `${phaseIcon(ph)} [${idx}/${totalPhases}] ${ph.name}: ${pc.dim(ph.detail)}`;\n });\n const skippedCount = report.phases.length - visible.length;\n if (skippedCount > 0 && !opts.showSkipped) {\n lines.push(pc.dim(`· ${skippedCount} phase${skippedCount === 1 ? '' : 's'} skipped (run with --show-skipped to see them)`));\n }\n p.note(lines.join('\\n'), 'Summary');\n}\n\n// Final outro + exit code from the phase report.\nfunction reportVerifyOutcome(report: VerifyReport): void {\n const summary = summarize(report);\n if (!summary.ok) {\n p.outro(pc.red(`${summary.failed} check${summary.failed === 1 ? '' : 's'} failed.`));\n process.exit(1);\n }\n if (summary.warned === 0) {\n p.outro(pc.green('All checks passed.'));\n } else {\n p.outro(pc.yellow(`Passed with ${summary.warned} warning${summary.warned === 1 ? '' : 's'}.`));\n }\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://github.com/OpusPopuli/opuspopuli-regions/schema/region-plugin.schema.json\",\n \"title\": \"Region Plugin File\",\n \"description\": \"A declarative region configuration file for the Opus Populi civic data platform. A handful of string-valued fields (ApiSourceConfig.queryParams, BulkDownloadConfig.filters) support ${variableName} placeholders that the consumer resolves at runtime — see those field descriptions for the supported variable list.\",\n \"type\": \"object\",\n \"required\": [\"name\", \"displayName\", \"description\", \"version\", \"config\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Region identifier (e.g., 'california')\"\n },\n \"displayName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Human-readable region name (e.g., 'California')\"\n },\n \"description\": {\n \"type\": \"string\",\n \"description\": \"Brief description of this region's data coverage\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\",\n \"description\": \"Semantic version of this config file\"\n },\n \"config\": {\n \"$ref\": \"#/definitions/DeclarativeRegionConfig\"\n }\n },\n \"definitions\": {\n \"DeclarativeRegionConfig\": {\n \"type\": \"object\",\n \"required\": [\"regionId\", \"regionName\", \"description\", \"timezone\", \"dataSources\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"regionId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Region identifier (e.g., 'california')\"\n },\n \"regionName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Human-readable region name (e.g., 'California')\"\n },\n \"description\": {\n \"type\": \"string\",\n \"description\": \"Region description\"\n },\n \"timezone\": {\n \"type\": \"string\",\n \"description\": \"IANA timezone (e.g., 'America/Los_Angeles')\"\n },\n \"stateCode\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Z]{2}$\",\n \"description\": \"Two-letter US state code (e.g., 'CA')\"\n },\n \"parentRegionId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Region identifier of this region's parent in the geographic hierarchy. Top-level regions (states, federal) omit this field. Counties set parentRegionId to their state's regionId (e.g., 'california'); cities will set it to their county's regionId. Presence of this field is the canonical signal that a region is a sub-region; the consumer loader uses it to build the region tree.\"\n },\n \"fipsCode\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d{2,7}$\",\n \"description\": \"Census FIPS code: 2 digits for states (e.g., '06' for CA), 5 digits for counties (e.g., '06037' for Los Angeles County — state FIPS + county FIPS), 7 digits for places/cities. This is the canonical join key against the consumer's PostGIS counties/places tables used today for user-to-district placement.\"\n },\n \"dataSources\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": \"#/definitions/DataSourceConfig\"\n },\n \"description\": \"Data sources to scrape\"\n },\n \"rateLimit\": {\n \"type\": \"object\",\n \"properties\": {\n \"requestsPerSecond\": { \"type\": \"number\", \"minimum\": 0 },\n \"burstSize\": { \"type\": \"integer\", \"minimum\": 1 }\n },\n \"required\": [\"requestsPerSecond\", \"burstSize\"],\n \"additionalProperties\": false,\n \"description\": \"Rate limiting defaults\"\n },\n \"cacheTtlMs\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Cache TTL in milliseconds\"\n },\n \"requestTimeoutMs\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Request timeout in milliseconds\"\n },\n \"normalizeExternalIdDistrict\": {\n \"type\": \"boolean\",\n \"description\": \"Strip leading zeros from representative externalId trailing segment (e.g. ca-assembly-01 → ca-assembly-1). Opt-in; default false. Only needed for regions whose LLM manifests emit zero-padded district numbers.\"\n },\n \"bioNoisePatterns\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Regex pattern strings (case-insensitive) matched against scraped representative bio text. Bios matching any pattern are treated as nav junk and discarded. Defaults to no filtering if omitted.\"\n },\n \"boundarySources\": {\n \"$ref\": \"#/definitions/BoundarySourcesConfig\",\n \"description\": \"Civic-boundary geometry sources used to populate the consumer's `jurisdictions` table (counties, cities, state legislative districts, school districts, special districts). The consumer's BoundaryLoaderService reads this block, dispatches to TIGER and ArcGIS FeatureServer fetchers, and upserts on fipsCode/ocdId. Omit when a region has no public boundary data — addresses still resolve via Census Geocoder string fields, but PostGIS point-in-polygon queries return no matches. See opuspopuli#804.\"\n }\n }\n },\n \"BoundarySourcesConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"ocdIdPrefix\"],\n \"description\": \"Per-region declarative recipe for loading civic boundaries. Pure config — no per-region code lives in the consumer.\",\n \"properties\": {\n \"ocdIdPrefix\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Open Civic Data ID prefix for this region, e.g. 'ocd-division/country:us/state:ca'. All jurisdiction OCD-IDs are composed as `${ocdIdPrefix}${TigerLayerConfig.ocdIdSegment}` (or the Geoportal equivalent).\"\n },\n \"tigerLayers\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"$ref\": \"#/definitions/TigerLayerConfig\" },\n \"description\": \"US Census TIGER/Line layers to ingest as jurisdictions. Each entry maps one ArcGIS MapServer layer to a JurisdictionType. Omit the field entirely when the region has no TIGER coverage — do not pass an empty array (the schema rejects it to prevent silent typos that strip the configured layers).\"\n },\n \"geoportalLayers\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"$ref\": \"#/definitions/GeoportalLayerConfig\" },\n \"description\": \"Region-specific ArcGIS FeatureServer endpoints — typically state geoportals serving boundary data Census TIGER doesn't cover (fire districts, water districts, transit districts, etc.). Omit when unused — empty arrays are rejected (see tigerLayers note).\"\n }\n }\n },\n \"JurisdictionTypeEnum\": {\n \"type\": \"string\",\n \"enum\": [\"COUNTY\", \"CITY\", \"STATE_SENATE_DISTRICT\", \"STATE_ASSEMBLY_DISTRICT\", \"CONGRESSIONAL_DISTRICT\", \"SCHOOL_DISTRICT_UNIFIED\", \"SCHOOL_DISTRICT_ELEMENTARY\", \"SCHOOL_DISTRICT_HIGH\", \"COMMUNITY_COLLEGE_DISTRICT\", \"WATER_DISTRICT\", \"FIRE_DISTRICT\", \"TRANSIT_DISTRICT\", \"SPECIAL_DISTRICT\"],\n \"description\": \"Maps each feature to a JurisdictionType row in the consumer's `jurisdictions` table. Single source of truth — TigerLayerConfig and GeoportalLayerConfig both reference this so a new jurisdiction type can't be added to one without the other.\"\n },\n \"JurisdictionLevelEnum\": {\n \"type\": \"string\",\n \"enum\": [\"FEDERAL\", \"STATE\", \"COUNTY\", \"MUNICIPAL\", \"DISTRICT\"],\n \"description\": \"Hierarchy level for the resulting jurisdiction rows. Single source of truth — referenced from TigerLayerConfig and GeoportalLayerConfig.\"\n },\n \"TigerLayerConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"layer\", \"outFields\", \"jurisdictionType\", \"level\", \"nameField\"],\n \"description\": \"One TIGER/Line layer mapped to a JurisdictionType. The consumer hits `https://tigerweb.geo.census.gov/arcgis/rest/services/TIGERweb/${layer}/query` with GeoJSON output. Supported placeholders inside `where`, `ocdIdSegment`, `nameTemplate`: ${fipsCode} (this region's fipsCode), ${stateCode} (two-letter code), ${name} (the layer's nameField value for a given feature), ${district} (the districtField value).\",\n \"properties\": {\n \"layer\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"TIGER MapServer service+layer path, e.g. 'State_County/MapServer/1', 'Legislative/MapServer/1' (state senate), 'Legislative/MapServer/2' (state assembly), 'School/MapServer/0' (unified school districts).\"\n },\n \"where\": {\n \"type\": \"string\",\n \"description\": \"ESRI WHERE clause filtering features. Defaults to `STATE='${fipsCode}'` when omitted. Use `${fipsCode}` / `${stateCode}` placeholders.\"\n },\n \"outFields\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Comma-separated TIGER attribute fields to return, e.g. 'GEOID,NAME' or 'GEOID,SLDUST'.\"\n },\n \"jurisdictionType\": {\n \"$ref\": \"#/definitions/JurisdictionTypeEnum\"\n },\n \"level\": {\n \"$ref\": \"#/definitions/JurisdictionLevelEnum\"\n },\n \"nameField\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"TIGER attribute key whose value becomes the substitution for `${name}` placeholders. Typically 'NAME' for human-readable layers, or a district code field like 'SLDUST'/'SLDLST' for legislative layers.\"\n },\n \"fipsField\": {\n \"type\": \"string\",\n \"description\": \"TIGER attribute key holding the canonical fips_code for an upsert. Defaults to 'GEOID'.\"\n },\n \"fipsPrefix\": {\n \"type\": \"string\",\n \"description\": \"Optional prefix prepended to the fipsField value before persisting as fips_code. Use when the raw GEOID would collide with another layer's GEOID (e.g. state senate GEOID overlapping county GEOID format). Example: 'sldu-' for state senate, 'sldl-' for state assembly.\"\n },\n \"districtField\": {\n \"type\": \"string\",\n \"description\": \"TIGER attribute key supplying the ${district} placeholder. Required when ocdIdSegment or nameTemplate contains ${district}.\"\n },\n \"ocdIdSegment\": {\n \"type\": \"string\",\n \"description\": \"Segment appended to `boundarySources.ocdIdPrefix` to form the full OCD-ID, e.g. '/county:${name}', '/sldu:${district}'. Supports ${name} and ${district} placeholders. Inside `${name}` substitutions the consumer normalizes whitespace to underscores and lowercases the value for OCD-ID compatibility — so a NAME of 'Alameda County' produces 'alameda_county' in the OCD-ID. Omit when this layer's rows don't carry an OCD-ID.\"\n },\n \"nameTemplate\": {\n \"type\": \"string\",\n \"description\": \"Template for the persisted jurisdiction name (NOT for OCD-ID composition). Supports ${name}, ${district}, ${stateCode}. The ${name} value is substituted verbatim (case + whitespace preserved). Defaults to ${name} when omitted.\"\n }\n }\n },\n \"GeoportalLayerConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"url\", \"outFields\", \"jurisdictionType\", \"level\", \"nameField\"],\n \"description\": \"One arbitrary ArcGIS FeatureServer layer for jurisdictions Census TIGER doesn't cover. Same placeholder rules as TigerLayerConfig.\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\",\n \"pattern\": \"^https://\",\n \"description\": \"Full ArcGIS FeatureServer layer URL ending in /FeatureServer/<n>. Must be HTTPS — the consumer rejects other schemes. The consumer paginates via resultOffset/resultRecordCount.\"\n },\n \"where\": {\n \"type\": \"string\",\n \"description\": \"ESRI WHERE clause. Defaults to '1=1'.\"\n },\n \"outFields\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Comma-separated FeatureServer attribute fields to return.\"\n },\n \"jurisdictionType\": {\n \"$ref\": \"#/definitions/JurisdictionTypeEnum\"\n },\n \"level\": {\n \"$ref\": \"#/definitions/JurisdictionLevelEnum\"\n },\n \"nameField\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"FeatureServer attribute key supplying the human-readable name and the ${name} placeholder.\"\n },\n \"fipsField\": {\n \"type\": \"string\",\n \"description\": \"FeatureServer attribute key used as fips_code. No default — geoportal attribute names vary widely (no GEOID convention). Omit when the layer has no FIPS analog; the upsert then matches on ocdId only.\"\n },\n \"fipsPrefix\": {\n \"type\": \"string\",\n \"description\": \"Optional prefix prepended to fipsField, mirroring TigerLayerConfig.fipsPrefix.\"\n },\n \"ocdIdSegment\": {\n \"type\": \"string\",\n \"description\": \"Appended to boundarySources.ocdIdPrefix. Supports ${name} placeholder. Same OCD-ID normalization as TigerLayerConfig.ocdIdSegment — whitespace to underscores, lowercased.\"\n },\n \"nameTemplate\": {\n \"type\": \"string\",\n \"description\": \"Template for persisted name (NOT for OCD-ID). ${name} substituted verbatim. Defaults to ${name}.\"\n }\n }\n },\n \"DataSourceConfig\": {\n \"type\": \"object\",\n \"required\": [\"url\", \"dataType\", \"contentGoal\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\",\n \"description\": \"URL to fetch data from\"\n },\n \"dataType\": {\n \"type\": \"string\",\n \"enum\": [\"propositions\", \"meetings\", \"representatives\", \"campaign_finance\", \"lobbying\", \"civics\", \"bills\"],\n \"description\": \"What type of content this source provides. Daily journals / meeting minutes go under 'meetings' with sourceType=pdf_archive — the consumer partitions by sourceType internally. 'civics' marks a source of region governmental structure, process, and vocabulary; the civics-ingest handler scrapes it and uses the private prompt-service to extract structured shape (chambers, measure types, lifecycle stages with status patterns, glossary) plus a plain-language rewrite for laypeople. Verbatim source text and the AI rewrite are stored together — never one without the other. 'bills' marks a source of individual legislative bills (AB, SB, ACA, SCA, etc.) scraped from an official legislature website; the bills-ingest handler BFS-crawls from the seed URL and extracts one Bill record per detail page. See opuspopuli#686.\"\n },\n \"contentGoal\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Natural language description of what to find/extract\"\n },\n \"category\": {\n \"type\": \"string\",\n \"description\": \"Sub-category for grouping (e.g., 'Assembly', 'Senate')\"\n },\n \"hints\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Hints to help the AI find the right content\"\n },\n \"rateLimitOverride\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"description\": \"Override rate limit for this specific source\"\n },\n \"syncCadence\": {\n \"type\": \"string\",\n \"pattern\": \"^[^ ]+ [^ ]+ [^ ]+ [^ ]+ [^ ]+$\",\n \"description\": \"5-field cron expression (minute hour dom month dow) controlling how often this source is synced. The worker applies a deterministic per-source minute offset at registration time to spread load across gov hosts — the minute field you specify is the base, not the exact fire time. Omit to inherit the global daily fallback. Common patterns: '0 2 * * *' daily at 2 AM, '0 2 * * 0' weekly on Sunday, '0 * * * *' hourly.\"\n },\n \"statusScanCadence\": {\n \"type\": \"string\",\n \"pattern\": \"^[^ ]+ [^ ]+ [^ ]+ [^ ]+ [^ ]+$\",\n \"description\": \"5-field cron expression for a periodic full status-page sweep of all bills (dataType='bills' only). Runs forceStatusRecheck=true — bypasses the needsStatusRecheck flag and the sourcePublishedAt skip to catch governor actions and off-session changes the journal linker can't see. Per-source minute offset is applied like syncCadence. Typical: '0 2 * * 0' weekly Sunday 2 AM. See #689.\"\n },\n \"sourceType\": {\n \"type\": \"string\",\n \"enum\": [\"html_scrape\", \"bulk_download\", \"api\", \"pdf\", \"pdf_archive\"],\n \"description\": \"Source type determines the extraction strategy (default: html_scrape). 'pdf_archive' selects the listing-walk + per-PDF-extract pipeline: the URL is a paginated listing page that links to a series of dated PDF documents, each fetched and parsed (text only at V1) into one Minutes record.\"\n },\n \"bulk\": {\n \"$ref\": \"#/definitions/BulkDownloadConfig\"\n },\n \"api\": {\n \"$ref\": \"#/definitions/ApiSourceConfig\"\n },\n \"pdf\": {\n \"$ref\": \"#/definitions/PdfSourceConfig\"\n },\n \"pdfArchive\": {\n \"$ref\": \"#/definitions/PdfArchiveConfig\"\n },\n \"billDiscovery\": {\n \"$ref\": \"#/definitions/BillDiscoveryConfig\"\n },\n \"detailFields\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"string\" },\n { \"$ref\": \"#/definitions/StructuredFieldConfig\" }\n ]\n },\n \"description\": \"Detail page extraction plan: maps domain field names to CSS selectors (string) or structured array configs (object). Supports dot notation and '|attr:name' suffix.\"\n },\n \"staticManifest\": {\n \"type\": \"object\",\n \"required\": [\"containerSelector\", \"itemSelector\", \"fieldMappings\"],\n \"additionalProperties\": false,\n \"description\": \"Explicit extraction selectors that bypass AI structural analysis entirely. Use when the page structure is known and stable, or when the local LLM consistently generates wrong selectors.\",\n \"properties\": {\n \"containerSelector\": { \"type\": \"string\" },\n \"itemSelector\": { \"type\": \"string\" },\n \"fieldMappings\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\"fieldName\", \"selector\", \"extractionMethod\", \"required\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"fieldName\": { \"type\": \"string\" },\n \"selector\": { \"type\": \"string\" },\n \"extractionMethod\": { \"type\": \"string\" },\n \"attribute\": { \"type\": \"string\" },\n \"regexPattern\": { \"type\": \"string\" },\n \"regexGroup\": { \"type\": \"integer\" },\n \"transform\": { \"type\": \"object\" },\n \"required\": { \"type\": \"boolean\" },\n \"defaultValue\": { \"type\": \"string\" },\n \"scope\": {\n \"type\": \"string\",\n \"enum\": [\"item\", \"container\"]\n },\n \"children\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"string\" },\n { \"$ref\": \"#/definitions/ChildFieldConfig\" }\n ]\n },\n \"description\": \"For extractionMethod='structured': child field selectors. Each value is a string shortcut or a ChildFieldConfig object.\"\n }\n }\n }\n }\n }\n },\n \"crawlDepth\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Crawl depth from the seed URL for sync handlers that walk a site's link graph (currently civics — see opuspopuli#669). 0 (default) = no crawl, fetch only the seed. N = N hops from seed. Crawls are scoped to same host + same path prefix as the seed, HTML responses only.\"\n },\n \"crawlMaxPages\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Cap on total pages a crawler will visit per sync run regardless of crawlDepth. Defaults to 20. Each page costs one LLM call, so this bounds runtime + token spend.\"\n },\n \"llmMaxTokens\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Per-source override for the LLM maxTokens generation cap. Useful when a source needs a much longer or shorter output than its siblings (e.g., a 150-term glossary needs ~32000; a short bio prompt finishes well under 2000). Overrides the sync handler's hardcoded default.\"\n },\n \"llmRequestTimeoutMs\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Per-source override for the LLM provider request timeout (milliseconds). Useful when a single source legitimately runs much longer than the platform-wide default — civics-glossary extraction on qwen3.5:9b can take 15-20 min, while bio gen finishes in 2 min on the same hardware. Overrides the provider's constructor-configured default.\"\n }\n }\n },\n \"BulkDownloadConfig\": {\n \"type\": \"object\",\n \"required\": [\"format\", \"columnMappings\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"format\": {\n \"type\": \"string\",\n \"enum\": [\"tsv\", \"csv\", \"zip_tsv\", \"zip_csv\"],\n \"description\": \"File format\"\n },\n \"filePattern\": {\n \"type\": \"string\",\n \"description\": \"For ZIP archives: path/glob of target file(s) within the ZIP\"\n },\n \"delimiter\": {\n \"type\": \"string\",\n \"description\": \"Column delimiter override\"\n },\n \"headerLines\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Number of header lines to skip\"\n },\n \"headers\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Explicit column headers for files without a header row (e.g., FEC bulk files)\"\n },\n \"columnMappings\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Column name mappings: source column name -> domain field name\"\n },\n \"filters\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Filter expressions applied during parse. Values support ${variableName} placeholders that the consumer resolves at runtime from the active local region. Supported variables: ${stateCode} (the 2-letter US state code of the active local region, e.g. 'CA'). Placeholders must appear verbatim. Example: '\\\"STATE\\\": \\\"${stateCode}\\\"' on an FEC bulk filter.\"\n },\n \"batchSize\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Records per batch for streaming processing (default: 10000)\"\n }\n }\n },\n \"ApiSourceConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"method\": {\n \"type\": \"string\",\n \"enum\": [\"GET\", \"POST\"],\n \"description\": \"HTTP method (default: GET)\"\n },\n \"apiKeyEnvVar\": {\n \"type\": \"string\",\n \"description\": \"Environment variable name containing the API key\"\n },\n \"apiKeyHeader\": {\n \"type\": \"string\",\n \"description\": \"Header name for the API key\"\n },\n \"pagination\": {\n \"$ref\": \"#/definitions/ApiPaginationConfig\"\n },\n \"resultsPath\": {\n \"type\": \"string\",\n \"description\": \"JSON path to the items array in the response\"\n },\n \"queryParams\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Query parameters appended to every request. Values support ${variableName} placeholders that the consumer resolves at runtime from the active local region. Supported variables: ${stateCode} (the 2-letter US state code of the active local region, e.g. 'CA'). Placeholders must appear verbatim — no escaping, no nested expressions. Example: '\\\"contributor_state\\\": \\\"${stateCode}\\\"'.\"\n },\n \"fieldMappings\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Field name mappings: API response field -> domain model field (e.g., committee_id -> committeeId)\"\n }\n }\n },\n \"ApiPaginationConfig\": {\n \"type\": \"object\",\n \"required\": [\"type\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"offset\", \"cursor\", \"page\"],\n \"description\": \"Pagination strategy type\"\n },\n \"pageParam\": {\n \"type\": \"string\",\n \"description\": \"Query parameter name for page/offset\"\n },\n \"limitParam\": {\n \"type\": \"string\",\n \"description\": \"Query parameter name for page size\"\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Number of items per page\"\n }\n }\n },\n \"PdfSourceConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"skipPages\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Skip first N pages (e.g., skip cover page)\"\n },\n \"maxPages\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Maximum pages to process (default: all)\"\n },\n \"followPdfLink\": {\n \"type\": \"boolean\",\n \"description\": \"If true, treats the URL as a gateway page and follows the first PDF link\"\n }\n }\n },\n \"StructuredFieldConfig\": {\n \"type\": \"object\",\n \"required\": [\"selector\", \"children\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"selector\": {\n \"type\": \"string\",\n \"description\": \"CSS selector matching each repeating item (e.g., '.office-card')\"\n },\n \"children\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"string\" },\n { \"$ref\": \"#/definitions/ChildFieldConfig\" }\n ]\n },\n \"description\": \"Child field selectors relative to each item. Each entry is either a string shortcut (e.g. 'h3', 'a|attr:href') or a richer ChildFieldConfig object with extractionMethod / regex / transform.\"\n },\n \"multiple\": {\n \"type\": \"boolean\",\n \"description\": \"If true, extracts all matches as an array (default: true)\"\n }\n }\n },\n \"ChildFieldConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Per-child extraction config for structured extraction. Object form supports the same shape as the top-level FieldMapping (selector + extractionMethod + attribute / regex / transform), minus fieldName/required/defaultValue which don't apply at child scope.\",\n \"properties\": {\n \"selector\": {\n \"type\": \"string\",\n \"description\": \"CSS selector relative to the matched parent item. Optional for regex on full element text.\"\n },\n \"extractionMethod\": {\n \"type\": \"string\",\n \"description\": \"How to extract: 'text', 'attribute', 'regex', 'html', etc.\"\n },\n \"attribute\": {\n \"type\": \"string\",\n \"description\": \"For extractionMethod='attribute': which attribute to read (e.g. 'href', 'src').\"\n },\n \"regexPattern\": {\n \"type\": \"string\",\n \"description\": \"For extractionMethod='regex': the pattern.\"\n },\n \"regexGroup\": {\n \"type\": \"integer\",\n \"description\": \"For extractionMethod='regex': capture group (default: 1).\"\n },\n \"transform\": {\n \"type\": \"object\",\n \"description\": \"Optional transform applied after extraction (e.g. trim, regex_replace, url_resolve).\"\n }\n }\n },\n \"BillDiscoveryConfig\": {\n \"type\": \"object\",\n \"required\": [\"navLinkPattern\", \"statusPageTemplate\", \"votesPageTemplate\"],\n \"additionalProperties\": false,\n \"description\": \"Declarative bill discovery for legislature sites that list per-bill nav-hub links on a search results page (e.g. CA leginfo). The bills-ingest handler fetches the seed once, extracts bill IDs with navLinkPattern, and constructs status + votes URLs from the templates — bypassing generic BFS which would exhaust crawlMaxPages with nav-hub links before reaching detail pages.\",\n \"properties\": {\n \"navLinkPattern\": {\n \"type\": \"string\",\n \"description\": \"Regex string applied to the decoded seed-page HTML to extract bill IDs. Capture group 1 must be the bill ID. Example for CA leginfo: \\\"/faces/billNavClient\\\\\\\\.xhtml\\\\\\\\?bill_id=([^\\\\\\\"&\\\\\\\\s]+)\\\"\"\n },\n \"statusPageTemplate\": {\n \"type\": \"string\",\n \"description\": \"URL path + query template for the bill status page. Use {bill_id} as the placeholder; the service prepends the seed origin. Example: \\\"/faces/billStatusClient.xhtml?bill_id={bill_id}\\\"\"\n },\n \"votesPageTemplate\": {\n \"type\": \"string\",\n \"description\": \"URL path + query template for the bill votes page. Same substitution as statusPageTemplate. Example: \\\"/faces/billVotesClient.xhtml?bill_id={bill_id}\\\"\"\n },\n \"textPageTemplate\": {\n \"type\": \"string\",\n \"description\": \"Optional URL path + query template for the bill text page. When set, the sync fetches this page before LLM extraction to check the 'Date Published' timestamp and skip unchanged bills. Example: \\\"/faces/billTextClient.xhtml?bill_id={bill_id}\\\"\"\n }\n }\n },\n \"PdfArchiveConfig\": {\n \"type\": \"object\",\n \"required\": [\"linkSelector\"],\n \"additionalProperties\": false,\n \"description\": \"Listing-walk configuration for sourceType=pdf_archive. The page at `url` is treated as a paginated index of dated PDF documents; each linked PDF is fetched, pdf-parsed, and stored as a Minutes record. Cold-start work is bounded by maxNew (default 10) so first-run sync doesn't ingest years of historical archives. Per-document parsing (text → action records) is a downstream backend pass — this block carries no parser DSL.\",\n \"properties\": {\n \"linkSelector\": {\n \"type\": \"string\",\n \"description\": \"CSS selector for PDF anchor elements on the listing page. Each match yields a candidate document.\"\n },\n \"datePattern\": {\n \"type\": \"string\",\n \"description\": \"Regex applied to the link href (falling back to anchor text) to extract the document's date. Capture groups depend on dateFormat.\"\n },\n \"dateFormat\": {\n \"type\": \"string\",\n \"description\": \"Date format hint for interpreting datePattern's captures. Supported: 'MMDDYY' (3 captures: month, day, two-digit year — assumed 20YY), 'YYYY-MM-DD' (3 captures), 'MM/DD/YYYY' (3 captures).\"\n },\n \"revisionPattern\": {\n \"type\": \"string\",\n \"description\": \"Regex against the link href whose match indicates this URL is a revision. Capture group 1 is the revision sequence number (1, 2, ...). Unmatched URLs are revisionSeq=0.\"\n },\n \"maxPages\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Maximum number of listing pages to walk during one sync cycle. Default: 10.\"\n },\n \"maxNew\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Hard cap on number of new documents ingested per sync cycle. Cold-start protection. Default: 10.\"\n },\n \"paginationParam\": {\n \"type\": \"string\",\n \"description\": \"Query parameter name used to paginate the listing page (e.g., 'page'). Omitted when the listing isn't paginated.\"\n }\n }\n }\n }\n}","/**\n * Pure logic for scaffolding a region config for the\n * [`OpusPopuli/opuspopuli-regions`](https://github.com/OpusPopuli/opuspopuli-regions)\n * repo.\n *\n * Region configs are declarative JSON files validated against\n * `schema/region-plugin.schema.json` in that repo. We vendor a copy of that\n * schema at `./region-schema.json` so the wizard is self-contained and\n * validates against the **canonical contract** rather than a hand-rolled\n * approximation. Anything the schema enforces is enforced here; we layer a\n * small set of cross-field invariants on top that the regions repo's\n * `pnpm test` also checks (e.g. `name === config.regionId`).\n *\n * Everything here is side-effect free and unit tested. The interactive shell\n * and filesystem writes live in `src/commands/region.ts`.\n */\n\n// ESM-native JSON Schema validator. Picked over Ajv 8 because Ajv ships only\n// CJS, which forces a `.default` interop dance under `verbatimModuleSyntax`.\n// `@cfworker/json-schema` is a clean ESM module with no peer dep and supports\n// the Draft 7 / 2019-09 / 2020-12 schemas the regions repo uses.\nimport { Validator, type Schema } from '@cfworker/json-schema';\n\n// Schema imported as JSON so tsup inlines it into the bundle — no need to\n// ship a separate file in dist/.\nimport REGION_SCHEMA from './region-schema.json' with { type: 'json' };\n\n/** `dataType` values the regions schema accepts on a data source. Mirrors the\n * enum block in `region-plugin.schema.json` so the CLI prompt matches. */\nexport const DATA_TYPES = [\n 'propositions',\n 'meetings',\n 'representatives',\n 'campaign_finance',\n 'lobbying',\n 'civics',\n 'bills',\n] as const;\nexport type DataType = (typeof DATA_TYPES)[number];\n\n/** `sourceType` values the regions schema accepts on a data source. */\nexport const SOURCE_TYPES = [\n 'html_scrape',\n 'bulk_download',\n 'api',\n 'pdf',\n 'pdf_archive',\n] as const;\nexport type SourceType = (typeof SOURCE_TYPES)[number];\n\n/** The two region levels this scaffolder authors. `federal` is a singleton that\n * already exists in the regions repo, so it is intentionally not offered. */\nexport type RegionLevel = 'state' | 'county';\n\nexport interface DataSourceInput {\n url: string;\n dataType: DataType;\n sourceType: SourceType;\n contentGoal: string;\n category?: string;\n}\n\nexport interface RegionInput {\n level: RegionLevel;\n /** kebab-case; for a county this is the combined `state-county` id. */\n regionId: string;\n /** kebab-case county slug only — the trailing segment of a county regionId.\n * Required for counties so we never have to re-derive it from string\n * prefixes; ignored for states. */\n countySlug?: string;\n displayName: string;\n regionName: string;\n description: string;\n /** semver, e.g. `0.1.0`. */\n version: string;\n /** IANA tz, e.g. `America/Los_Angeles`. */\n timezone: string;\n /** Two-letter US state code, uppercase. */\n stateCode: string;\n /** 2 digits for a state, 5 digits for a county. */\n fipsCode: string;\n /** kebab-case parent state id; required for counties, omitted for states. */\n parentRegionId?: string;\n dataSources: DataSourceInput[];\n}\n\ninterface DeclarativeRegionConfig {\n regionId: string;\n regionName: string;\n description: string;\n timezone: string;\n stateCode?: string;\n parentRegionId?: string;\n fipsCode?: string;\n dataSources: DataSourceInput[];\n}\n\nexport interface RegionPluginFile {\n name: string;\n displayName: string;\n description: string;\n version: string;\n config: DeclarativeRegionConfig;\n}\n\nexport const SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst STATE_CODE_RE = /^[A-Z]{2}$/;\n\n/** Lower-cases, strips accents, and collapses anything non-alphanumeric into\n * single hyphens — turning \"Los Angeles County\" into \"los-angeles\". */\nexport function slugify(input: string): string {\n return input\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n // The collapse above leaves at most a single hyphen at each edge, so a\n // quantifier-free `^-|-$` trim is equivalent to `^-+|-+$` and can't\n // backtrack super-linearly.\n .replace(/^-|-$/g, '');\n}\n\nexport function isValidSlug(v: string): boolean {\n return SLUG_RE.test(v);\n}\n\nexport function isValidStateCode(v: string): boolean {\n return STATE_CODE_RE.test(v);\n}\n\n/** A state FIPS is exactly 2 digits; a county FIPS is exactly 5 (state prefix +\n * 3-digit county). */\nexport function isValidFips(v: string, level: RegionLevel): boolean {\n return level === 'state' ? /^\\d{2}$/.test(v) : /^\\d{5}$/.test(v);\n}\n\n/** Set of IANA zone names on this runtime, or `null` if the host VM doesn't\n * expose `Intl.supportedValuesOf` (in which case callers should skip the\n * membership check rather than reject everything). */\nfunction supportedTimeZones(): Set<string> | null {\n const intl = Intl as typeof Intl & {\n supportedValuesOf?: (key: string) => string[];\n };\n if (typeof intl.supportedValuesOf !== 'function') return null;\n try {\n return new Set(intl.supportedValuesOf('timeZone'));\n } catch {\n return null;\n }\n}\n\nexport function isValidTimezone(v: string): boolean {\n if (!v.includes('/')) return false;\n const zones = supportedTimeZones();\n // If the runtime can't enumerate zones, fall back to a shape check so we\n // don't reject a perfectly good \"Region/City\" string.\n return zones ? zones.has(v) : true;\n}\n\n/**\n * Build the `RegionPluginFile` object from collected input. Optional config\n * fields are only set when present so the JSON stays minimal and we don't trip\n * the schema's `additionalProperties: false` / `exactOptionalPropertyTypes`.\n */\nexport function buildRegionConfig(input: RegionInput): RegionPluginFile {\n const config: DeclarativeRegionConfig = {\n // The regions repo requires `name === config.regionId`; we tie them\n // together at construction so they can never drift.\n regionId: input.regionId,\n regionName: input.regionName,\n description: input.description,\n timezone: input.timezone,\n stateCode: input.stateCode,\n fipsCode: input.fipsCode,\n dataSources: input.dataSources.map(normalizeDataSource),\n };\n if (input.parentRegionId) {\n config.parentRegionId = input.parentRegionId;\n }\n\n return {\n name: input.regionId,\n displayName: input.displayName,\n description: input.description,\n version: input.version,\n config,\n };\n}\n\nfunction normalizeDataSource(src: DataSourceInput): DataSourceInput {\n const out: DataSourceInput = {\n url: src.url,\n dataType: src.dataType,\n sourceType: src.sourceType,\n contentGoal: src.contentGoal,\n };\n if (src.category) out.category = src.category;\n return out;\n}\n\n/**\n * Canonical path of a region file inside the regions repo, relative to the repo\n * root:\n * state → `regions/<state>/<state>.json`\n * county → `regions/<state>/counties/<county>/<county>.json`\n *\n * Counties pass `countySlug` explicitly so we never have to back out a slug\n * from a string prefix — important when a parent state slug contains a hyphen\n * (`new-jersey-cumberland` shouldn't be sliced on the first `-`).\n */\nexport function regionFilePath(input: {\n level: RegionLevel;\n regionId: string;\n parentRegionId?: string;\n countySlug?: string;\n}): string {\n if (input.level === 'state') {\n return `regions/${input.regionId}/${input.regionId}.json`;\n }\n const parent = input.parentRegionId;\n const countySlug = input.countySlug;\n if (!parent || !countySlug) {\n throw new Error(\n 'regionFilePath: county requires both parentRegionId and countySlug',\n );\n }\n return `regions/${parent}/counties/${countySlug}/${countySlug}.json`;\n}\n\n// ---------------------------------------------------------------------------\n// Schema-based validation (single source of truth)\n// ---------------------------------------------------------------------------\n\n// The JSON import resolves to a narrower literal type than `Schema` accepts\n// (e.g. `type: \"object\"` as a string literal vs the union enum). The cast is\n// a TS-only widening — runtime data is unchanged.\nconst schemaValidator = new Validator(REGION_SCHEMA as unknown as Schema, '7');\n\n/**\n * Re-check the invariants the regions repo enforces in CI, returning a list of\n * human-readable problems (empty means valid). Two layers:\n *\n * 1. **JSON Schema** — run the vendored `region-plugin.schema.json` (the same\n * file `pnpm test` validates against). Catches every structural rule the\n * schema declares.\n * 2. **Cross-field invariants** — checks the regions repo enforces in custom\n * test code that don't live in the schema: `name === config.regionId`,\n * county regionId prefixed by its parent, no duplicate data sources keyed by\n * `(dataType, url)`.\n */\nexport function validateRegionConfig(file: RegionPluginFile): string[] {\n // Cross-field invariants run first so their human-friendlier messages\n // (\"not a valid semver\", \"must be 5 digits for a county\", \"name mismatch\")\n // surface ahead of the corresponding raw Ajv pattern errors. Order of the\n // groups here IS the order issues are reported in.\n return [\n ...validateVersionAndIds(file),\n ...validateFipsCode(file),\n ...validateDataSourceUniqueness(file),\n ...validateAgainstSchema(file),\n ];\n}\n\n// version semver + name/regionId agreement + kebab-case + county prefix.\nfunction validateVersionAndIds(file: RegionPluginFile): string[] {\n const issues: string[] = [];\n const { config } = file;\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(file.version)) {\n issues.push(`version \"${file.version}\" is not a valid semver (expected MAJOR.MINOR.PATCH)`);\n }\n if (file.name !== config.regionId) {\n issues.push(`name \"${file.name}\" must equal config.regionId \"${config.regionId}\"`);\n }\n if (!isValidSlug(config.regionId)) {\n issues.push(`regionId \"${config.regionId}\" must be kebab-case`);\n }\n if (\n config.parentRegionId !== undefined &&\n !config.regionId.startsWith(`${config.parentRegionId}-`)\n ) {\n issues.push(\n `county regionId \"${config.regionId}\" should be prefixed with its parent \"${config.parentRegionId}-\"`,\n );\n }\n return issues;\n}\n\n// The JSON schema only checks the FIPS shape (2–7 digits). Per-level lengths\n// (\"2 for state, 5 for county\") are a cross-field rule the regions repo\n// enforces in custom test code — re-checked here.\nfunction validateFipsCode(file: RegionPluginFile): string[] {\n const { config } = file;\n if (config.fipsCode === undefined) return [];\n const isCounty = config.parentRegionId !== undefined;\n const expected = isCounty ? 5 : 2;\n if (!/^\\d+$/.test(config.fipsCode) || config.fipsCode.length !== expected) {\n return [\n `fipsCode \"${config.fipsCode}\" must be ${expected} digits for a ${isCounty ? 'county' : 'state'}`,\n ];\n }\n return [];\n}\n\n// dataSources is required by the schema — if it's missing the schema layer\n// below will flag that, so we just skip the duplicate scan here rather than\n// throwing on a malformed-but-not-yet-validated file.\nfunction validateDataSourceUniqueness(file: RegionPluginFile): string[] {\n const { config } = file;\n if (!Array.isArray(config.dataSources)) return [];\n const issues: string[] = [];\n const seen = new Set<string>();\n for (const src of config.dataSources) {\n const key = `${src.dataType} ${src.url}`;\n if (seen.has(key)) {\n issues.push(`duplicate data source: ${src.dataType} ${src.url}`);\n }\n seen.add(key);\n }\n return issues;\n}\n\n// Layer the schema on last — catches anything the friendly checks didn't\n// pre-empt (missing required fields, wrong types, unknown extras, etc.).\nfunction validateAgainstSchema(file: RegionPluginFile): string[] {\n const result = schemaValidator.validate(file);\n if (result.valid) return [];\n return result.errors.map((err) => `schema: ${err.instanceLocation || '<root>'} ${err.error}`);\n}\n","import { mkdir, writeFile, access } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport {\n DATA_TYPES,\n SOURCE_TYPES,\n buildRegionConfig,\n isValidFips,\n isValidSlug,\n isValidStateCode,\n isValidTimezone,\n regionFilePath,\n slugify,\n validateRegionConfig,\n type DataSourceInput,\n type DataType,\n type RegionInput,\n type RegionLevel,\n type RegionPluginFile,\n type SourceType,\n} from '../lib/region.js';\nimport { unwrap } from '../lib/prompts.js';\n\ninterface RegionOptions {\n level?: string;\n name?: string;\n parent?: string;\n stateCode?: string;\n fips?: string;\n timezone?: string;\n outDir?: string;\n force?: boolean;\n}\n\nexport const regionCommand = new Command('region')\n .description(\n 'Scaffold a schema-valid region config for the OpusPopuli/opuspopuli-regions repo. ' +\n 'Run this from inside your checkout of that repo.',\n )\n .addOption(\n new Option('--level <level>', 'Region level').choices(['state', 'county']),\n )\n .addOption(new Option('--name <name>', 'Region name (e.g. \"California\" or \"Alameda\")'))\n .addOption(\n new Option('--parent <slug>', 'Parent state slug for a county (e.g. california)'),\n )\n .addOption(new Option('--state-code <code>', 'Two-letter US state code (e.g. CA)'))\n .addOption(new Option('--fips <code>', 'FIPS code (2 digits state, 5 digits county)'))\n .addOption(new Option('--timezone <tz>', 'IANA timezone (e.g. America/Los_Angeles)'))\n .addOption(\n new Option('--out-dir <dir>', 'Repo root to write under').default(\n process.cwd(),\n 'current directory',\n ),\n )\n .addOption(new Option('-f, --force', 'Overwrite an existing config file').default(false))\n .action(async (opts: RegionOptions) => {\n p.intro(pc.bgMagenta(pc.black(' create-op-node region ')));\n printRegionWelcome();\n\n const targetDir = await resolveTargetDir(opts);\n const level = await resolveLevel(opts);\n const identity = await collectIdentity(opts, level);\n const codes = await collectCodes(opts, level);\n const dataSources = await collectDataSources();\n\n const input = buildRegionInput({ level, identity, codes, dataSources });\n const file = buildAndValidateConfig(input);\n await writeRegionConfig({ opts, targetDir, level, identity, file });\n });\n\n// ----------------------------------------------------------------------------\n// Region wizard steps\n// ----------------------------------------------------------------------------\n// The action delegates to these so no single function exceeds the\n// cognitive-complexity budget. Behavior-preserving: prompts, validation, and\n// process.exit calls are relocated verbatim.\n\ninterface RegionIdentity {\n rawName: string;\n parentSlug: string | undefined;\n ownSlug: string;\n regionId: string;\n regionName: string;\n description: string;\n}\n\ninterface RegionCodes {\n stateCode: string;\n fipsCode: string;\n timezone: string;\n}\n\nconst requireNonEmpty = (v: string | undefined): string | undefined =>\n v && v.trim().length > 0 ? undefined : 'Required';\n\nfunction printRegionWelcome(): void {\n p.note(\n [\n 'Scaffolds a declarative region config JSON for opuspopuli-regions —',\n 'the file that defines WHAT civic data a region collects.',\n '',\n pc.dim('Run this from the root of your opuspopuli-regions checkout.'),\n pc.dim('It validates the same invariants the repo’s `pnpm test` enforces,'),\n pc.dim('so the file lands green and you just commit + open a PR.'),\n ].join('\\n'),\n 'Welcome',\n );\n}\n\n// ---- Step 0: sanity-check we're inside an opuspopuli-regions checkout ----\nasync function resolveTargetDir(opts: RegionOptions): Promise<string> {\n const targetDir = opts.outDir ?? process.cwd();\n const looksRight = await looksLikeRegionsRepo(targetDir);\n if (!looksRight) {\n const proceed = unwrap(\n await p.confirm({\n message: `${targetDir} doesn't look like an opuspopuli-regions checkout (no schema/region-plugin.schema.json). Continue anyway?`,\n initialValue: false,\n }),\n );\n if (!proceed) {\n p.cancel('Cancelled — run again from your opuspopuli-regions checkout, or pass --out-dir.');\n process.exit(0);\n }\n }\n return targetDir;\n}\n\n// ---- Step 1: level ----\nasync function resolveLevel(opts: RegionOptions): Promise<RegionLevel> {\n return opts.level === 'state' || opts.level === 'county'\n ? opts.level\n : unwrap(\n await p.select({\n message: 'What level is this region?',\n options: [\n { value: 'state', label: 'State', hint: 'e.g. California' },\n { value: 'county', label: 'County', hint: 'e.g. Alameda, within California' },\n ],\n }),\n );\n}\n\n// Parent state slug — only prompted for counties.\nasync function resolveParentSlug(opts: RegionOptions, level: RegionLevel): Promise<string | undefined> {\n if (level !== 'county') return undefined;\n const parentSlug =\n opts.parent ??\n unwrap(\n await p.text({\n message: 'Parent state slug?',\n placeholder: 'california',\n validate: (v) =>\n isValidSlug(v ?? '') ? undefined : 'kebab-case (lowercase letters, digits, hyphens)',\n }),\n );\n if (!isValidSlug(parentSlug)) {\n p.cancel(`Parent slug \"${parentSlug}\" must be kebab-case.`);\n process.exit(1);\n }\n return parentSlug;\n}\n\n// ---- Step 2: identity (name, slug, parent, display, description) ----\nasync function collectIdentity(opts: RegionOptions, level: RegionLevel): Promise<RegionIdentity> {\n const rawName =\n opts.name ??\n unwrap(\n await p.text({\n message: level === 'county' ? 'County name?' : 'State name?',\n placeholder: level === 'county' ? 'Alameda' : 'California',\n validate: requireNonEmpty,\n }),\n );\n\n const parentSlug = await resolveParentSlug(opts, level);\n\n const ownSlug = slugify(rawName);\n const regionId = level === 'county' ? `${parentSlug}-${ownSlug}` : ownSlug;\n if (!isValidSlug(regionId)) {\n p.cancel(`Derived regionId \"${regionId}\" is not valid kebab-case. Try a simpler name.`);\n process.exit(1);\n }\n\n const displayName = unwrap(\n await p.text({\n message: 'Display name?',\n defaultValue: rawName,\n }),\n );\n const regionName = displayName || rawName;\n\n const description = unwrap(\n await p.text({\n message: 'One-line description of the data coverage?',\n placeholder:\n level === 'county'\n ? `Civic data for ${rawName} County`\n : `Civic data for the state of ${rawName}`,\n validate: requireNonEmpty,\n }),\n );\n\n return { rawName, parentSlug, ownSlug, regionId, regionName, description };\n}\n\n// ---- Step 3: codes (state code, FIPS, timezone) ----\nasync function collectCodes(opts: RegionOptions, level: RegionLevel): Promise<RegionCodes> {\n const stateCode = (\n opts.stateCode ??\n unwrap(\n await p.text({\n message: 'Two-letter state code?',\n placeholder: 'CA',\n validate: (v) =>\n isValidStateCode((v ?? '').toUpperCase()) ? undefined : 'Two letters, e.g. CA',\n }),\n )\n ).toUpperCase();\n if (!isValidStateCode(stateCode)) {\n p.cancel(`State code \"${stateCode}\" must be two letters.`);\n process.exit(1);\n }\n\n const fipsCode =\n opts.fips ??\n unwrap(\n await p.text({\n message: level === 'county' ? 'County FIPS (5 digits)?' : 'State FIPS (2 digits)?',\n placeholder: level === 'county' ? '06001' : '06',\n validate: (v) => {\n if (isValidFips(v ?? '', level)) return undefined;\n const expectedDigits = level === 'county' ? '5' : '2';\n return `Expected ${expectedDigits} digits`;\n },\n }),\n );\n if (!isValidFips(fipsCode, level)) {\n p.cancel(`FIPS \"${fipsCode}\" is the wrong length for a ${level}.`);\n process.exit(1);\n }\n\n const timezone =\n opts.timezone ??\n unwrap(\n await p.text({\n message: 'IANA timezone?',\n defaultValue: 'America/Los_Angeles',\n placeholder: 'America/Los_Angeles',\n validate: (v) =>\n isValidTimezone(v || 'America/Los_Angeles')\n ? undefined\n : 'Not a recognized IANA zone (e.g. America/New_York)',\n }),\n );\n\n return { stateCode, fipsCode, timezone };\n}\n\n// ---- Step 4: at least one data source ----\nasync function collectOneDataSource(index: number): Promise<DataSourceInput> {\n const url = unwrap(\n await p.text({\n message: `Data source #${index} — URL?`,\n placeholder: 'https://example.gov/meetings',\n validate: (v) => (/^https?:\\/\\//.test(v ?? '') ? undefined : 'Must start with http(s)://'),\n }),\n );\n const dataType = unwrap(\n await p.select({\n message: 'Data type?',\n options: DATA_TYPES.map((t) => ({ value: t, label: t })),\n }),\n ) as DataType;\n const sourceType = unwrap(\n await p.select({\n message: 'Source type?',\n initialValue: 'html_scrape' as SourceType,\n options: SOURCE_TYPES.map((t) => ({ value: t, label: t })),\n }),\n ) as SourceType;\n const contentGoal = unwrap(\n await p.text({\n message: 'Content goal (what should the scraper extract)?',\n placeholder: 'Fetch upcoming board meeting agendas and minutes',\n validate: requireNonEmpty,\n }),\n );\n const category = unwrap(\n await p.text({\n message: 'Category label (optional)?',\n placeholder: 'Board of Supervisors',\n }),\n );\n\n const src: DataSourceInput = { url, dataType, sourceType, contentGoal };\n if (category && category.trim().length > 0) src.category = category.trim();\n return src;\n}\n\nasync function collectDataSources(): Promise<DataSourceInput[]> {\n const dataSources: DataSourceInput[] = [];\n do {\n dataSources.push(await collectOneDataSource(dataSources.length + 1));\n const again = unwrap(\n await p.confirm({ message: 'Add another data source?', initialValue: false }),\n );\n if (!again) break;\n // eslint-disable-next-line no-constant-condition\n } while (true);\n return dataSources;\n}\n\n// ---- Step 5: build the RegionInput from the collected answers ----\nexport function buildRegionInput(args: {\n level: RegionLevel;\n identity: RegionIdentity;\n codes: RegionCodes;\n dataSources: DataSourceInput[];\n}): RegionInput {\n const { level, identity, codes, dataSources } = args;\n return {\n level,\n regionId: identity.regionId,\n displayName: identity.regionName,\n regionName: identity.regionName,\n description: identity.description,\n // New region configs start at 0.1.0 — the documented convention in the\n // regions repo's CLAUDE.md. Bump manually as the config matures.\n version: '0.1.0',\n timezone: codes.timezone,\n stateCode: codes.stateCode,\n fipsCode: codes.fipsCode,\n dataSources,\n ...(identity.parentSlug ? { parentRegionId: identity.parentSlug } : {}),\n ...(level === 'county' ? { countySlug: identity.ownSlug } : {}),\n };\n}\n\n// Build + validate the config; exits if the generated file would fail CI.\nfunction buildAndValidateConfig(input: RegionInput): RegionPluginFile {\n const file = buildRegionConfig(input);\n const issues = validateRegionConfig(file);\n if (issues.length > 0) {\n p.note(issues.map((i) => `${pc.red('•')} ${i}`).join('\\n'), 'Validation failed');\n p.cancel('The generated config would not pass the regions repo CI. Re-run and adjust.');\n process.exit(1);\n }\n return file;\n}\n\n// ---- Step 6: preview + write ----\nasync function writeRegionConfig(args: {\n opts: RegionOptions;\n targetDir: string;\n level: RegionLevel;\n identity: RegionIdentity;\n file: RegionPluginFile;\n}): Promise<void> {\n const { opts, targetDir, level, identity, file } = args;\n const relPath = regionFilePath({\n level,\n regionId: identity.regionId,\n ...(identity.parentSlug ? { parentRegionId: identity.parentSlug } : {}),\n ...(level === 'county' ? { countySlug: identity.ownSlug } : {}),\n });\n const absPath = resolve(targetDir, relPath);\n const json = `${JSON.stringify(file, null, 2)}\\n`;\n\n p.note(json, `${relPath} (preview)`);\n\n if (!opts.force && (await fileExists(absPath))) {\n p.cancel(`${relPath} already exists. Re-run with --force to overwrite.`);\n process.exit(1);\n }\n\n const write = unwrap(\n await p.confirm({ message: `Write ${relPath}?`, initialValue: true }),\n );\n if (!write) {\n p.cancel('Nothing written.');\n process.exit(0);\n }\n\n await mkdir(dirname(absPath), { recursive: true });\n await writeFile(absPath, json, 'utf8');\n\n p.note(\n [\n `${pc.green('✓')} Wrote ${pc.cyan(relPath)}`,\n '',\n 'Next steps in your opuspopuli-regions checkout:',\n pc.dim(' pnpm test # schema + hierarchy validation'),\n pc.dim(' pnpm test:connectivity # URL reachability (informational)'),\n pc.dim(` git add ${relPath} && git commit && open a PR`),\n ].join('\\n'),\n 'Done',\n );\n p.outro(pc.magenta(`Region scaffolded: ${identity.regionId}`));\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Heuristic: the regions repo always has `schema/region-plugin.schema.json`\n * and a top-level `regions/` directory. If both are present we're confident\n * we're in the right checkout; if neither we warn before writing anywhere. */\nasync function looksLikeRegionsRepo(dir: string): Promise<boolean> {\n const [hasSchema, hasRegions] = await Promise.all([\n fileExists(join(dir, 'schema', 'region-plugin.schema.json')),\n fileExists(join(dir, 'regions')),\n ]);\n return hasSchema && hasRegions;\n}\n","import { Command } from 'commander';\nimport pc from 'picocolors';\n\nimport { initCommand } from './commands/init.js';\nimport { bootstrapCommand } from './commands/bootstrap.js';\nimport { resetCommand } from './commands/reset.js';\nimport { verifyCommand } from './commands/verify.js';\nimport { regionCommand } from './commands/region.js';\n\n// release-please updates the string in `const VERSION = '...'` on each\n// release. See release-please-config.json's extra-files entry that points\n// at this file with type: generic — that scanner finds the version string\n// in package.json (via the manifest file) and updates literals on lines\n// like the one below.\n// x-release-please-start-version\nconst VERSION = '0.10.12';\n// x-release-please-end\n\nconst program = new Command();\n\nprogram\n .name('create-op-node')\n .description(\n 'Interactive bootstrap for an Opus Populi federation node.\\n' +\n 'Cloudflare infrastructure → Mac Studio → live public API.',\n )\n .version(VERSION, '-v, --version', 'show version');\n\nprogram.addCommand(initCommand);\nprogram.addCommand(bootstrapCommand);\nprogram.addCommand(resetCommand);\nprogram.addCommand(verifyCommand);\nprogram.addCommand(regionCommand);\n\n// When invoked with no subcommand, default to `init` — the create-* convention\n// is that `npx create-op-node` \"just works\" without specifying a subcommand.\nif (process.argv.length === 2) {\n process.argv.push('init');\n}\n\nawait program.parseAsync(process.argv).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`\\n${pc.red('✗')} ${msg}\\n`);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/constants.ts","../src/lib/cloudflare.ts","../src/lib/tfc.ts","../src/lib/exec.ts","../src/lib/keychain.ts","../src/lib/prompts.ts","../src/lib/github.ts","../src/lib/secrets.ts","../src/lib/polling.ts","../src/commands/init.ts","../src/lib/homebrew.ts","../src/lib/macos.ts","../src/lib/launchagent.ts","../src/lib/op-compose-script.ts","../src/lib/op-compose-install.ts","../src/lib/docker.ts","../src/lib/ollama.ts","../src/lib/noderepo.ts","../src/lib/assert.ts","../src/commands/bootstrap.ts","../src/commands/reset.ts","../src/lib/cosign.ts","../src/lib/http.ts","../src/lib/tls.ts","../src/commands/verify.ts","../src/lib/region-schema.json","../src/lib/region.ts","../src/commands/region.ts","../src/cli.ts"],"names":["result","password","p","p2","pc","fresh","v","mkdir","writeFile","chmod","text","join","homedir","Command","Option","resolveRegion","rm","save","REGION_RE","fileExists","access","p4","connect","resolve","DEFAULT_DEPS","tls","p5","phaseIcon","p6","dirname"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Shared invariants reused across libs + commands. Each constant has exactly\n * one definition so a format change can't drift between callers (which\n * happened during review: the pgsodium-key shape was hand-rolled in three\n * places).\n */\n\n/** A pgsodium master key is 32 bytes of CSPRNG output, encoded as 64\n * lowercase hex characters. Match it everywhere with this regex so an\n * uppercase-hex or wrong-length value gets a consistent reason. */\nexport const PGSODIUM_KEY_RE = /^[a-f0-9]{64}$/;\n\n/** Allowed character set for a Cloudflare Tunnel token before we\n * interpolate it into a launchd plist string. JWT-style tokens\n * (header.payload.signature) use base64-url — letters, digits, `-`,\n * `_`, `.`, `=`. We deliberately reject anything outside that set so\n * a crafted token can't inject XML attributes or break the plist\n * string content.\n *\n * Stricter than SAFE_LAUNCHCTL_VALUE_RE on purpose: Cloudflare Tunnel\n * tokens are guaranteed base64url by the issuer, so allowing `+` or `/`\n * here would silently accept malformed tokens that would later fail at\n * cloudflared startup with a less actionable error. Kept separate from\n * SAFE_LAUNCHCTL_VALUE_RE for that reason. */\nexport const TUNNEL_TOKEN_RE = /^[A-Za-z0-9_\\-.=]+$/;\n\n/** Operator-friendly path safety check used before interpolating a path\n * into a launchd `sh -c` command. Any shell metacharacter would let an\n * attacker-supplied path execute arbitrary code at every login. The set\n * permits everything macOS allows in a normal path (letters, digits,\n * `/`, `-`, `_`, `.`, space) — and rejects `;`, `$`, backticks, quotes,\n * newlines, etc. */\nexport const SAFE_PATH_RE = /^[A-Za-z0-9_\\-./ ]+$/;\n\n/** Character set allowed for any value we interpolate into the launchd\n * `sh -c` body as a `launchctl setenv VAR \"<value>\"` argument. Permits\n * every character that base64 (`+`, `/`, `=`), base64url (`-`, `_`), and\n * JWT (`.`) produce, plus alphanumerics — covers JWT_SECRET and the signed\n * Supabase tokens (which use JWT shape `xxx.yyy.zzz`). Rejects shell\n * metacharacters (`;`, `$`, backticks, quotes, spaces, newlines) that\n * would let a tampered value inject commands into the login session.\n *\n * POSTGRES_PASSWORD and DASHBOARD_PASSWORD use the stricter\n * URL_SAFE_PASSWORD_RE — they land in postgres:// URIs where `+`/`/`/`=`\n * cause parser ambiguity. */\nexport const SAFE_LAUNCHCTL_VALUE_RE = /^[A-Za-z0-9+/=._-]+$/;\n\n/** Subset of SAFE_LAUNCHCTL_VALUE_RE for values that ALSO land in URI\n * components (postgres:// connection strings, basic-auth headers).\n * base64url alphabet — no `+`, no `/`, no `=`. */\nexport const URL_SAFE_PASSWORD_RE = /^[A-Za-z0-9_-]+$/;\n\n/** Same shape as TUNNEL_TOKEN_RE but documented separately because the\n * SUPABASE_URL value also lands in the plist and we want to allow `://`\n * and `:` for the port. Letters, digits, `-`, `_`, `.`, `:`, `/`. */\nexport const SAFE_URL_RE = /^[A-Za-z0-9:/_.-]+$/;\n\n/** Default network timeout used by `verify`'s probes (TLS handshake, HTTP\n * GET /health, GraphQL POST). One number so tls.ts and http.ts don't drift. */\nexport const VERIFY_NETWORK_TIMEOUT_MS = 10_000;\n\n/** Per-request timeout for the Terraform Cloud + Cloudflare API helpers\n * (`tfc.ts`, `cloudflare.ts`). Deliberately separate from the `verify`\n * probe timeout: these are control-plane API calls, and the overall\n * apply-wait budget is governed by `polling.ts`, so each individual\n * request just needs a sane cap to fail fast on a stalled connection\n * instead of hanging `init` indefinitely. */\nexport const API_REQUEST_TIMEOUT_MS = 15_000;\n\n/** First N chars of a probe response body that get echoed back to the\n * operator for diagnostics. Capped low because the wizard renders this\n * inline; for the real body, use `curl -v` and friends. */\nexport const BODY_PREVIEW_MAX = 200;\n","/**\n * Cloudflare API helpers used by `create-op-node init`.\n *\n * The probe replicates what we built interactively on 2026-06-16: hit each of\n * the 5 endpoints we need so we know the token has every scope before going any\n * further. Failing early here saves a ~60-second Terraform plan that would fail\n * with a less useful error.\n *\n * Account-owned tokens (`cfat_…`) cannot use `/user/tokens/verify`. We hit\n * `/accounts/{id}/tokens/verify` for validity and the 5 resource endpoints for\n * scope coverage.\n */\n\nimport { API_REQUEST_TIMEOUT_MS } from './constants.js';\n\nconst CF_API = 'https://api.cloudflare.com/client/v4';\n\ninterface ProbeInput {\n token: string;\n accountId: string;\n zoneId: string;\n}\n\nexport interface ProbeResult {\n ok: boolean;\n issues: string[];\n}\n\n/**\n * GET a Cloudflare API path as JSON, with a hard per-request timeout.\n *\n * Native `fetch` has no default timeout, so a stalled connection would hang\n * `init` indefinitely (`probeCloudflareToken` makes 6 sequential calls). We\n * wrap the call in an `AbortController` and, on any throw (timeout / DNS blip\n * / TLS reset / proxy error), return `{ status: 0, body: null }`. Callers\n * treat a non-200 status as a soft failure, so a `0` degrades to a\n * network-error message instead of rejecting out of the wizard.\n */\nasync function get(\n token: string,\n path: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<{ status: number; body: unknown }> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), API_REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(`${CF_API}${path}`, {\n headers: { Authorization: `Bearer ${token}` },\n signal: ctrl.signal,\n });\n let body: unknown = null;\n try {\n body = await res.json();\n } catch {\n /* non-JSON body — leave as null */\n }\n return { status: res.status, body };\n } catch {\n // Timeout (AbortError) or any network-layer throw. status 0 = \"never got\n // a response\" — see the docstring above.\n return { status: 0, body: null };\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction shortError(body: unknown): string {\n if (\n typeof body === 'object' &&\n body !== null &&\n 'errors' in body &&\n Array.isArray((body as { errors: unknown[] }).errors)\n ) {\n const errs = (body as { errors: Array<{ message?: string; code?: number }> }).errors;\n return errs\n .map((e) => {\n const prefix = e.code ? `CF ${e.code}: ` : '';\n return `${prefix}${e.message ?? 'unknown'}`;\n })\n .join('; ');\n }\n return 'no error message returned';\n}\n\ninterface ScopeCheck {\n name: string;\n path: string;\n /** Endpoints that 404 when the underlying feature isn't enabled but the scope\n * IS present (e.g. R2 before \"Enable R2\"). We treat those as passes with a\n * note rather than failures. */\n treat404AsPass?: boolean;\n}\n\nexport async function probeCloudflareToken(input: ProbeInput): Promise<ProbeResult> {\n const issues: string[] = [];\n\n // ---- Validity probe (Account-owned token endpoint) ----\n const verify = await get(input.token, `/accounts/${input.accountId}/tokens/verify`);\n if (verify.status === 0) {\n issues.push(\n \"Couldn't reach Cloudflare (network error or timeout). Check your connection and retry.\",\n );\n return { ok: false, issues };\n }\n if (verify.status !== 200) {\n issues.push(\n `Token verify failed (HTTP ${verify.status}): ${shortError(verify.body)}`,\n );\n return { ok: false, issues };\n }\n\n // ---- Scope probes ----\n const checks: ScopeCheck[] = [\n { name: 'Zone : Zone : Read', path: `/zones/${input.zoneId}` },\n { name: 'Zone : DNS : Edit', path: `/zones/${input.zoneId}/dns_records?per_page=1` },\n { name: 'Account : Cloudflare Tunnel : Edit', path: `/accounts/${input.accountId}/cfd_tunnel` },\n { name: 'Account : Workers R2 Storage : Edit', path: `/accounts/${input.accountId}/r2/buckets` },\n { name: 'Account : Cloudflare Pages : Edit', path: `/accounts/${input.accountId}/pages/projects` },\n ];\n\n for (const check of checks) {\n const res = await get(input.token, check.path);\n if (res.status === 200) continue;\n if (res.status === 404 && check.treat404AsPass) continue;\n if (res.status === 0) {\n issues.push(`Couldn't reach Cloudflare while checking ${check.name} (network error or timeout).`);\n } else if (res.status === 401 || res.status === 403) {\n issues.push(`Missing scope: ${check.name}`);\n } else if (\n res.status === 400 &&\n typeof res.body === 'object' &&\n res.body !== null &&\n 'errors' in res.body &&\n Array.isArray((res.body as { errors: Array<{ code?: number }> }).errors) &&\n (res.body as { errors: Array<{ code?: number }> }).errors.some((e) => e.code === 10042)\n ) {\n // R2 not enabled yet — actionable, not a scope problem.\n issues.push(\n `R2 not enabled on this account. ` +\n `Enable it once in Cloudflare dashboard → R2 → Get started, then re-run.`,\n );\n } else {\n issues.push(`${check.name} probe returned HTTP ${res.status}: ${shortError(res.body)}`);\n }\n }\n\n return { ok: issues.length === 0, issues };\n}\n\n/* ------------------------------------------------------------------ *\n * Tunnel-status probe (used by `verify`, not `init`) *\n * ------------------------------------------------------------------ */\n\nexport interface TunnelStatusInput {\n token: string;\n accountId: string;\n tunnelId: string;\n /** Injectable for tests. */\n fetchImpl?: typeof fetch;\n}\n\nexport interface TunnelStatusOk {\n ok: true;\n /** Active connector connections registered with Cloudflare's edge. Zero on\n * a freshly-created tunnel that hasn't been started, > 0 on a healthy one. */\n connections: number;\n /** Cloudflare's own status field — `healthy`, `degraded`, `inactive`, etc. */\n status: string;\n}\n\nexport interface TunnelStatusFailed {\n ok: false;\n reason: string;\n}\n\nexport type TunnelStatusResult = TunnelStatusOk | TunnelStatusFailed;\n\ninterface CfTunnelEnvelope {\n result?: {\n status?: string;\n connections?: Array<unknown>;\n };\n}\n\n/**\n * Look up a single tunnel's current edge-side status. The CF API endpoint\n * returns `connections: []` until at least one cloudflared connector\n * registers — useful as a verify signal that the Studio's cloudflared is\n * actually online.\n */\nexport async function tunnelStatus(input: TunnelStatusInput): Promise<TunnelStatusResult> {\n const fetchImpl = input.fetchImpl ?? fetch;\n try {\n const res = await get(\n input.token,\n `/accounts/${input.accountId}/cfd_tunnel/${input.tunnelId}`,\n fetchImpl,\n );\n if (res.status === 0) {\n return { ok: false, reason: \"couldn't reach Cloudflare (network error or timeout)\" };\n }\n if (res.status !== 200) {\n return {\n ok: false,\n reason: `tunnel lookup failed (HTTP ${res.status}): ${shortError(res.body)}`,\n };\n }\n const env = res.body as CfTunnelEnvelope;\n const status = env.result?.status ?? '<no status>';\n const connections = env.result?.connections?.length ?? 0;\n return { ok: true, connections, status };\n } catch (err) {\n return { ok: false, reason: `tunnel lookup threw: ${(err as Error).message}` };\n }\n}\n","/**\n * Terraform Cloud (HCP Terraform) API helpers used by `create-op-node init`.\n *\n * We hit a tiny subset of the TFC v2 API directly via native `fetch` — no\n * client library. Three needs:\n *\n * 1. Verify the operator's TFC token is valid and has access to the org\n * they typed.\n * 2. Resolve a workspace by tag set so we can poll its state for outputs.\n * 3. Fetch the Tunnel token output after `terraform apply` completes.\n *\n * The TFC API responds with JSON:API-shaped documents; helpers below narrow\n * each call to the minimal shape we actually consume.\n */\n\nimport { API_REQUEST_TIMEOUT_MS } from './constants.js';\n\nconst TFC_API = 'https://app.terraform.io/api/v2';\n\n/** TFC organization slug rules: alphanumerics, underscores, hyphens; the API\n * doesn't formally publish a max but slugs over 40 chars are rejected in\n * practice. We validate before any URL interpolation to neutralise typos\n * that would otherwise hit unintended endpoints (e.g. `?` or `/` in the\n * slug bouncing us into a different route). */\nconst ORG_SLUG_RE = /^[A-Za-z0-9_-]{1,40}$/;\n\nexport function isValidTfcOrgSlug(slug: string): boolean {\n return ORG_SLUG_RE.test(slug);\n}\n\ninterface TfcAuth {\n token: string;\n organization: string;\n}\n\ntype Headers = Record<string, string>;\n\nfunction authHeaders(token: string): Headers {\n return {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/vnd.api+json',\n };\n}\n\n/**\n * GET a TFC API path as JSON, with a hard per-request timeout.\n *\n * A stalled or half-open connection (native `fetch` has no default timeout)\n * would otherwise hang `init` — including the ~10-minute apply-wait in\n * `polling.ts` — forever. We wrap the call in an `AbortController` and, on\n * any throw (timeout / DNS blip / TLS reset / proxy error), return\n * `{ status: 0, body: null }`. Every caller already treats a non-200 status\n * as a soft failure, so a `0` degrades to `null` / a network-error message\n * instead of rejecting out of the poll loop and crashing the wizard.\n */\nasync function getJson(\n token: string,\n path: string,\n): Promise<{ status: number; body: unknown }> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), API_REQUEST_TIMEOUT_MS);\n try {\n const res = await fetch(`${TFC_API}${path}`, {\n headers: authHeaders(token),\n signal: ctrl.signal,\n });\n let body: unknown = null;\n try {\n body = await res.json();\n } catch {\n /* non-JSON body — leave as null */\n }\n return { status: res.status, body };\n } catch {\n // Timeout (AbortError) or any network-layer throw. status 0 = \"never got\n // a response\" — see the docstring above.\n return { status: 0, body: null };\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport interface TfcProbeResult {\n ok: boolean;\n /** TFC user's display name when the token belongs to a user (`null` when it's a team / org token). */\n userName?: string;\n issues: string[];\n}\n\n/**\n * Sanity-check the token + organization at the same time:\n *\n * - GET /account/details — confirms the token itself is valid.\n * - GET /organizations/{org} — confirms the org exists AND that the token\n * has the membership/permissions to see it.\n *\n * Both must pass before we let the wizard proceed; a token that's valid but\n * scoped to a different org would silently fail at the workspace step.\n */\nexport async function probeTfcToken(input: TfcAuth): Promise<TfcProbeResult> {\n const issues: string[] = [];\n\n if (!isValidTfcOrgSlug(input.organization)) {\n issues.push(\n `Organization \"${input.organization}\" isn't a valid TFC slug (letters, digits, hyphens, underscores; up to 40 chars).`,\n );\n return { ok: false, issues };\n }\n\n const account = await getJson(input.token, '/account/details');\n if (account.status === 0) {\n issues.push(\n \"Couldn't reach Terraform Cloud (network error or timeout). Check your connection and retry.\",\n );\n return { ok: false, issues };\n }\n if (account.status !== 200) {\n issues.push(\n `TFC token invalid (HTTP ${account.status}). Regenerate at https://app.terraform.io/app/settings/tokens.`,\n );\n return { ok: false, issues };\n }\n const userName = extractUserName(account.body);\n\n const org = await getJson(\n input.token,\n `/organizations/${encodeURIComponent(input.organization)}`,\n );\n if (org.status === 0) {\n issues.push(\n \"Couldn't reach Terraform Cloud while checking the organization (network error or timeout).\",\n );\n } else if (org.status === 404) {\n issues.push(\n `TFC organization \"${input.organization}\" not found, or this token lacks access. Check the org slug at https://app.terraform.io.`,\n );\n } else if (org.status === 401 || org.status === 403) {\n issues.push(\n `TFC token doesn't have permission to access org \"${input.organization}\".`,\n );\n } else if (org.status !== 200) {\n issues.push(`TFC org probe returned HTTP ${org.status}.`);\n }\n\n return {\n ok: issues.length === 0,\n issues,\n ...(userName ? { userName } : {}),\n };\n}\n\nfunction extractUserName(body: unknown): string | undefined {\n if (\n typeof body === 'object' &&\n body !== null &&\n 'data' in body &&\n typeof (body as { data: unknown }).data === 'object'\n ) {\n const data = (body as { data: { attributes?: { username?: string } } }).data;\n return data.attributes?.username;\n }\n return undefined;\n}\n\nexport interface FindWorkspaceInput extends TfcAuth {\n /** Tag set the workspace must carry. For our use case: `['opuspopuli', 'cloudflare']`. */\n tags: string[];\n /** Optional name to disambiguate when multiple workspaces share the tag set. */\n name?: string;\n}\n\nexport interface TfcWorkspace {\n id: string;\n name: string;\n /** Latest run id, used to poll for apply completion. */\n currentRunId: string | null;\n}\n\n/**\n * Find the workspace this region's Terraform code will run in.\n *\n * TFC's filter syntax for tags is `filter[tagged]=tag1,tag2`. We ask for all\n * matches and let the caller pick by `name` when there's ambiguity (one TFC\n * org can host many workspaces with the same tag set).\n */\nexport async function findWorkspace(input: FindWorkspaceInput): Promise<TfcWorkspace | null> {\n if (!isValidTfcOrgSlug(input.organization)) return null;\n const tagFilter = encodeURIComponent(input.tags.join(','));\n const res = await getJson(\n input.token,\n `/organizations/${encodeURIComponent(input.organization)}/workspaces?filter[tagged]=${tagFilter}&page[size]=100`,\n );\n if (res.status !== 200) return null;\n\n const items = extractWorkspaceList(res.body);\n if (items.length === 0) return null;\n\n const match = input.name ? items.find((w) => w.name === input.name) : items[0];\n return match ?? null;\n}\n\ninterface RawWorkspace {\n id: string;\n attributes?: { name?: string };\n relationships?: { 'current-run'?: { data?: { id?: string } | null } };\n}\n\nfunction extractWorkspaceList(body: unknown): TfcWorkspace[] {\n if (\n typeof body !== 'object' ||\n body === null ||\n !('data' in body) ||\n !Array.isArray((body as { data: unknown }).data)\n ) {\n return [];\n }\n const data = (body as { data: RawWorkspace[] }).data;\n return data.map((w) => ({\n id: w.id,\n name: w.attributes?.name ?? '',\n currentRunId: w.relationships?.['current-run']?.data?.id ?? null,\n }));\n}\n\nexport interface TfcRunStatus {\n id: string;\n status: string;\n /** `true` once the run reached a terminal state (applied / errored / canceled / discarded). */\n finished: boolean;\n /** `true` only when the run finished successfully (`applied`). */\n succeeded: boolean;\n}\n\nconst TERMINAL_STATUSES = new Set([\n 'applied',\n 'errored',\n 'canceled',\n 'discarded',\n 'policy_soft_failed',\n 'force_canceled',\n]);\n\n/**\n * Look up a single TFC run by id. Used while we're waiting for the first\n * `terraform apply` to finish.\n */\nexport async function getRunStatus(\n auth: TfcAuth,\n runId: string,\n): Promise<TfcRunStatus | null> {\n // runId comes from a previous TFC response — trusted shape — but\n // encodeURIComponent is cheap defense if it's ever sourced from elsewhere.\n const res = await getJson(auth.token, `/runs/${encodeURIComponent(runId)}`);\n if (res.status !== 200) return null;\n\n const body = res.body as {\n data?: { id?: string; attributes?: { status?: string } };\n };\n const id = body.data?.id;\n const status = body.data?.attributes?.status;\n if (!id || !status) return null;\n\n return {\n id,\n status,\n finished: TERMINAL_STATUSES.has(status),\n succeeded: status === 'applied',\n };\n}\n\n/**\n * Pull a named output value from a workspace's current state version.\n * Returns `null` when:\n *\n * - the workspace, token, or HTTP call fails (any non-200 status)\n * - the named output isn't present in the response\n * - the output value isn't a string (e.g. the operator changed the type)\n *\n * Caller should poll the matching run for `applied` status first; an\n * in-flight workspace returns a 404 / 425 here.\n */\nexport async function fetchOutput(\n auth: TfcAuth,\n workspaceId: string,\n outputName: string,\n): Promise<string | null> {\n const res = await getJson(\n auth.token,\n `/workspaces/${encodeURIComponent(workspaceId)}/current-state-version-outputs`,\n );\n if (res.status !== 200) return null;\n\n const body = res.body as {\n data?: Array<{ attributes?: { name?: string; value?: unknown; sensitive?: boolean } }>;\n };\n const match = body.data?.find((o) => o.attributes?.name === outputName);\n if (!match) return null;\n\n const value = match.attributes?.value;\n return typeof value === 'string' ? value : null;\n}\n","/**\n * Shared `execa` wrapper for the few CLIs the wizard shells out to (`op`, `gh`).\n *\n * Two patterns this exists to share:\n *\n * 1. `reject: false` is opt-out on every call, since we want to inspect the\n * exit code rather than have a thrown error fan out across the wizard.\n * 2. **ENOENT doesn't suppress** under `reject: false` — that's a spawn\n * error, not a child-process exit. Callers that don't catch it crash.\n * `safeExeca` traps `ENOENT` / `ENOTDIR` and returns `null` so callers\n * can branch on \"binary not installed at all\" cleanly.\n *\n * The shape kept narrow on purpose — adds nothing execa doesn't, just makes\n * the failure modes uniform across call sites.\n */\n\nimport { execa, ExecaError } from 'execa';\n\nexport interface SafeExecaResult {\n /** Exit code from the child. `undefined` when the child was killed by a\n * signal — we pass it through honestly so callers can distinguish\n * signal-killed from clean zero. */\n exitCode: number | undefined;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Run a command; return `null` when the binary isn't on PATH at all, an\n * object with exit code + output otherwise. Never throws on a missing\n * binary, never throws on a non-zero exit.\n */\nexport async function safeExeca(\n cmd: string,\n args: string[],\n options?: {\n input?: string;\n /** Working directory for the child. Defaults to the parent's cwd. */\n cwd?: string;\n /** Extra env vars merged into the child's env (execa's default\n * extendEnv: true means these add to process.env rather than\n * replace). Used by bootstrap's compose subprocess calls so the\n * Keychain-loaded secrets reach docker compose without first\n * being written to a plaintext .env file on disk. */\n env?: NodeJS.ProcessEnv;\n },\n): Promise<SafeExecaResult | null> {\n try {\n const result = await execa(cmd, args, { reject: false, ...options });\n return {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n };\n } catch (err) {\n const e = err as ExecaError & NodeJS.ErrnoException;\n if (e.code === 'ENOENT' || e.code === 'ENOTDIR') return null;\n throw err;\n }\n}\n","/**\n * macOS Keychain wrapper around the built-in `security` CLI.\n *\n * Replaces the 1Password integration as of v0.3.0: secrets live in the\n * operator's login keychain (FileVault-encrypted at rest, locked with\n * the user session). Generic-password items only — we don't need\n * internet-password semantics.\n *\n * **Cross-device caveat:** the `security` CLI cannot create iCloud-\n * Keychain-synchronizable items (no `kSecAttrSynchronizable` flag is\n * exposed). Items written here stay on the machine they were written\n * on. `init` writes on the laptop; `bootstrap` reads on the Studio.\n * On a Studio miss, bootstrap falls back to prompting the operator to\n * paste the value and persists it locally for re-runs.\n *\n * **Argv exposure caveat:** `security add-generic-password -w <value>`\n * passes the secret via argv. It's briefly visible to anyone running\n * `ps -E` while the child is alive. Same risk model as the\n * `op item create notesPlain=<value>` pattern we previously accepted.\n * If a future `security` release adds a stdin form, swap to it here.\n */\n\nimport { safeExeca } from './exec.js';\n\n/** Reverse-DNS prefix for all Opus Populi entries in Keychain Access. */\nconst SERVICE_PREFIX = 'org.opuspopuli';\n\nexport type SecretAccount =\n | 'pgsodium-root-key'\n | 'tunnel-token'\n | 'postgres-password'\n | 'jwt-secret'\n | 'supabase-anon-key'\n | 'supabase-service-role-key'\n | 'dashboard-password'\n | 'prompts-db-password'\n | 'prompt-service-api-key'\n | 'prompt-service-admin-api-key';\n\nexport interface SecretCoordinates {\n /** Region label, used to scope the service identifier. */\n region: string;\n /** Which secret within the region. */\n account: SecretAccount;\n}\n\nfunction serviceFor(region: string): string {\n return `${SERVICE_PREFIX}.${region}`;\n}\n\nconst FRIENDLY: Record<SecretAccount, string> = {\n 'pgsodium-root-key': 'pgsodium root key',\n 'tunnel-token': 'Cloudflare Tunnel token',\n 'postgres-password': 'Postgres password',\n 'jwt-secret': 'JWT signing secret',\n 'supabase-anon-key': 'Supabase anon key',\n 'supabase-service-role-key': 'Supabase service role key',\n 'dashboard-password': 'Supabase Studio dashboard password',\n 'prompts-db-password': 'prompt-service Postgres password',\n 'prompt-service-api-key': 'prompt-service HMAC API key',\n 'prompt-service-admin-api-key': 'prompt-service admin API key',\n};\n\nfunction labelFor(coords: SecretCoordinates): string {\n return `Opus Populi (${coords.region}) — ${FRIENDLY[coords.account]}`;\n}\n\nexport interface KeychainAvailability {\n /** True when the `security` CLI ran cleanly (macOS or compatible). On\n * non-macOS hosts this is false and callers should fall back to\n * prompt-only flows. */\n available: boolean;\n /** Free-text reason when unavailable. */\n reason?: string;\n}\n\nexport async function detectKeychain(): Promise<KeychainAvailability> {\n const res = await safeExeca('security', ['-h']);\n if (res === null) {\n return {\n available: false,\n reason: '`security` CLI not on PATH (Keychain requires macOS)',\n };\n }\n return { available: true };\n}\n\nexport interface SaveSecretResult {\n written: boolean;\n /** True when an item already existed and was updated (via -U upsert). */\n updated: boolean;\n reason?: string;\n}\n\n/**\n * Write a generic-password item, upserting if it already exists. Uses\n * `add-generic-password -U` so re-runs don't error on duplicates.\n */\nexport async function saveSecret(\n coords: SecretCoordinates,\n value: string,\n): Promise<SaveSecretResult> {\n const service = serviceFor(coords.region);\n const label = labelFor(coords);\n\n // Check whether the item exists ahead of the upsert so we can report\n // `updated: true` vs `written: true` to the caller (purely informational —\n // the operator sees a different message in the wizard).\n const existing = await safeExeca('security', [\n 'find-generic-password',\n '-s',\n service,\n '-a',\n coords.account,\n ]);\n const updated = existing !== null && existing.exitCode === 0;\n\n const res = await safeExeca('security', [\n 'add-generic-password',\n '-U', // upsert\n '-s', service,\n '-a', coords.account,\n '-l', label,\n '-D', 'Opus Populi secret',\n '-w', value, // argv-exposure caveat, see file header\n ]);\n if (res === null) {\n return { written: false, updated: false, reason: '`security` CLI not on PATH' };\n }\n if (res.exitCode !== 0) {\n return {\n written: false,\n updated,\n reason: `security add-generic-password failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}${formatKeychainHint(res.exitCode)}`,\n };\n }\n return { written: true, updated };\n}\n\n/**\n * Read a generic-password item by service + account. Returns `null` when\n * the item doesn't exist, `security` isn't available, or the value is\n * empty. Callers branch to a paste prompt on `null`.\n */\nexport async function readSecret(coords: SecretCoordinates): Promise<string | null> {\n const service = serviceFor(coords.region);\n\n const res = await safeExeca('security', [\n 'find-generic-password',\n '-s', service,\n '-a', coords.account,\n '-w', // print the password to stdout (final flag = read mode)\n ]);\n if (res === null || res.exitCode !== 0) return null;\n const value = res.stdout.trim();\n return value.length > 0 ? value : null;\n}\n\n/** Delete a generic-password item. Idempotent — missing items return ok. */\nexport async function deleteSecret(coords: SecretCoordinates): Promise<{ ok: boolean; reason?: string }> {\n const service = serviceFor(coords.region);\n\n const res = await safeExeca('security', [\n 'delete-generic-password',\n '-s', service,\n '-a', coords.account,\n ]);\n if (res === null) return { ok: false, reason: '`security` CLI not on PATH' };\n // Exit 44 (errSecItemNotFound) is fine — already gone.\n if (res.exitCode === 0 || res.exitCode === ERR_SEC_ITEM_NOT_FOUND) return { ok: true };\n return {\n ok: false,\n reason: `security delete-generic-password failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}${formatKeychainHint(res.exitCode)}`,\n };\n}\n\n/**\n * macOS `security` exit codes we care about. Defined as constants so callers\n * can reason about them without sprinkling magic numbers.\n * 36 = errSecInteractionNotAllowed — keychain is locked / no UI session\n * 44 = errSecItemNotFound — item doesn't exist (treated as \"ok\" for delete)\n */\nexport const ERR_SEC_INTERACTION_NOT_ALLOWED = 36;\nexport const ERR_SEC_ITEM_NOT_FOUND = 44;\n\n/** Append an operator-friendly remediation hint to a `security` error\n * message when the exit code maps to one we recognize. Returns empty\n * string when no hint applies, so the call site can safely concatenate. */\nfunction formatKeychainHint(exitCode: number | null | undefined): string {\n if (exitCode === ERR_SEC_INTERACTION_NOT_ALLOWED) {\n return (\n `\\n` +\n `Hint: the login keychain is locked (SSH sessions don't auto-unlock it).\\n` +\n `Run \\`security unlock-keychain ~/Library/Keychains/login.keychain-db\\` and re-run bootstrap.`\n );\n }\n return '';\n}\n\n/**\n * Probe whether the login keychain is currently locked. Implemented by\n * attempting a no-op `find-generic-password` against a service that won't\n * exist: exit 44 (errSecItemNotFound) → unlocked, exit 36 → locked.\n *\n * Used by bootstrap to proactively prompt SSH operators for their login\n * password before the first Keychain write — without this, the operator\n * gets nine identical failures (one per secret) before they figure out\n * the keychain is locked.\n */\nexport async function isKeychainLocked(): Promise<boolean> {\n const res = await safeExeca('security', [\n 'find-generic-password',\n '-s',\n `${SERVICE_PREFIX}.__op_node_lock_probe__`,\n '-a',\n '__nothing_here__',\n ]);\n if (res === null) return false; // no security CLI; can't be locked\n return res.exitCode === ERR_SEC_INTERACTION_NOT_ALLOWED;\n}\n\nexport interface UnlockResult {\n ok: boolean;\n reason?: string;\n}\n\n/**\n * Unlock the login keychain via `security unlock-keychain -p <password>`.\n *\n * argv-exposure caveat: the password is visible briefly to `ps -E` while\n * the security child is alive. Same risk model as `saveSecret` writing\n * the secret value via `-w`. The `security` CLI doesn't expose a stdin\n * password form for unlock, so this is the cleanest option available.\n *\n * Callers should prompt the operator via clack's `p.password()` (which\n * doesn't echo) and pass the value here.\n */\nexport async function unlockKeychain(password: string): Promise<UnlockResult> {\n const res = await safeExeca('security', [\n 'unlock-keychain',\n '-p',\n password,\n // Default keychain path — same as the operator's GUI login keychain\n // on a stock macOS install. Lets us avoid a homedir lookup here.\n `${process.env['HOME'] ?? ''}/Library/Keychains/login.keychain-db`,\n ]);\n if (res === null) return { ok: false, reason: '`security` CLI not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `security unlock-keychain failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\n/** Heuristic: are we running inside an SSH session?\n * `SSH_CONNECTION` is set by sshd on every interactive login. `SSH_TTY`\n * is set on TTY-allocated sessions; we check both. Process-env only —\n * no syscalls. */\nexport function isSshSession(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env['SSH_CONNECTION'] ?? env['SSH_TTY']);\n}\n\n/** Exported for tests + the rare caller that needs the raw service string. */\nexport const _internal = {\n serviceFor,\n labelFor,\n SERVICE_PREFIX,\n};\n","/**\n * Tiny shared helper around @clack/prompts' cancel sentinel.\n *\n * Every wizard subcommand wants the same shape: ask for a value, if the\n * operator hit Ctrl-C / Esc, exit cleanly with a \"Cancelled.\" note. Without\n * this helper each call site duplicates the `p.isCancel` check + `p.cancel`\n * + `process.exit(0)`.\n *\n * Keeping it dead-simple — no return-value transformation, no async, no\n * exit-code override. Subcommands that want a different exit policy\n * shouldn't use this helper.\n */\n\nimport * as p from '@clack/prompts';\n\nexport function unwrap<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n return value;\n}\n","/**\n * GitHub helpers used by `create-op-node init`.\n *\n * Mix of two clients on purpose:\n *\n * - Octokit (REST) for typed API calls — create-from-template, content\n * write, PR open. These return well-shaped data we care about (URLs,\n * SHAs).\n * - `gh` CLI shell-out for repository secret seeding. Secrets need to be\n * encrypted with the repo's libsodium public key before PUT — Octokit\n * doesn't bundle libsodium and the wrapper packages are ~800 KB.\n * `gh secret set` does the encryption transparently. The operator\n * already has `gh` (it's part of the runbook), so the dep is free.\n *\n * The Octokit instance is created lazily so a missing token surfaces as a\n * clear error rather than a cryptic auth failure inside a downstream call.\n */\n\nimport { Octokit } from '@octokit/rest';\n\nimport { safeExeca } from './exec.js';\n\nexport interface GhAuth {\n /** A GitHub Personal Access Token (Classic or Fine-grained) with at least\n * `repo` scope. */\n token: string;\n}\n\n// One Octokit per token — fine for a one-shot CLI. NOT safe to wire into a\n// long-running service that issues calls under different identities; the\n// memoization will hand out the wrong client. If that ever happens, key the\n// cache by (token, …other-dimensions) or drop the memoization.\nlet _client: Octokit | null = null;\nlet _clientToken: string | null = null;\n\nfunction client(token: string): Octokit {\n if (_client && _clientToken === token) return _client;\n _client = new Octokit({ auth: token });\n _clientToken = token;\n return _client;\n}\n\n// Test-only: reset the memoized client between cases. Not exported via\n// index, intentionally — tests reach into the module.\nexport function _resetClient(): void {\n _client = null;\n _clientToken = null;\n}\n\n// ----------------------------------------------------------------------------\n// Create from template\n// ----------------------------------------------------------------------------\n\nexport interface CreateFromTemplateInput extends GhAuth {\n /** `<owner>/<repo>` of the template repo, e.g. `OpusPopuli/opuspopuli-node`. */\n template: string;\n /** The new repo's owner (user or org). */\n owner: string;\n /** The new repo's name. */\n name: string;\n /** Optional repo description. */\n description?: string;\n /** When true, create the repo as private. Default: false (public). */\n private?: boolean;\n /** Include all template branches, not just default. Default: false. */\n includeAllBranches?: boolean;\n}\n\nexport interface CreatedRepo {\n fullName: string;\n htmlUrl: string;\n defaultBranch: string;\n}\n\n/**\n * Create a new repository from a template repository. Wraps\n * `POST /repos/{template_owner}/{template_repo}/generate`.\n *\n * Caller should handle \"repository already exists\" as a recoverable case —\n * the operator may have started + abandoned a previous run. We throw on the\n * 422 (already exists) so the caller can show a \"use existing? overwrite?\"\n * prompt.\n */\nexport async function createRepoFromTemplate(\n input: CreateFromTemplateInput,\n): Promise<CreatedRepo> {\n const [templateOwner, templateRepo] = input.template.split('/');\n if (!templateOwner || !templateRepo) {\n throw new Error(`Bad template spec \"${input.template}\" — expected <owner>/<repo>`);\n }\n\n const res = await client(input.token).request(\n 'POST /repos/{template_owner}/{template_repo}/generate',\n {\n template_owner: templateOwner,\n template_repo: templateRepo,\n owner: input.owner,\n name: input.name,\n private: input.private ?? false,\n include_all_branches: input.includeAllBranches ?? false,\n ...(input.description ? { description: input.description } : {}),\n },\n );\n\n return {\n fullName: res.data.full_name,\n htmlUrl: res.data.html_url,\n defaultBranch: res.data.default_branch ?? 'main',\n };\n}\n\n// ----------------------------------------------------------------------------\n// Seed secrets via gh CLI\n// ----------------------------------------------------------------------------\n\nexport interface SetRepoSecretInput {\n /** `<owner>/<repo>`. */\n repo: string;\n /** Secret name (e.g. `CLOUDFLARE_API_TOKEN`). */\n name: string;\n /** Secret value. Passed via stdin to `gh secret set` so it never lands in\n * argv or the shell history. */\n value: string;\n}\n\nexport interface SetSecretResult {\n written: boolean;\n reason?: string;\n}\n\n/**\n * Set a single repository Actions secret via `gh secret set`. Value is piped\n * on stdin — never on argv — so it doesn't land in process listing or any\n * shell history. Returns `written: false` with a clear reason when `gh`\n * isn't installed (B2 — required for the `--gh-token` escape hatch where the\n * operator supplies a PAT and may not have `gh` at all).\n */\nexport async function setRepoSecret(input: SetRepoSecretInput): Promise<SetSecretResult> {\n const res = await safeExeca(\n 'gh',\n ['secret', 'set', input.name, '--repo', input.repo, '--body', '-'],\n { input: input.value },\n );\n if (res === null) {\n return {\n written: false,\n reason: '`gh` CLI not installed — install from https://cli.github.com or seed secrets manually',\n };\n }\n if (res.exitCode !== 0) {\n return {\n written: false,\n reason: `gh secret set failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { written: true };\n}\n\n// ----------------------------------------------------------------------------\n// Content write + PR open\n// ----------------------------------------------------------------------------\n\nexport interface CommitFileInput extends GhAuth {\n /** `<owner>/<repo>`. */\n repo: string;\n /** Branch to commit on. The caller creates the branch first via\n * `createBranch` when committing to a non-default branch. */\n branch: string;\n /** Repo-relative path (e.g. `infra/cloudflare/environments/prod.tfvars`). */\n path: string;\n /** File contents, plain text. We base64-encode for the API. */\n content: string;\n /** Commit message. */\n message: string;\n}\n\nexport interface CommitFileResult {\n commitSha: string;\n contentSha: string;\n}\n\n/**\n * Create or update a file in a repo's branch via the Contents API. Handles\n * both cases transparently — looks up the existing file's SHA when present\n * and includes it in the update.\n */\nexport async function commitFile(input: CommitFileInput): Promise<CommitFileResult> {\n const [owner, repo] = input.repo.split('/');\n if (!owner || !repo) {\n throw new Error(`Bad repo \"${input.repo}\" — expected <owner>/<repo>`);\n }\n\n const octokit = client(input.token);\n\n let existingSha: string | undefined;\n try {\n const existing = await octokit.repos.getContent({\n owner,\n repo,\n path: input.path,\n ref: input.branch,\n });\n if (!Array.isArray(existing.data) && existing.data.type === 'file') {\n existingSha = existing.data.sha;\n }\n } catch (err: unknown) {\n // 404 is fine — file just doesn't exist yet. Re-throw anything else.\n if (!is404(err)) throw err;\n }\n\n const res = await octokit.repos.createOrUpdateFileContents({\n owner,\n repo,\n path: input.path,\n branch: input.branch,\n message: input.message,\n content: Buffer.from(input.content, 'utf8').toString('base64'),\n ...(existingSha ? { sha: existingSha } : {}),\n });\n\n return {\n commitSha: res.data.commit.sha ?? '',\n contentSha: res.data.content?.sha ?? '',\n };\n}\n\nfunction is404(err: unknown): boolean {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'status' in err &&\n (err as { status: number }).status === 404\n );\n}\n\nexport interface CreateBranchInput extends GhAuth {\n repo: string;\n /** Name of the new branch. */\n branch: string;\n /** Name of the branch to fork from. */\n fromBranch: string;\n}\n\n/** Create a new branch by copying the head commit of `fromBranch`. */\nexport async function createBranch(input: CreateBranchInput): Promise<void> {\n const [owner, repo] = input.repo.split('/');\n if (!owner || !repo) {\n throw new Error(`Bad repo \"${input.repo}\" — expected <owner>/<repo>`);\n }\n const octokit = client(input.token);\n\n const ref = await octokit.git.getRef({\n owner,\n repo,\n ref: `heads/${input.fromBranch}`,\n });\n await octokit.git.createRef({\n owner,\n repo,\n ref: `refs/heads/${input.branch}`,\n sha: ref.data.object.sha,\n });\n}\n\nexport interface OpenPrInput extends GhAuth {\n repo: string;\n /** Branch to merge from. */\n head: string;\n /** Branch to merge into. */\n base: string;\n title: string;\n body: string;\n}\n\nexport interface OpenedPr {\n number: number;\n htmlUrl: string;\n}\n\n/** Open a pull request. Returns the PR number + URL so the caller can show\n * it to the operator. */\nexport async function openPullRequest(input: OpenPrInput): Promise<OpenedPr> {\n const [owner, repo] = input.repo.split('/');\n if (!owner || !repo) {\n throw new Error(`Bad repo \"${input.repo}\" — expected <owner>/<repo>`);\n }\n const octokit = client(input.token);\n\n const res = await octokit.pulls.create({\n owner,\n repo,\n head: input.head,\n base: input.base,\n title: input.title,\n body: input.body,\n });\n\n return { number: res.data.number, htmlUrl: res.data.html_url };\n}\n","/**\n * Small pure helpers for the local-state-only bits of `create-op-node init`:\n * generating a fresh pgsodium master key, and rendering a region's\n * `prod.tfvars` file.\n *\n * Both are side-effect free — they produce strings the caller decides what to\n * do with. Tests exercise them in isolation.\n */\n\nimport { createHmac, randomBytes } from 'node:crypto';\n\n/**\n * Generate a 32-byte (256-bit) key encoded as 64 lowercase hex characters —\n * the format `pgsodium` expects in `PGSODIUM_ROOT_KEY` and what the runbook\n * documents. The bytes come from Node's CSPRNG.\n */\nexport function generatePgsodiumRootKey(): string {\n return randomBytes(32).toString('hex');\n}\n\n/**\n * url-safe base64 helper (RFC 4648 §5) — the JWT spec mandates this variant\n * (no `+`, no `/`, no padding). `Buffer#toString('base64url')` exists on\n * Node ≥ 16 but expressing it locally keeps the dependency surface tiny and\n * avoids type-coverage games across older `@types/node`.\n */\nfunction base64url(input: Buffer | string): string {\n const buf = typeof input === 'string' ? Buffer.from(input) : input;\n return buf\n .toString('base64')\n // base64 padding `=` only ever appears at the end, so stripping every `=`\n // is equivalent to `/=+$/` and avoids the anchored-quantifier backtracking.\n .replace(/=/g, '')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_');\n}\n\n/**\n * 32-byte CSPRNG password rendered as base64url (no `+`, no `/`, no `=`).\n * Used for POSTGRES_PASSWORD — every Supabase admin user (supabase_admin,\n * authenticator, pgbouncer, supabase_auth_admin, supabase_functions_admin,\n * supabase_storage_admin) shares this one password by design of the\n * upstream init scripts.\n *\n * MUST be URL-safe: the value lands in postgres:// connection-string URIs\n * inside docker-compose env vars (gotrue, postgrest, storage). libpq parses\n * those as RFC 3986 URIs, so `/` would terminate the password component and\n * `+`/`=` are reserved sub-delims that can confuse some URI parsers. base64url\n * keeps the alphabet to `[A-Za-z0-9_-]` which is unambiguously safe in every\n * URI component.\n *\n * 32 bytes → 256 bits of entropy. The base64url encoding is ~43 chars (no\n * padding) — well above what any offline attack on a bcrypt store could\n * threaten.\n */\nexport function generatePostgresPassword(): string {\n return base64url(randomBytes(32));\n}\n\n/** Alias for clarity at the call site. Also base64url so it composes safely\n * into kong's declarative config (where DASHBOARD_PASSWORD is interpolated). */\nexport function generateDashboardPassword(): string {\n return base64url(randomBytes(24));\n}\n\n/**\n * 32-byte CSPRNG HMAC key rendered as base64url. Used for the prompt-service\n * client HMAC: prompt-service's `API_KEYS` env is a comma-separated list of\n * `<region>:<key>` pairs, and the consuming backend sends the same `<key>`\n * value in its HMAC header.\n *\n * Base64url alphabet ensures the value survives the `<region>:<key>` join\n * and any URL-component embedding without ambiguity.\n */\nexport function generateHmacApiKey(): string {\n return base64url(randomBytes(32));\n}\n\n/**\n * 48-byte (384-bit) base64 secret used to sign every Supabase-issued JWT.\n *\n * gotrue, postgrest, storage, and studio all verify tokens against this\n * value, so it must stay identical across the stack and across restarts.\n * Treat it like a master key — rotating it invalidates every session and\n * every long-lived ANON/SERVICE_ROLE token derived from it.\n */\nexport function generateJwtSecret(): string {\n return randomBytes(48).toString('base64');\n}\n\nexport type SupabaseRole = 'anon' | 'service_role';\n\nexport interface SupabaseJwtInput {\n role: SupabaseRole;\n /** HS256 signing key — same JWT_SECRET that gotrue/postgrest verify with. */\n secret: string;\n /** `iat` claim, seconds since epoch. Defaults to 1700000000 (2023-11-14)\n * — a stable past timestamp. This is deliberate, not a test artifact:\n * bootstrap re-runs generate the SAME token shape so we don't churn\n * the cached Keychain entry on every invocation. Pass `Date.now()/1000`\n * if you need a fresh `iat` (e.g. tests that exercise expiry handling). */\n issuedAtSeconds?: number;\n /** Token lifetime in seconds. Default: 10 years — Supabase's own\n * self-hosting docs ship `exp = iat + 10y` for the long-lived\n * anon + service_role keys. */\n ttlSeconds?: number;\n /** `iss` claim. Default: `supabase`. */\n issuer?: string;\n}\n\n/**\n * Verify that a stored JWT's signature was produced by the given secret.\n *\n * Constant-time-ish compare via Buffer length + manual byte loop — the\n * tokens are short and rare enough that the timing channel here doesn't\n * meaningfully advantage an attacker (and the attacker would need to be\n * able to feed bootstrap arbitrary candidate tokens, which they can't).\n *\n * Use case: bootstrap loaded supabase-anon-key from Keychain, but JWT_SECRET\n * may have rotated since. If the cached token's signature doesn't match the\n * current secret, we treat it as stale and regenerate. Without this check,\n * a partial Keychain wipe (e.g. operator deletes only jwt-secret) leaves\n * the derived tokens looking valid by shape but useless against gotrue/\n * postgrest, and every auth call silently fails 401.\n */\nexport function verifySupabaseJwt(token: string, secret: string): boolean {\n const parts = token.split('.');\n if (parts.length !== 3) return false;\n const [h, p, sig] = parts as [string, string, string];\n const expected = base64url(createHmac('sha256', secret).update(`${h}.${p}`).digest());\n if (sig.length !== expected.length) return false;\n let mismatch = 0;\n for (let i = 0; i < sig.length; i++) {\n mismatch |= sig.charCodeAt(i) ^ expected.charCodeAt(i);\n }\n return mismatch === 0;\n}\n\n/**\n * Mint a Supabase-shaped HS256 JWT for the `anon` or `service_role` claim.\n *\n * Shape matches what the official `supabase` CLI / hosted-Supabase docs\n * produce, so the token works with @supabase/supabase-js, postgrest's\n * `Authorization: Bearer …`, storage-api, and Studio out of the box.\n *\n * No third-party JWT lib — we'd have to add `jsonwebtoken` (+ its CVE\n * history) for ~30 lines of HMAC code. Implementing it here keeps the\n * dep tree clean and the algorithm pinned to HS256 by construction.\n */\nexport function signSupabaseJwt(input: SupabaseJwtInput): string {\n const iat = input.issuedAtSeconds ?? 1_700_000_000;\n const ttl = input.ttlSeconds ?? 10 * 365 * 24 * 60 * 60;\n const issuer = input.issuer ?? 'supabase';\n\n const header = { alg: 'HS256', typ: 'JWT' };\n const payload = {\n role: input.role,\n iss: issuer,\n iat,\n exp: iat + ttl,\n };\n\n const encodedHeader = base64url(JSON.stringify(header));\n const encodedPayload = base64url(JSON.stringify(payload));\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signature = base64url(\n createHmac('sha256', input.secret).update(signingInput).digest(),\n );\n return `${signingInput}.${signature}`;\n}\n\nexport interface ProdTfvarsInput {\n /** Resource-name prefix used across the Terraform module\n * (e.g. `<project>-tunnel-prod`). Defaults to `opuspopuli`. */\n project?: string;\n /** Operator's registered domain in Cloudflare (e.g. `civicfeed.tx`). */\n domain: string;\n /** Subdomain for the API tunnel (e.g. `api`). Default: `api`. */\n apiSubdomain?: string;\n /** Subdomain for the Cloudflare Pages frontend (e.g. `app`). Default: `app`. */\n appSubdomain?: string;\n /** Local port the API Gateway listens on inside the Studio. Default: 8080. */\n tunnelApiPort?: number;\n /** R2 region hint. Default: `WNAM` (Western North America). */\n r2LocationHint?: string;\n}\n\n/**\n * Render a region operator's `prod.tfvars` from their answers. Mirrors the\n * shape of `opuspopuli-node/infra/cloudflare/environments/prod.tfvars.example`\n * so the file lands ready for the cloudflare-infra workflow without any\n * post-processing.\n *\n * The output is the literal file contents — caller writes it to the repo via\n * the GitHub Contents API (`commitFile`).\n */\nexport function renderProdTfvars(input: ProdTfvarsInput): string {\n const project = input.project ?? 'opuspopuli';\n const api = input.apiSubdomain ?? 'api';\n const app = input.appSubdomain ?? 'app';\n const port = input.tunnelApiPort ?? 8080;\n const r2 = input.r2LocationHint ?? 'WNAM';\n\n return `# =============================================================================\n# Production environment — generated by create-op-node init\n# =============================================================================\n# Region-specific values for the OpusPopuli/opuspopuli-node template's\n# infra/cloudflare/ Terraform. Edit by hand to tweak.\n\nproject = ${JSON.stringify(project)}\n\ndomain_name = ${JSON.stringify(input.domain)}\n\napi_subdomain = ${JSON.stringify(api)}\napp_subdomain = ${JSON.stringify(app)}\n\ntunnel_api_port = ${port}\n\nr2_location_hint = ${JSON.stringify(r2)}\n\nenable_tunnel = true\nenable_frontend = true\nenable_r2 = true\n`;\n}\n","/**\n * Generic two-phase TFC apply-and-output wait. Two independent clocks:\n *\n * 1. **Discovery phase** — wait for the workspace to have a current run.\n * The cloudflare-infra workflow takes a few seconds to dispatch to TFC\n * after the operator merges the PR, so we re-poll the workspace until\n * a run id appears or the discovery budget elapses.\n * 2. **Run phase** — wait for that run to reach a terminal state. Sharing\n * one clock with discovery would let slow discovery eat the run-wait\n * budget; two independent clocks isolate them.\n *\n * Dependencies are injected so unit tests can drive the loop without real\n * timers or HTTP. `sleep` is a parameter; tests pass a no-op.\n */\n\nimport { fetchOutput, findWorkspace, getRunStatus } from './tfc.js';\n\nexport interface WaitInput {\n token: string;\n organization: string;\n workspaceId: string;\n /** Last-known run id when starting. `null` triggers the discovery phase. */\n runId: string | null;\n /** Tags used to re-discover the workspace's current run id. */\n workspaceTags: string[];\n /** Output to pull once the run is `applied`. */\n outputName: string;\n}\n\nexport interface WaitBudgets {\n discoveryMs: number;\n runMs: number;\n pollMs: number;\n}\n\nexport const DEFAULT_BUDGETS: WaitBudgets = {\n discoveryMs: 60 * 1000,\n runMs: 10 * 60 * 1000,\n pollMs: 10 * 1000,\n};\n\nexport type WaitOutcome =\n | { kind: 'success'; value: string }\n | { kind: 'output-missing' }\n | { kind: 'no-run-started' }\n | { kind: 'run-failed'; status: string }\n | { kind: 'timeout' };\n\n/** Test seam: lets tests inject fake findWorkspace / getRunStatus / fetchOutput. */\nexport interface WaitDeps {\n findWorkspace: typeof findWorkspace;\n getRunStatus: typeof getRunStatus;\n fetchOutput: typeof fetchOutput;\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n /** Optional progress callback for UI integration (spinner messages, etc.). */\n onProgress?: (phase: 'discovery' | 'run' | 'fetching' | 'retry') => void;\n}\n\nexport const realDeps: WaitDeps = {\n findWorkspace,\n getRunStatus,\n fetchOutput,\n sleep: (ms) => new Promise((res) => setTimeout(res, ms)),\n now: () => Date.now(),\n};\n\n/**\n * Pure polling implementation. Returns a discriminated outcome so the caller\n * can render the right message for each terminal state.\n */\nexport async function waitForApply(\n input: WaitInput,\n budgets: WaitBudgets = DEFAULT_BUDGETS,\n deps: WaitDeps = realDeps,\n): Promise<WaitOutcome> {\n let runId = input.runId;\n if (!runId) {\n runId = await discoverRunId(input, budgets, deps);\n if (!runId) return { kind: 'no-run-started' };\n }\n return waitForRunOutput(input, budgets, deps, runId);\n}\n\n// Run a single poll attempt, degrading any throw to `null` (treated as \"no\n// result this interval, try again\"). Keeps a transient network failure from\n// rejecting out of the multi-minute wait loops. `onRetry` fires on a swallowed\n// throw so the caller can surface the hiccup instead of retrying in silence.\nasync function safePoll<T>(\n fn: () => Promise<T | null>,\n onRetry?: () => void,\n): Promise<T | null> {\n try {\n return await fn();\n } catch {\n onRetry?.();\n return null;\n }\n}\n\n// Phase 1: discovery — poll the workspace until it has a current run, or the\n// discovery budget expires. Returns the run id, or null on timeout.\nasync function discoverRunId(\n input: WaitInput,\n budgets: WaitBudgets,\n deps: WaitDeps,\n): Promise<string | null> {\n deps.onProgress?.('discovery');\n const discoveryStart = deps.now();\n while (deps.now() - discoveryStart < budgets.discoveryMs) {\n await deps.sleep(budgets.pollMs);\n // A transient failure is not fatal to a multi-minute discovery window —\n // swallow it and retry on the next poll rather than rejecting the wait.\n // (The tfc helpers already degrade throws to null, so this is\n // belt-and-suspenders against any future throwing dep.)\n const ws = await safePoll(\n () =>\n deps.findWorkspace({\n token: input.token,\n organization: input.organization,\n tags: input.workspaceTags,\n }),\n () => deps.onProgress?.('retry'),\n );\n if (ws?.currentRunId) return ws.currentRunId;\n }\n return null;\n}\n\n// Phase 2: run wait — poll the run until it finishes (fetching the output on\n// success), or the run budget expires.\nasync function waitForRunOutput(\n input: WaitInput,\n budgets: WaitBudgets,\n deps: WaitDeps,\n runId: string,\n): Promise<WaitOutcome> {\n deps.onProgress?.('run');\n const runStart = deps.now();\n while (deps.now() - runStart < budgets.runMs) {\n // Transient status-poll failure → retry next interval, don't abort the\n // ~10-minute run wait on a single bad packet.\n const r = await safePoll(\n () => deps.getRunStatus({ token: input.token, organization: input.organization }, runId),\n () => deps.onProgress?.('retry'),\n );\n if (r?.finished) {\n if (!r.succeeded) return { kind: 'run-failed', status: r.status };\n deps.onProgress?.('fetching');\n const value = await safePoll(\n () =>\n deps.fetchOutput(\n { token: input.token, organization: input.organization },\n input.workspaceId,\n input.outputName,\n ),\n () => deps.onProgress?.('retry'),\n );\n return value !== null ? { kind: 'success', value } : { kind: 'output-missing' };\n }\n await deps.sleep(budgets.pollMs);\n }\n\n return { kind: 'timeout' };\n}\n","import { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport { probeCloudflareToken } from '../lib/cloudflare.js';\nimport { probeTfcToken } from '../lib/tfc.js';\nimport { detectKeychain, readSecret, saveSecret } from '../lib/keychain.js';\nimport { safeExeca } from '../lib/exec.js';\nimport { unwrap } from '../lib/prompts.js';\nimport {\n commitFile,\n createBranch,\n createRepoFromTemplate,\n openPullRequest,\n setRepoSecret,\n} from '../lib/github.js';\nimport { generatePgsodiumRootKey, renderProdTfvars } from '../lib/secrets.js';\nimport { findWorkspace } from '../lib/tfc.js';\nimport { waitForApply, realDeps as realWaitDeps } from '../lib/polling.js';\n\nexport interface InitOptions {\n domain?: string;\n region?: string;\n owner?: string;\n template?: string;\n project?: string;\n cfToken?: string;\n cfAccount?: string;\n cfZone?: string;\n tfToken?: string;\n tfOrg?: string;\n ghToken?: string;\n overwrite?: boolean;\n useExistingRepo?: boolean;\n skipWait?: boolean;\n localOnly?: boolean;\n yes?: boolean;\n}\n\n/** Pull the GitHub token from `gh auth token` if the CLI is signed in. Lets\n * operators who use `gh` skip pasting their PAT. Returns null cleanly when\n * `gh` isn't installed or isn't signed in. */\nasync function ghTokenFromCli(): Promise<string | null> {\n const r = await safeExeca('gh', ['auth', 'token']);\n if (r === null || r.exitCode !== 0) return null;\n const token = r.stdout.trim();\n return token.length > 0 ? token : null;\n}\n\nexport const initCommand = new Command('init')\n .description(\n 'Stand up the node repo + Cloudflare infrastructure for a new region. Run this on your laptop.',\n )\n .addOption(new Option('--domain <domain>', 'Your registered domain (e.g. example.org)'))\n .addOption(new Option('--region <slug>', 'Short label for your region (e.g. us-ca)'))\n .addOption(new Option('--owner <owner>', 'GitHub owner for the new node repo').default('OpusPopuli'))\n .addOption(\n new Option('--template <owner/repo>', 'Template repo to clone from').default(\n 'OpusPopuli/opuspopuli-node',\n ),\n )\n .addOption(new Option('--project <name>', 'tfvars project prefix').default('opuspopuli'))\n .addOption(new Option('--cf-token <token>', 'Cloudflare Account API token').env('CF_TOKEN'))\n .addOption(new Option('--cf-account <id>', 'Cloudflare account ID').env('CF_ACCOUNT'))\n .addOption(new Option('--cf-zone <id>', 'Cloudflare zone ID for your domain').env('CF_ZONE'))\n .addOption(new Option('--tf-token <token>', 'Terraform Cloud user/team token').env('TF_API_TOKEN'))\n .addOption(new Option('--tf-org <org>', 'Terraform Cloud organization').env('TF_CLOUD_ORGANIZATION'))\n .addOption(new Option('--gh-token <token>', 'GitHub Personal Access Token (else gh CLI)').env('GH_TOKEN'))\n .addOption(\n new Option(\n '--overwrite',\n 'Overwrite existing Keychain items (pgsodium key, Tunnel token) on a re-run',\n ).default(false),\n )\n .addOption(\n new Option(\n '--use-existing-repo',\n \"Continue using a previously-created node repo (don't fail on 'already exists')\",\n ).default(false),\n )\n .addOption(new Option('--skip-wait', \"Don't poll for Terraform apply; exit after PR open\").default(false))\n .addOption(\n new Option(\n '--local-only',\n 'Skip the Cloudflare/TFC/PR/tunnel phases. Creates the region repo from template + stores a pgsodium key — enough for `bootstrap --local-only` to work.',\n ).default(false),\n )\n .addOption(new Option('-y, --yes', 'Skip the final confirmation').default(false))\n .action(async (opts: InitOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node init ')));\n printWelcomeNote(opts);\n\n const region = await resolveRegion(opts);\n const owner = opts.owner ?? 'OpusPopuli';\n const newRepoName = `opuspopuli-node-${region}`;\n const newRepoFull = `${owner}/${newRepoName}`;\n warnIgnoredLocalOnlyFlags(opts);\n\n // Collect domain + Cloudflare + TFC creds when running in production mode.\n // Returns null in --local-only — downstream branches on this once and the\n // typed presence carries through (no non-null assertions). (S1)\n const publicConfig = opts.localOnly ? null : await collectPublicConfig(opts);\n const ghToken = await resolveGhToken(opts);\n const keychain = await detectKeychain();\n printSecretStoreNote(keychain);\n\n await confirmPlan({ opts, region, owner, newRepoFull, publicConfig });\n\n const created = await createRegionRepo({ opts, ghToken, owner, newRepoName, newRepoFull, region });\n if (publicConfig) {\n await seedRepoSecrets({ publicConfig, newRepoFull });\n }\n const pr = publicConfig\n ? await openInfraPr({ opts, ghToken, region, newRepoFull, publicConfig, created })\n : null;\n\n await persistPgsodiumKey({ keychain, opts, region });\n\n // Local-only flow ends here. Gating on publicConfig (not opts.localOnly)\n // lets TS narrow it to non-null for the TFC poll block below.\n if (!publicConfig) {\n printLocalOnlyOutro({ region, newRepoFull });\n return;\n }\n if (!pr) {\n throw new Error('init: PR creation step did not run despite publicConfig present');\n }\n\n const proceed = await pauseForMerge({ pr, opts });\n if (!proceed) return;\n\n const tunnelToken = await fetchTunnelToken({ publicConfig });\n await persistTunnelToken({ keychain, region, tunnelToken });\n printDoneOutro(region);\n });\n\n// ----------------------------------------------------------------------------\n// Init phases\n// ----------------------------------------------------------------------------\n// The command action delegates to these phase helpers so no single function\n// exceeds the cognitive-complexity budget. Each is behavior-preserving — the\n// interactive prompts, spinners, and process.exit calls are relocated\n// verbatim, restructured only with early returns to flatten nesting.\n\nfunction printWelcomeNote(opts: InitOptions): void {\n p.note(\n opts.localOnly\n ? [\n 'Local-only setup — creates the region repo from template + a pgsodium key.',\n 'No Cloudflare, no Terraform Cloud, no public exposure.',\n '',\n pc.dim('Phase 1: laptop side (now) — GitHub repo from template + Keychain.'),\n pc.dim('Phase 2: Studio side — `create-op-node bootstrap --local-only`.'),\n '',\n pc.dim('When you\\'re ready to expose publicly, re-run `init` without --local-only.'),\n ].join('\\n')\n : [\n 'This walks you from a sealed Mac Studio + a Cloudflare account to a',\n 'live federation node serving traffic at api.<your-domain>.',\n '',\n pc.dim('Phase 1: laptop side (now) — Cloudflare, GitHub, Terraform Cloud.'),\n pc.dim('Phase 2: Studio side — run `create-op-node bootstrap` on the Mac.'),\n ].join('\\n'),\n 'Welcome',\n );\n}\n\n// Region label (used as the Keychain service suffix + R2 prefix).\nasync function resolveRegion(opts: InitOptions): Promise<string> {\n return opts.region\n ? opts.region\n : unwrap(\n await p.text({\n message: 'Short region label (used as the Keychain service suffix + R2 prefix)?',\n placeholder: 'us-ca',\n validate: (v) =>\n /^[a-z0-9-]{2,32}$/.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens; 2–32 chars',\n }),\n );\n}\n\n// Warn if the operator passed flags that don't apply to --local-only. They'd\n// otherwise be silently ignored and the operator would wonder why their\n// token/domain/etc. seemed to do nothing. (S2/S3)\nfunction warnIgnoredLocalOnlyFlags(opts: InitOptions): void {\n if (!opts.localOnly) return;\n const ignored = listIgnoredLocalOnlyFlags(opts);\n if (ignored.length === 0) return;\n p.note(\n pc.yellow(\n `⚠ The following ${ignored.length === 1 ? 'flag is' : 'flags are'} ignored with --local-only:\\n` +\n ` ${ignored.join(', ')}\\n` +\n pc.dim('These configure Cloudflare / TFC / PR-merge flow, which --local-only skips.'),\n ),\n 'Notice',\n );\n}\n\n// ---- GitHub auth: flag > signed-in gh CLI > paste prompt ----\nasync function resolveGhToken(opts: InitOptions): Promise<string> {\n let ghToken = opts.ghToken;\n if (!ghToken) {\n const fromCli = await ghTokenFromCli();\n if (fromCli) {\n const useCli = unwrap(\n await p.confirm({\n message: 'Found a signed-in `gh` CLI — use its token?',\n initialValue: true,\n }),\n );\n if (useCli) ghToken = fromCli;\n }\n }\n if (!ghToken) {\n ghToken = await collectSecret(\n undefined,\n 'GitHub Personal Access Token (repo scope)',\n 'github',\n );\n }\n return ghToken;\n}\n\nfunction printSecretStoreNote(keychain: Awaited<ReturnType<typeof detectKeychain>>): void {\n const kcNote = keychain.available\n ? `✓ macOS Keychain available — pgsodium key + Tunnel token will be saved to your login keychain.\\n` +\n pc.dim('Note: items don\\'t sync to iCloud Keychain via the security CLI.\\n') +\n pc.dim('On the Studio, bootstrap will read locally and prompt you to paste if missing.')\n : `⚠ ${keychain.reason ?? 'Keychain unavailable'}. Secrets will be printed for manual stash.`;\n p.note(kcNote, 'Secret store');\n}\n\n// ---- Plan summary + confirm ----\nasync function confirmPlan(args: {\n opts: InitOptions;\n region: string;\n owner: string;\n newRepoFull: string;\n publicConfig: PublicConfig | null;\n}): Promise<void> {\n const { opts, region, owner, newRepoFull, publicConfig } = args;\n const orgWriteAccess = pc.dim(`required for ${owner}`);\n p.note(\n opts.localOnly\n ? [\n `Region label: ${pc.cyan(region)}`,\n `New node repo: ${pc.cyan(newRepoFull)}`,\n `Template: ${pc.dim(opts.template ?? 'OpusPopuli/opuspopuli-node')}`,\n `GH org write access: ${orgWriteAccess}`,\n ``,\n `Will create the repo from template (private, no Cloudflare),`,\n `and store a fresh pgsodium key in Keychain. That's it — no PR,`,\n `no terraform, no tunnel token. Bootstrap on the Studio with`,\n `\\`bootstrap --local-only --region ${region}\\` next.`,\n ].join('\\n')\n : [\n `Region label: ${pc.cyan(region)}`,\n `Domain: ${pc.cyan(publicConfig?.domain ?? '')}`,\n `New node repo: ${pc.cyan(newRepoFull)}`,\n `Template: ${pc.dim(opts.template ?? 'OpusPopuli/opuspopuli-node')}`,\n `TFC organization: ${pc.cyan(publicConfig?.tfOrg ?? '')}`,\n `GH org write access: ${orgWriteAccess}`,\n ``,\n `Will create the repo, seed 5 secrets, write prod.tfvars on a branch,`,\n `open a PR, generate a fresh pgsodium key, and (after you merge) wait`,\n `for terraform apply to finish and retrieve the Tunnel token.`,\n ].join('\\n'),\n 'Plan',\n );\n\n if (opts.yes) return;\n const go = unwrap(await p.confirm({ message: 'Proceed?', initialValue: true }));\n if (!go) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n}\n\n// ---- Execute: create repo (idempotent on HTTP 422 already-exists) ----\nasync function createRegionRepo(args: {\n opts: InitOptions;\n ghToken: string;\n owner: string;\n newRepoName: string;\n newRepoFull: string;\n region: string;\n}): Promise<{ fullName: string; defaultBranch: string }> {\n const { opts, ghToken, owner, newRepoName, newRepoFull, region } = args;\n const repoSpin = p.spinner();\n repoSpin.start(`Creating ${newRepoFull} from ${opts.template}…`);\n try {\n const created = await createRepoFromTemplate({\n token: ghToken,\n template: opts.template ?? 'OpusPopuli/opuspopuli-node',\n owner,\n name: newRepoName,\n description: `Opus Populi node deployment for ${region}`,\n });\n repoSpin.stop(pc.green(`✓ Created ${created.fullName}`));\n return { fullName: created.fullName, defaultBranch: created.defaultBranch };\n } catch (err) {\n // The most likely re-run failure mode: the repo already exists from a\n // previous partial run. The GitHub API responds with HTTP 422 for that\n // case — status code is the API contract, message text isn't. Don't\n // regex on the message; it can change.\n const status =\n typeof err === 'object' && err !== null && 'status' in err\n ? (err as { status: number }).status\n : 0;\n const message = (err as Error).message ?? 'unknown error';\n\n if (status !== 422) {\n repoSpin.stop(pc.red(`✗ Couldn't create repo: ${message}`));\n p.cancel('Fix the issue and re-run.');\n process.exit(1);\n }\n\n repoSpin.stop(pc.yellow(`⚠ ${newRepoFull} already exists.`));\n const reuse =\n opts.useExistingRepo ||\n unwrap(\n await p.confirm({\n message: `Continue with the existing ${newRepoFull}? (Re-seeds secrets + re-commits prod.tfvars on a fresh branch.)`,\n initialValue: true,\n }),\n );\n if (!reuse) {\n p.cancel(\n `Delete ${newRepoFull} on GitHub and re-run, or pass --use-existing-repo to skip this prompt.`,\n );\n process.exit(0);\n }\n // Synthesize the same shape `createRepoFromTemplate` returns so the rest\n // of the flow doesn't care which path got us here.\n // Deferred (#41): query the actual default branch via gh API instead of\n // assuming `main` — a pre-existing repo could have been initialized with\n // a different default (older operator habit, organization defaults).\n return { fullName: newRepoFull, defaultBranch: 'main' };\n }\n}\n\n// ---- Execute: seed 5 repo secrets (production mode only) ----\nasync function seedRepoSecrets(args: {\n publicConfig: PublicConfig;\n newRepoFull: string;\n}): Promise<void> {\n const { publicConfig, newRepoFull } = args;\n const secrets: Array<{ name: string; value: string }> = [\n { name: 'CLOUDFLARE_API_TOKEN', value: publicConfig.cfToken },\n { name: 'CLOUDFLARE_ACCOUNT_ID', value: publicConfig.cfAccount },\n { name: 'CLOUDFLARE_ZONE_ID', value: publicConfig.cfZone },\n { name: 'TF_API_TOKEN', value: publicConfig.tfToken },\n { name: 'TF_CLOUD_ORGANIZATION', value: publicConfig.tfOrg },\n ];\n const secSpin = p.spinner();\n secSpin.start(`Seeding ${secrets.length} repo secrets…`);\n const seeded: string[] = [];\n for (const s of secrets) {\n const r = await setRepoSecret({ repo: newRepoFull, name: s.name, value: s.value });\n if (!r.written) {\n secSpin.stop(pc.red(`✗ Failed to set ${s.name}: ${r.reason ?? 'unknown'}`));\n const remaining = secrets\n .slice(secrets.findIndex((x) => x.name === s.name))\n .map((x) => x.name);\n p.cancel(\n [\n seeded.length > 0\n ? `Already seeded on ${newRepoFull}: ${seeded.join(', ')}.`\n : `Nothing seeded yet on ${newRepoFull}.`,\n `Still pending: ${remaining.join(', ')}.`,\n '',\n `Make sure \\`gh\\` is installed and signed in (\\`gh auth login\\`).`,\n `Re-run with --use-existing-repo to retry (GitHub will overwrite the already-set secrets idempotently).`,\n ].join('\\n'),\n );\n process.exit(1);\n }\n seeded.push(s.name);\n }\n secSpin.stop(pc.green(`✓ Seeded ${secrets.length} secrets on ${newRepoFull}`));\n}\n\n// ---- Execute: branch + tfvars + PR (production mode only) ----\n// Branch name is timestamped (ISO compact, UTC) so re-runs don't collide\n// with a leftover branch from a previous partial run.\nasync function openInfraPr(args: {\n opts: InitOptions;\n ghToken: string;\n region: string;\n newRepoFull: string;\n publicConfig: PublicConfig;\n created: { defaultBranch: string };\n}): Promise<Awaited<ReturnType<typeof openPullRequest>>> {\n const { opts, ghToken, region, newRepoFull, publicConfig, created } = args;\n const branch = `init/region-${region}-${isoStampUtc(new Date())}`;\n const setupSpin = p.spinner();\n setupSpin.start(`Writing prod.tfvars on branch ${branch}…`);\n try {\n await createBranch({\n token: ghToken,\n repo: newRepoFull,\n branch,\n fromBranch: created.defaultBranch,\n });\n const tfvars = renderProdTfvars({\n project: opts.project ?? 'opuspopuli',\n domain: publicConfig.domain,\n });\n await commitFile({\n token: ghToken,\n repo: newRepoFull,\n branch,\n path: 'infra/cloudflare/environments/prod.tfvars',\n content: tfvars,\n message: `init: prod.tfvars for ${region}`,\n });\n } catch (err) {\n setupSpin.stop(pc.red(`✗ Couldn't write tfvars: ${(err as Error).message}`));\n p.cancel('The repo exists but the branch / commit failed. Open it on GitHub and inspect.');\n process.exit(1);\n }\n setupSpin.stop(pc.green('✓ Wrote prod.tfvars'));\n\n const prSpin = p.spinner();\n prSpin.start('Opening pull request…');\n try {\n const pr = await openPullRequest({\n token: ghToken,\n repo: newRepoFull,\n head: branch,\n base: created.defaultBranch,\n title: `init: bring up region ${region}`,\n body: [\n `Initial region deployment for **${region}** (${publicConfig.domain}).`,\n '',\n 'Adds `infra/cloudflare/environments/prod.tfvars`. Merging this PR triggers',\n '`cloudflare-infra.yml` which runs `terraform apply` against the',\n `\\`${publicConfig.tfOrg}\\` Terraform Cloud organization, provisioning the Cloudflare`,\n 'Tunnel, DNS records, R2 buckets, and Pages project.',\n '',\n `Generated by \\`create-op-node init\\`.`,\n ].join('\\n'),\n });\n prSpin.stop(pc.green(`✓ Opened PR #${pr.number}`));\n return pr;\n } catch (err) {\n prSpin.stop(pc.red(`✗ Couldn't open PR: ${(err as Error).message}`));\n p.cancel('Branch + tfvars are committed; open the PR by hand on GitHub.');\n process.exit(1);\n }\n}\n\n// ---- pgsodium master key (read existing OR generate fresh) ----\n//\n// Three branches: Keychain hit + key present + no --overwrite → surface the\n// existing key; Keychain hit + missing/--overwrite → generate + save; no\n// Keychain → generate + print for manual stash.\nasync function persistPgsodiumKey(args: {\n keychain: Awaited<ReturnType<typeof detectKeychain>>;\n opts: InitOptions;\n region: string;\n}): Promise<void> {\n const { keychain, opts, region } = args;\n const pgsodiumCoords = { region, account: 'pgsodium-root-key' as const };\n const keyLabel = `org.opuspopuli.${region}/pgsodium-root-key`;\n\n if (!keychain.available) {\n const fresh = generatePgsodiumRootKey();\n await printKeyForManualSave(fresh, keyLabel);\n return;\n }\n\n const existing = opts.overwrite ? null : await readSecret(pgsodiumCoords);\n if (existing && /^[a-f0-9]{64}$/.test(existing)) {\n p.note(\n `${pc.green('✓')} Re-using existing pgsodium master key from Keychain (${pc.cyan(keyLabel)}). Pass --overwrite to rotate.`,\n 'Secret',\n );\n return;\n }\n\n const fresh = generatePgsodiumRootKey();\n const r = await saveSecret(pgsodiumCoords, fresh);\n if (r.written) {\n p.note(\n `${pc.green('✓')} pgsodium master key${r.updated ? ' rotated' : ' saved'} to Keychain as ${pc.cyan(keyLabel)}.`,\n 'Secret',\n );\n } else {\n await printKeyForManualSave(fresh, keyLabel, r.reason);\n }\n}\n\nfunction printLocalOnlyOutro(args: { region: string; newRepoFull: string }): void {\n const { region, newRepoFull } = args;\n p.outro(\n pc.cyan(\n [\n `Region ${region} provisioned for local-only mode.`,\n `Repo: https://github.com/${newRepoFull}`,\n ``,\n `Next: on the Studio (fresh or otherwise — bootstrap installs`,\n `brew packages it needs), run:`,\n ` npx create-op-node bootstrap --region ${region} --local-only`,\n ``,\n `When you're ready to expose publicly, re-run BOTH \\`init\\` and`,\n `\\`bootstrap\\` without --local-only. Same region repo + pgsodium key`,\n `promote cleanly to the production-shaped deploy.`,\n ].join('\\n'),\n ),\n );\n}\n\n// Pause for the operator to merge the infra PR. Returns false when the flow\n// should stop here (--skip-wait, or the operator hasn't merged yet).\nasync function pauseForMerge(args: {\n pr: { htmlUrl: string };\n opts: InitOptions;\n}): Promise<boolean> {\n const { pr, opts } = args;\n if (opts.skipWait) {\n p.outro(\n pc.cyan(\n `Review + merge ${pr.htmlUrl} when ready. Re-run with no --skip-wait or run \\`npx create-op-node verify\\` afterwards.`,\n ),\n );\n return false;\n }\n\n p.note(\n [\n `Open the PR: ${pc.cyan(pr.htmlUrl)}`,\n '',\n 'Review the `terraform plan` comment, then merge to main.',\n 'The workflow then runs `terraform apply` against Terraform Cloud.',\n ].join('\\n'),\n 'Next step: review + merge',\n );\n const merged = unwrap(await p.confirm({ message: 'PR merged?', initialValue: false }));\n if (!merged) {\n p.outro(\n pc.cyan(`No worries — re-run \\`create-op-node init --skip-wait\\` later to skip this step, or finish manually.`),\n );\n return false;\n }\n return true;\n}\n\n// ---- Poll TFC for apply completion + fetch the tunnel token ----\nasync function fetchTunnelToken(args: { publicConfig: PublicConfig }): Promise<string> {\n const { publicConfig } = args;\n const ws = await findWorkspace({\n token: publicConfig.tfToken,\n organization: publicConfig.tfOrg,\n tags: ['opuspopuli', 'cloudflare'],\n });\n if (!ws) {\n p.cancel(\n `Couldn't find a TFC workspace tagged opuspopuli + cloudflare in ${publicConfig.tfOrg}. ` +\n `Check the workflow's run log; the workspace is created on first apply.`,\n );\n process.exit(1);\n }\n\n const tunnelToken = await waitForApplyAndFetchTunnelToken({\n token: publicConfig.tfToken,\n organization: publicConfig.tfOrg,\n workspaceId: ws.id,\n runId: ws.currentRunId,\n });\n if (!tunnelToken) {\n p.cancel(\n `Terraform apply didn't produce a tunnel_token output. Check the run on TFC; if it succeeded, the output may be named differently — patch and re-run, or fetch via 'terraform output -raw tunnel_token'.`,\n );\n process.exit(1);\n }\n return tunnelToken;\n}\n\nasync function persistTunnelToken(args: {\n keychain: Awaited<ReturnType<typeof detectKeychain>>;\n region: string;\n tunnelToken: string;\n}): Promise<void> {\n const { keychain, region, tunnelToken } = args;\n const tunnelCoords = { region, account: 'tunnel-token' as const };\n const tunnelLabel = `org.opuspopuli.${region}/tunnel-token`;\n if (!keychain.available) {\n await printKeyForManualSave(tunnelToken, tunnelLabel);\n return;\n }\n const r = await saveSecret(tunnelCoords, tunnelToken);\n if (r.written) {\n p.note(\n `${pc.green('✓')} Tunnel token saved to Keychain as ${pc.cyan(tunnelLabel)}.`,\n 'Secret',\n );\n } else {\n await printKeyForManualSave(tunnelToken, tunnelLabel, r.reason);\n }\n}\n\nfunction printDoneOutro(region: string): void {\n p.outro(\n pc.cyan(\n `Region ${region} is provisioned. Next: \\`npx create-op-node bootstrap\\` on the Mac Studio.`,\n ),\n );\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n/** Source-specific minimums — every real-world token from these issuers is\n * longer than the floor, so a short input is a typo or paste error. */\nconst MIN_TOKEN_LENGTH: Record<SecretKind, number> = {\n cloudflare: 40,\n tfc: 40,\n github: 40,\n generic: 20,\n};\n\ntype SecretKind = 'cloudflare' | 'tfc' | 'github' | 'generic';\n\n/** Pure description of which init phases will run given the operator's\n * flags. Useful for testing the flag-routing logic without touching the\n * action handler (which shells out to GH / Cloudflare / TFC). The action\n * uses the same `opts.localOnly` directly; this is a docs + test seam. */\nexport function summarizePhases(opts: Pick<InitOptions, 'localOnly'>): {\n cloudflareProbe: boolean;\n tfcProbe: boolean;\n seedSecrets: boolean;\n branchAndPR: boolean;\n tunnelTokenWait: boolean;\n} {\n const production = !opts.localOnly;\n return {\n cloudflareProbe: production,\n tfcProbe: production,\n seedSecrets: production,\n branchAndPR: production,\n tunnelTokenWait: production,\n };\n}\n\n/** Which production-only flags the operator passed but which won't be used\n * in `--local-only` mode. Surfaced as a warning so the operator knows their\n * --cf-token / --domain / etc. weren't silently swallowed. (review S2/S3) */\nexport function listIgnoredLocalOnlyFlags(opts: InitOptions): string[] {\n const ignored: string[] = [];\n if (opts.domain) ignored.push('--domain');\n if (opts.cfToken) ignored.push('--cf-token');\n if (opts.cfAccount) ignored.push('--cf-account');\n if (opts.cfZone) ignored.push('--cf-zone');\n if (opts.tfToken) ignored.push('--tf-token');\n if (opts.tfOrg) ignored.push('--tf-org');\n if (opts.skipWait) ignored.push('--skip-wait');\n return ignored;\n}\n\n/** All the inputs init needs when running the full production flow.\n * Returned by `collectPublicConfig` (whose presence is gated on\n * `!opts.localOnly`). Carrying this around as a tagged shape lets the\n * downstream code use the fields without non-null assertions. */\nexport interface PublicConfig {\n domain: string;\n cfToken: string;\n cfAccount: string;\n cfZone: string;\n tfToken: string;\n tfOrg: string;\n}\n\n/** Prompt for + verify Cloudflare and Terraform Cloud creds. Exits the\n * process on any verification failure. Only called in production mode;\n * in --local-only mode the caller passes `null` straight through. */\nasync function collectPublicConfig(opts: InitOptions): Promise<PublicConfig> {\n const domain = opts.domain\n ? opts.domain\n : unwrap(\n await p.text({\n message: 'Domain registered in Cloudflare?',\n placeholder: 'example.org',\n validate: (v) => {\n if (!v) return 'Required';\n return v.includes('.') ? undefined : 'Missing a TLD?';\n },\n }),\n );\n\n // ---- Cloudflare token --------------------------------------------------\n const cfToken = await collectSecret(\n opts.cfToken,\n 'Cloudflare Account API token (input hidden)',\n 'cloudflare',\n );\n const cfAccount = await collectId(opts.cfAccount, 'Cloudflare account ID');\n const cfZone = await collectId(opts.cfZone, `Cloudflare zone ID for ${domain}`);\n\n const cfSpin = p.spinner();\n cfSpin.start('Verifying Cloudflare token + 5 scopes…');\n const cfProbe = await probeCloudflareToken({\n token: cfToken,\n accountId: cfAccount,\n zoneId: cfZone,\n });\n if (!cfProbe.ok) {\n cfSpin.stop(pc.red('✗ Cloudflare token check failed.'));\n for (const issue of cfProbe.issues) console.error(` - ${issue}`);\n p.cancel('Fix the token in the Cloudflare dashboard, then re-run.');\n process.exit(1);\n }\n cfSpin.stop(pc.green('✓ Cloudflare token valid, 5 scopes present.'));\n\n // ---- Terraform Cloud token ---------------------------------------------\n const tfToken = await collectSecret(\n opts.tfToken,\n 'Terraform Cloud user/team API token',\n 'tfc',\n );\n const tfOrg = opts.tfOrg\n ? opts.tfOrg\n : unwrap(\n await p.text({\n message: 'Terraform Cloud organization name?',\n placeholder: 'op-region-ca',\n }),\n );\n\n const tfSpin = p.spinner();\n tfSpin.start('Verifying Terraform Cloud token + organization…');\n const tfProbe = await probeTfcToken({ token: tfToken, organization: tfOrg });\n if (!tfProbe.ok) {\n tfSpin.stop(pc.red('✗ Terraform Cloud check failed.'));\n for (const issue of tfProbe.issues) console.error(` - ${issue}`);\n p.cancel('Fix the token / org, then re-run.');\n process.exit(1);\n }\n const asUser = tfProbe.userName ? ` (as ${tfProbe.userName})` : '';\n tfSpin.stop(\n pc.green(\n `✓ TFC token valid${asUser}, org \"${tfOrg}\" reachable.`,\n ),\n );\n\n return { domain, cfToken, cfAccount, cfZone, tfToken, tfOrg };\n}\n\nasync function collectSecret(\n preset: string | undefined,\n message: string,\n kind: SecretKind = 'generic',\n): Promise<string> {\n if (preset) return preset;\n const min = MIN_TOKEN_LENGTH[kind];\n const v = unwrap(\n await p.password({\n message,\n validate: (v) =>\n v && v.length >= min\n ? undefined\n : `That looks too short — expected at least ${min} characters for a ${kind} token`,\n }),\n );\n return v;\n}\n\nasync function collectId(preset: string | undefined, message: string): Promise<string> {\n if (preset) return preset;\n const v = unwrap(\n await p.text({\n message,\n placeholder: '0000000000000000000000000000000',\n validate: (v) =>\n /^[a-f0-9]{32}$/.test(v ?? '') ? undefined : 'Expected 32 hex characters',\n }),\n );\n return v;\n}\n\nasync function printKeyForManualSave(\n value: string,\n label: string,\n reason?: string,\n): Promise<void> {\n p.note(\n [\n reason ? `${pc.red('✗')} ${reason}` : '',\n `Save this value to your secret store as ${pc.cyan(label)}:`,\n '',\n pc.yellow(value),\n '',\n pc.dim('It will not be shown again.'),\n pc.dim('On the Studio, bootstrap will prompt you to paste it back.'),\n ]\n .filter((line) => line.length > 0)\n .join('\\n'),\n 'Manual save',\n );\n unwrap(\n await p.confirm({\n message: 'Value stashed?',\n initialValue: true,\n }),\n );\n}\n\n/** Compact ISO timestamp suitable for a git branch name: 20260618-184530Z.\n * UTC so re-runs across timezones sort coherently. */\nfunction isoStampUtc(d: Date): string {\n const pad = (n: number, w = 2) => n.toString().padStart(w, '0');\n return (\n `${d.getUTCFullYear()}` +\n `${pad(d.getUTCMonth() + 1)}` +\n `${pad(d.getUTCDate())}` +\n `-` +\n `${pad(d.getUTCHours())}` +\n `${pad(d.getUTCMinutes())}` +\n `${pad(d.getUTCSeconds())}Z`\n );\n}\n\ninterface WaitInput {\n token: string;\n organization: string;\n workspaceId: string;\n runId: string | null;\n}\n\n/** Thin command-side adapter for the polling lib — renders Clack spinner\n * state from the lib's progress callback + maps the discriminated outcome\n * to a single nullable result the command keeps using. */\nasync function waitForApplyAndFetchTunnelToken(input: WaitInput): Promise<string | null> {\n const spin = p.spinner();\n spin.start('Waiting for terraform apply to finish (polling every 10s)…');\n\n const outcome = await waitForApply(\n {\n token: input.token,\n organization: input.organization,\n workspaceId: input.workspaceId,\n runId: input.runId,\n workspaceTags: ['opuspopuli', 'cloudflare'],\n outputName: 'tunnel_token',\n },\n undefined,\n {\n ...realWaitDeps,\n // Surface a transient network hiccup instead of silently re-polling, so\n // a slow wait doesn't look like a hang.\n onProgress: (phase) => {\n if (phase === 'retry') spin.message('Transient network error — retrying next poll…');\n },\n },\n );\n\n switch (outcome.kind) {\n case 'success':\n spin.stop(pc.green('✓ Tunnel token retrieved.'));\n return outcome.value;\n case 'output-missing':\n spin.stop(pc.red('✗ Apply succeeded but tunnel_token output is missing.'));\n return null;\n case 'no-run-started':\n spin.stop(pc.red('✗ No run started in the workspace yet.'));\n return null;\n case 'run-failed':\n spin.stop(pc.red(`✗ Run finished with status \"${outcome.status}\".`));\n return null;\n case 'timeout':\n spin.stop(pc.red('✗ Timed out after 10 minutes.'));\n return null;\n }\n}\n","/**\n * Detect Homebrew + install packages (formulae or casks) idempotently.\n *\n * Bootstrap shells out to brew once per package — `brew install` is itself\n * idempotent (no-op when already installed) but we list-check first so the\n * wizard can print \"already present\" vs \"installing…\" and skip the\n * potentially-multi-minute download for packages that are already on the\n * Studio.\n *\n * We don't try to AUTO-install Homebrew itself. The official installer is a\n * curl-pipe-bash script that prompts for sudo + has its own UX; the wizard\n * detects its absence, prints the single-line install command, and waits for\n * the operator to confirm before proceeding.\n */\n\nimport { safeExeca } from './exec.js';\n\nexport type PackageKind = 'formula' | 'cask';\n\nexport interface PackageSpec {\n name: string;\n kind: PackageKind;\n}\n\n/** The package set the runbook installs on the Studio. Casks need GUI\n * authorization on first launch — Docker Desktop in particular requires\n * manual click-through after `brew install --cask docker`. The wizard\n * surfaces that as a follow-up prompt; this list is just what we'd shell\n * out for.\n *\n * Deep-readonly via `as const` — neither the array nor the individual\n * PackageSpec entries can be mutated by accident. */\nexport const STUDIO_PACKAGES = [\n { name: 'git', kind: 'formula' },\n { name: 'gh', kind: 'formula' },\n { name: 'pnpm', kind: 'formula' },\n { name: 'jq', kind: 'formula' },\n { name: 'cloudflared', kind: 'formula' },\n { name: 'rclone', kind: 'formula' },\n { name: 'ollama', kind: 'formula' },\n { name: 'docker', kind: 'cask' },\n { name: 'tailscale', kind: 'cask' },\n] as const satisfies readonly PackageSpec[];\n\nexport interface BrewInfo {\n installed: boolean;\n /** Version string when installed (`Homebrew 4.x.y`). Undefined otherwise. */\n version?: string;\n}\n\nexport async function detectBrew(): Promise<BrewInfo> {\n const res = await safeExeca('brew', ['--version']);\n if (res === null || res.exitCode !== 0) {\n return { installed: false };\n }\n // `brew --version` prints e.g. \"Homebrew 4.4.10\".\n const version = res.stdout.split('\\n').find((l) => l.startsWith('Homebrew '));\n return { installed: true, ...(version ? { version } : {}) };\n}\n\n/** The one-shot install command operators paste into their shell when brew is\n * missing. Surfaced verbatim so the wizard can show + the docs can quote\n * the same string. */\nexport const HOMEBREW_INSTALL_COMMAND =\n '/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"';\n\n/**\n * Is the named package already installed? `brew list <name>` exits 0 when\n * yes, non-zero when no. Cask vs formula lookup uses different flags.\n */\nexport async function isPackageInstalled(pkg: PackageSpec): Promise<boolean> {\n const flag = pkg.kind === 'cask' ? '--cask' : '--formula';\n const res = await safeExeca('brew', ['list', flag, pkg.name]);\n return res !== null && res.exitCode === 0;\n}\n\nexport interface InstallResult {\n ok: boolean;\n /** Set when ok=false. Stderr or stdout from the failing command. */\n reason?: string;\n}\n\n/** Install one package. Caller should `isPackageInstalled` first to skip\n * re-installs when speed matters; brew install is itself idempotent. */\nexport async function installPackage(pkg: PackageSpec): Promise<InstallResult> {\n const args =\n pkg.kind === 'cask'\n ? ['install', '--cask', pkg.name]\n : ['install', pkg.name];\n const res = await safeExeca('brew', args);\n if (res === null) {\n return { ok: false, reason: '`brew` not on PATH' };\n }\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `brew install ${pkg.name} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport interface InstallReport {\n installed: PackageSpec[];\n alreadyPresent: PackageSpec[];\n failed: Array<{ pkg: PackageSpec; reason: string }>;\n}\n\n/**\n * Install every package in the spec list. Each is independently logged into\n * one of three buckets so the wizard can show a clean summary. A failure in\n * one package doesn't abort the rest — we want the operator to see the\n * whole landscape and decide which to retry.\n */\nexport async function installPackages(\n packages: readonly PackageSpec[],\n onEach?: (pkg: PackageSpec, status: 'checking' | 'installing' | 'present' | 'installed' | 'failed') => void,\n): Promise<InstallReport> {\n const report: InstallReport = {\n installed: [],\n alreadyPresent: [],\n failed: [],\n };\n for (const pkg of packages) {\n onEach?.(pkg, 'checking');\n if (await isPackageInstalled(pkg)) {\n report.alreadyPresent.push(pkg);\n onEach?.(pkg, 'present');\n continue;\n }\n onEach?.(pkg, 'installing');\n const r = await installPackage(pkg);\n if (r.ok) {\n report.installed.push(pkg);\n onEach?.(pkg, 'installed');\n } else {\n report.failed.push({ pkg, reason: r.reason ?? 'unknown' });\n onEach?.(pkg, 'failed');\n }\n }\n return report;\n}\n","/**\n * Read + write the small set of macOS settings `create-op-node bootstrap`\n * cares about on the Mac Studio:\n *\n * - Hostname and OS version (informational + sanity check we're on Apple Silicon).\n * - Power management (`pmset`): auto-restart-on-power-failure, disk sleep.\n * - FileVault status (`fdesetup`) — informational only; we don't toggle it,\n * since the operator's earlier decision (gate 0.7 in the runbook) was OFF.\n *\n * All probes shell out via `safeExeca` from `lib/exec.ts` so a missing binary\n * (extremely unusual on macOS, but it's the principle) doesn't crash the\n * wizard. Writers use `pmset -a` which requires sudo on macOS — execa\n * propagates the operator's stdin so the password prompt works inline.\n */\n\nimport { safeExeca } from './exec.js';\n\nexport interface SystemSnapshot {\n hostname: string;\n /** `sw_vers -productVersion` output, or `null` when the call failed. */\n osVersion: string | null;\n /** True when `pmset -g` reports `autorestart 1`. */\n autoRestartOnPowerFailure: boolean;\n /** True when `pmset -g` reports `disksleep 0` (i.e. disk sleep DISABLED — the\n * state the bootstrap wants). */\n diskSleepDisabled: boolean;\n /** `true` / `false` when `fdesetup status` reported decisively, `'unknown'`\n * when the call failed or the output was unexpected. We don't toggle\n * FileVault — this is for the operator-facing summary only. */\n fileVaultEnabled: boolean | 'unknown';\n /** True when `uname -m` returns `arm64` (i.e. Apple Silicon Mac).\n * Bootstrap is M-series-only; Intel Macs fail with a clear message. */\n isAppleSilicon: boolean;\n}\n\nexport async function inspectSystem(): Promise<SystemSnapshot> {\n const [hostnameOut, osVersionOut, pmsetOut, fdesetupOut, unameOut] =\n await Promise.all([\n safeExeca('hostname', []),\n safeExeca('sw_vers', ['-productVersion']),\n safeExeca('pmset', ['-g']),\n safeExeca('fdesetup', ['status']),\n safeExeca('uname', ['-m']),\n ]);\n\n return {\n hostname: hostnameOut?.stdout.trim() ?? 'unknown',\n osVersion:\n osVersionOut && osVersionOut.exitCode === 0\n ? osVersionOut.stdout.trim()\n : null,\n autoRestartOnPowerFailure: parsePmsetBool(pmsetOut?.stdout ?? '', 'autorestart', 1),\n diskSleepDisabled: parsePmsetBool(pmsetOut?.stdout ?? '', 'disksleep', 0),\n fileVaultEnabled: parseFileVault(fdesetupOut?.stdout ?? ''),\n isAppleSilicon: (unameOut?.stdout.trim() ?? '') === 'arm64',\n };\n}\n\n/**\n * `pmset -g` prints one space-separated `key value` per line, e.g.:\n *\n * ```\n * System-wide power settings:\n * Currently in use:\n * lidwake 1\n * autorestart 1\n * disksleep 0\n * ```\n *\n * Returns `true` when the named key's value matches `expected`. Tolerant of\n * leading/trailing whitespace; matches first occurrence.\n */\nexport function parsePmsetBool(\n output: string,\n key: string,\n expected: number,\n): boolean {\n for (const line of output.split('\\n')) {\n const match = line.match(/^\\s*([a-z]+)\\s+(-?\\d+)\\s*$/);\n if (match && match[1] === key) {\n return Number(match[2]) === expected;\n }\n }\n return false;\n}\n\n/**\n * `fdesetup status` prints either:\n * - `FileVault is On.`\n * - `FileVault is Off.`\n * - `Encryption in progress: ...` (treat as On)\n * - anything else → `'unknown'`\n */\nexport function parseFileVault(output: string): boolean | 'unknown' {\n const trimmed = output.trim();\n if (/^FileVault is On\\.?/i.test(trimmed)) return true;\n if (/^FileVault is Off\\.?/i.test(trimmed)) return false;\n if (/encryption in progress/i.test(trimmed)) return true;\n return 'unknown';\n}\n\nexport interface SetResult {\n ok: boolean;\n /** Set when `ok=false`. Stderr or stdout from the failing command. */\n reason?: string;\n}\n\n/**\n * Enable auto-restart-on-power-failure (`pmset -a autorestart 1`). Requires\n * sudo; the operator's password prompt is inherited from the parent shell.\n */\nexport async function enableAutoRestartOnPowerFailure(): Promise<SetResult> {\n return runSudoPmset(['autorestart', '1']);\n}\n\n/** Disable disk sleep (`pmset -a disksleep 0`). Same sudo behavior. */\nexport async function disableDiskSleep(): Promise<SetResult> {\n return runSudoPmset(['disksleep', '0']);\n}\n\n/**\n * Read the Studio's unified memory in GB via `sysctl hw.memsize`. Returns\n * `null` when sysctl is unavailable or the output is unparseable — callers\n * fall back to platform defaults in that case.\n *\n * `hw.memsize` reports bytes (e.g. `137438953472` for 128 GB). We divide\n * by 2^30 and round; vendors mostly ship integer GB so the rounding is\n * cosmetic, but the user may see `127` instead of `128` on rare configs.\n */\nexport async function detectUnifiedMemoryGB(): Promise<number | null> {\n const res = await safeExeca('sysctl', ['-n', 'hw.memsize']);\n if (res === null || res.exitCode !== 0) return null;\n const bytes = Number.parseInt(res.stdout.trim(), 10);\n if (!Number.isFinite(bytes) || bytes <= 0) return null;\n return Math.round(bytes / 2 ** 30);\n}\n\nasync function runSudoPmset(args: string[]): Promise<SetResult> {\n const res = await safeExeca('sudo', ['pmset', '-a', ...args]);\n if (res === null) {\n return { ok: false, reason: '`sudo` not on PATH' };\n }\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `pmset ${args.join(' ')} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n","/**\n * macOS LaunchAgent for the env-loader that the bootstrap puts in place.\n *\n * The plist's whole job is to inject two env vars into the launchd session at\n * login so Docker Desktop + the container stack see them:\n *\n * PGSODIUM_ROOT_KEY — 64-hex pgsodium master key, read from a `0400` file\n * outside the container so a `docker compose --build`\n * can never wipe it (runbook gate / #791).\n * TUNNEL_TOKEN — Cloudflare Tunnel token, baked into the plist literal.\n *\n * The pgsodium key is materialized as a separate `0400` file (not embedded in\n * the plist) so it can be backed up out-of-band + rotated independently. The\n * Tunnel token gets baked into the plist directly — it's a different rotation\n * cadence (rotates with the Tunnel resource, not on pgsodium key churn).\n *\n * File modes match the runbook:\n * - pgsodium key file: 0400 (owner-read-only)\n * - plist file: 0600 (owner read+write; contains TUNNEL_TOKEN)\n */\n\nimport { mkdir, writeFile, chmod, rm } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { homedir } from 'node:os';\n\nimport {\n PGSODIUM_KEY_RE,\n SAFE_LAUNCHCTL_VALUE_RE,\n SAFE_PATH_RE,\n SAFE_URL_RE,\n TUNNEL_TOKEN_RE,\n} from './constants.js';\nimport { safeExeca } from './exec.js';\n\nexport const LAUNCH_AGENT_LABEL = 'org.opuspopuli.envloader';\n\nexport interface LaunchAgentPaths {\n /** Absolute path to the 64-hex pgsodium master key file (mode 0400). */\n keyFile: string;\n /** Absolute path to the LaunchAgent plist (mode 0600). */\n plistFile: string;\n}\n\n/** Default on-disk locations the runbook documents. Operators can override. */\nexport function defaultPaths(home: string = homedir()): LaunchAgentPaths {\n return {\n keyFile: `${home}/.config/opuspopuli/pgsodium_root_key`,\n plistFile: `${home}/Library/LaunchAgents/${LAUNCH_AGENT_LABEL}.plist`,\n };\n}\n\nexport interface WriteResult {\n ok: boolean;\n /** Set when ok=false. */\n reason?: string;\n}\n\n/**\n * Write the 64-hex pgsodium master key to `keyFile` with mode 0400. Creates\n * the parent directory tree (mode 0700 on the immediate parent) and refuses\n * non-64-hex input.\n */\nexport async function writePgsodiumKeyFile(\n key: string,\n keyFile: string,\n): Promise<WriteResult> {\n if (!PGSODIUM_KEY_RE.test(key)) {\n return {\n ok: false,\n reason: `pgsodium key must be 64 lowercase hex characters (got ${key.length} chars)`,\n };\n }\n try {\n const dir = dirname(keyFile);\n await mkdir(dir, { recursive: true, mode: 0o700 });\n await writeFile(keyFile, key, { mode: 0o400 });\n // mkdir's mode option respects umask; chmod is the belt to the suspenders.\n await chmod(dir, 0o700);\n await chmod(keyFile, 0o400);\n return { ok: true };\n } catch (err) {\n return { ok: false, reason: `writing ${keyFile} failed: ${(err as Error).message}` };\n }\n}\n\n/** Model-identifier safe set. Requires at least one alphanumeric character\n * to start (rejects lone `:`, `.`, `///`, etc. — Ollama would reject those\n * too, but catching them here gives a clearer error). Then allows the\n * letters/digits + Ollama's separators (`.`, `:`, `_`, `-`, `/`) — matches\n * shapes like `qwen3.5:9b`, `library/llama3.3:70b-q4`, `mxbai-embed-large`.\n * Reject anything outside this because the value gets interpolated into a\n * `sh -c` body run by launchd — `;`, `$`, backticks, quotes would all give\n * shell injection. */\nconst MODEL_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;\n\nexport interface PlistInput {\n /** Path the plist will exec — sourced from defaultPaths() unless an operator\n * overrides on the command line. */\n keyFilePath: string;\n /** Literal Cloudflare Tunnel token; embedded in the plist. Omit for\n * `bootstrap --local-only` flows where no Tunnel is provisioned — the\n * rendered plist will only set PGSODIUM_ROOT_KEY. */\n tunnelToken?: string;\n /** Ollama model identifier (e.g. `qwen3.5:9b`, `llama3.3:70b`).\n * When set, plist exports `LLM_MODEL` into the launchd session so the\n * knowledge service reads it via env. */\n llmModel?: string;\n /** Ollama embedding model identifier. When set, plist exports\n * `EMBEDDINGS_MODEL` into the launchd session. Only meaningful when the\n * knowledge service runs with `EMBEDDINGS_PROVIDER=ollama`. */\n embeddingModel?: string;\n /** Self-hosted Supabase credentials. When provided, the plist exports each\n * value via `launchctl setenv` so docker-compose-prod.yml — and every\n * Supabase container the compose brings up — sees them. Omit individual\n * fields to skip emitting that var (e.g. for partial re-runs). */\n postgresPassword?: string;\n jwtSecret?: string;\n supabaseAnonKey?: string;\n supabaseServiceRoleKey?: string;\n dashboardPassword?: string;\n /** Public-facing Supabase URL — what browsers + microservices use to reach\n * Kong. Local dev: `http://localhost:8000`. Tunnel: `https://supabase.<domain>`. */\n supabaseUrl?: string;\n}\n\n/**\n * Render the LaunchAgent plist XML. Pure function — caller writes it.\n *\n * The plist runs a `/bin/sh -c` at load that calls `launchctl setenv` for\n * each var. `launchctl setenv` exports into the running launchd session,\n * not just the agent's own env, so anything Docker Desktop launches\n * downstream sees the same values.\n *\n * Required: `PGSODIUM_ROOT_KEY`. Optional: `TUNNEL_TOKEN`, `LLM_MODEL`,\n * `EMBEDDINGS_MODEL` — omitted from the setenv list when their inputs\n * are undefined.\n */\nexport function renderLaunchAgentPlist(input: PlistInput): string {\n validatePlistInput(input);\n const command = buildSetenvCommand(input);\n\n return [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">',\n '<plist version=\"1.0\">',\n '<dict>',\n ` <key>Label</key><string>${LAUNCH_AGENT_LABEL}</string>`,\n ' <key>ProgramArguments</key>',\n ' <array>',\n ' <string>/bin/sh</string>',\n ' <string>-c</string>',\n ` <string>${command}</string>`,\n ' </array>',\n ' <key>RunAtLoad</key><true/>',\n '</dict>',\n '</plist>',\n '',\n ].join('\\n');\n}\n\n// Reject any input that would break the XML or inject shell metacharacters\n// into the `sh -c` body launchd runs at every login. Throws on the first\n// offending field. Our own generators only emit safe alphabets, but\n// operators can pass --import-* overrides, so re-validate here.\nfunction validatePlistInput(input: PlistInput): void {\n if (input.tunnelToken !== undefined && !TUNNEL_TOKEN_RE.test(input.tunnelToken)) {\n throw new Error('Tunnel token contains characters outside the expected base64-url set');\n }\n if (input.llmModel !== undefined && !MODEL_NAME_RE.test(input.llmModel)) {\n throw new Error(\n `llmModel ${JSON.stringify(input.llmModel)} contains characters not allowed in a launchd setenv value`,\n );\n }\n if (input.embeddingModel !== undefined && !MODEL_NAME_RE.test(input.embeddingModel)) {\n throw new Error(\n `embeddingModel ${JSON.stringify(input.embeddingModel)} contains characters not allowed in a launchd setenv value`,\n );\n }\n if (!SAFE_PATH_RE.test(input.keyFilePath)) {\n // The keyFilePath gets interpolated into a `sh -c` command run by launchd\n // at every login — reject shell metacharacters even though defaultPaths()\n // never produces one (defense in depth against operator overrides).\n throw new Error(\n `keyFilePath ${JSON.stringify(input.keyFilePath)} contains characters not allowed in a launchd path interpolation`,\n );\n }\n const supabaseFields: Array<[keyof PlistInput, string | undefined]> = [\n ['postgresPassword', input.postgresPassword],\n ['jwtSecret', input.jwtSecret],\n ['supabaseAnonKey', input.supabaseAnonKey],\n ['supabaseServiceRoleKey', input.supabaseServiceRoleKey],\n ['dashboardPassword', input.dashboardPassword],\n ];\n for (const [name, value] of supabaseFields) {\n if (value !== undefined && !SAFE_LAUNCHCTL_VALUE_RE.test(value)) {\n throw new Error(`${String(name)} contains characters not allowed in a launchd setenv value`);\n }\n }\n if (input.supabaseUrl !== undefined && !SAFE_URL_RE.test(input.supabaseUrl)) {\n throw new Error(\n `supabaseUrl ${JSON.stringify(input.supabaseUrl)} contains characters not allowed in a launchd setenv value`,\n );\n }\n}\n\n// Assemble the `; `-joined `launchctl setenv` command. PGSODIUM_ROOT_KEY is\n// always set; every other var is emitted only when its value is present.\nfunction buildSetenvCommand(input: PlistInput): string {\n return [\n `launchctl setenv PGSODIUM_ROOT_KEY \"$(cat ${input.keyFilePath})\"`,\n ...(input.tunnelToken !== undefined\n ? [`launchctl setenv TUNNEL_TOKEN \"${input.tunnelToken}\"`]\n : []),\n ...(input.llmModel !== undefined ? [`launchctl setenv LLM_MODEL \"${input.llmModel}\"`] : []),\n ...(input.embeddingModel !== undefined\n ? [`launchctl setenv EMBEDDINGS_MODEL \"${input.embeddingModel}\"`]\n : []),\n ...(input.postgresPassword !== undefined\n ? [`launchctl setenv POSTGRES_PASSWORD \"${input.postgresPassword}\"`]\n : []),\n ...(input.jwtSecret !== undefined ? [`launchctl setenv JWT_SECRET \"${input.jwtSecret}\"`] : []),\n ...(input.supabaseAnonKey !== undefined\n ? [`launchctl setenv SUPABASE_ANON_KEY \"${input.supabaseAnonKey}\"`]\n : []),\n ...(input.supabaseServiceRoleKey !== undefined\n ? [`launchctl setenv SUPABASE_SERVICE_ROLE_KEY \"${input.supabaseServiceRoleKey}\"`]\n : []),\n ...(input.dashboardPassword !== undefined\n ? [`launchctl setenv DASHBOARD_PASSWORD \"${input.dashboardPassword}\"`]\n : []),\n ...(input.supabaseUrl !== undefined\n ? [`launchctl setenv SUPABASE_URL \"${input.supabaseUrl}\"`]\n : []),\n ].join('; ');\n}\n\n/** Write the plist file to disk at mode 0600. */\nexport async function writeLaunchAgentPlist(\n plistFile: string,\n content: string,\n): Promise<WriteResult> {\n try {\n await mkdir(dirname(plistFile), { recursive: true });\n await writeFile(plistFile, content, { mode: 0o600 });\n await chmod(plistFile, 0o600);\n return { ok: true };\n } catch (err) {\n return { ok: false, reason: `writing ${plistFile} failed: ${(err as Error).message}` };\n }\n}\n\n/**\n * Load (or reload) the agent via `launchctl load`. Unload first to handle\n * re-runs; ignore errors on unload since it could just not be loaded yet.\n */\nexport async function loadLaunchAgent(plistFile: string): Promise<WriteResult> {\n await safeExeca('launchctl', ['unload', plistFile]); // ignore errors\n const load = await safeExeca('launchctl', ['load', plistFile]);\n if (load === null) {\n return { ok: false, reason: '`launchctl` not on PATH' };\n }\n if (load.exitCode !== 0) {\n return {\n ok: false,\n reason: `launchctl load failed (${load.exitCode ?? 'signal'}): ${load.stderr || load.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport interface SetupInput {\n pgsodiumKey: string;\n /** Omit for `bootstrap --local-only` flows — the rendered plist will only\n * set `PGSODIUM_ROOT_KEY`. */\n tunnelToken?: string;\n /** Ollama LLM model name. When set, plist exports `LLM_MODEL`. */\n llmModel?: string;\n /** Ollama embedding model name. When set, plist exports `EMBEDDINGS_MODEL`. */\n embeddingModel?: string;\n /** Self-hosted Supabase credentials — generated by `bootstrap` and stored\n * in Keychain. Each value here gets exported into the launchd session\n * via the plist's `launchctl setenv` lines. */\n postgresPassword?: string;\n jwtSecret?: string;\n supabaseAnonKey?: string;\n supabaseServiceRoleKey?: string;\n dashboardPassword?: string;\n /** Public-facing Supabase URL. */\n supabaseUrl?: string;\n paths?: LaunchAgentPaths;\n}\n\nexport interface SetupReport {\n ok: boolean;\n paths: LaunchAgentPaths;\n step?: 'key-file' | 'plist' | 'load';\n reason?: string;\n}\n\n/**\n * One-shot: write the key file, render + write the plist, load the agent.\n * Returns a report that names which step failed (if any) for clean operator\n * messaging.\n */\n// Map the flat SetupInput onto a PlistInput, carrying only the fields that\n// are present (each optional secret is spread in only when defined).\nfunction plistInputFromSetup(input: SetupInput, keyFilePath: string): PlistInput {\n return {\n keyFilePath,\n ...(input.tunnelToken !== undefined ? { tunnelToken: input.tunnelToken } : {}),\n ...(input.llmModel !== undefined ? { llmModel: input.llmModel } : {}),\n ...(input.embeddingModel !== undefined ? { embeddingModel: input.embeddingModel } : {}),\n ...(input.postgresPassword !== undefined ? { postgresPassword: input.postgresPassword } : {}),\n ...(input.jwtSecret !== undefined ? { jwtSecret: input.jwtSecret } : {}),\n ...(input.supabaseAnonKey !== undefined ? { supabaseAnonKey: input.supabaseAnonKey } : {}),\n ...(input.supabaseServiceRoleKey !== undefined\n ? { supabaseServiceRoleKey: input.supabaseServiceRoleKey }\n : {}),\n ...(input.dashboardPassword !== undefined ? { dashboardPassword: input.dashboardPassword } : {}),\n ...(input.supabaseUrl !== undefined ? { supabaseUrl: input.supabaseUrl } : {}),\n };\n}\n\nexport async function setupLaunchAgent(input: SetupInput): Promise<SetupReport> {\n const paths = input.paths ?? defaultPaths();\n\n const keyResult = await writePgsodiumKeyFile(input.pgsodiumKey, paths.keyFile);\n if (!keyResult.ok) {\n return { ok: false, paths, step: 'key-file', ...(keyResult.reason ? { reason: keyResult.reason } : {}) };\n }\n\n let plistContent: string;\n try {\n plistContent = renderLaunchAgentPlist(plistInputFromSetup(input, paths.keyFile));\n } catch (err) {\n return { ok: false, paths, step: 'plist', reason: (err as Error).message };\n }\n\n const plistResult = await writeLaunchAgentPlist(paths.plistFile, plistContent);\n if (!plistResult.ok) {\n return { ok: false, paths, step: 'plist', ...(plistResult.reason ? { reason: plistResult.reason } : {}) };\n }\n\n const loadResult = await loadLaunchAgent(paths.plistFile);\n if (!loadResult.ok) {\n return { ok: false, paths, step: 'load', ...(loadResult.reason ? { reason: loadResult.reason } : {}) };\n }\n\n return { ok: true, paths };\n}\n\nexport interface TeardownResult {\n ok: boolean;\n /** Per-step outcome. Each step is independently logged so the operator can\n * see \"unload worked but the plist file was already gone.\" */\n steps: Array<{ step: 'unload' | 'rm-plist' | 'rm-key-file'; ok: boolean; reason?: string }>;\n}\n\nexport interface TeardownOptions {\n /** When true, leave the pgsodium key file in place. Useful when the\n * operator wants to unload the LaunchAgent + remove the plist but\n * keep the key as belt-and-suspenders backup. */\n keepKeyFile?: boolean;\n}\n\n/**\n * Reverse of `setupLaunchAgent`: unload the agent via `launchctl unload`,\n * then `rm -f` both the plist and (unless `keepKeyFile`) the pgsodium key\n * file. Idempotent — `rm -f` is a no-op when the file doesn't exist, and\n * we treat `launchctl unload` of an already-unloaded agent as success.\n *\n * Used by `reset`. Also useful as a test seam during integration tests.\n */\nexport async function teardownLaunchAgent(\n paths: LaunchAgentPaths,\n opts: TeardownOptions = {},\n): Promise<TeardownResult> {\n const steps: TeardownResult['steps'] = [];\n\n const unload = await safeExeca('launchctl', ['unload', paths.plistFile]);\n // `launchctl unload` exits non-zero when the agent isn't loaded — that's\n // a successful teardown from our point of view, so we don't propagate it.\n steps.push({\n step: 'unload',\n ok: true,\n ...(unload === null ? { reason: '`launchctl` not on PATH' } : {}),\n });\n\n try {\n await rm(paths.plistFile, { force: true });\n steps.push({ step: 'rm-plist', ok: true });\n } catch (err) {\n steps.push({ step: 'rm-plist', ok: false, reason: (err as Error).message });\n }\n\n if (!opts.keepKeyFile) {\n try {\n await rm(paths.keyFile, { force: true });\n steps.push({ step: 'rm-key-file', ok: true });\n } catch (err) {\n steps.push({ step: 'rm-key-file', ok: false, reason: (err as Error).message });\n }\n }\n\n return { ok: steps.every((s) => s.ok), steps };\n}\n","/**\n * Renders the `bin/op-compose` wrapper script that lives in the operator's\n * region-node repo.\n *\n * **Why a wrapper instead of a `.env` file:**\n * The project's vault-first principle (#811) says runtime secrets read via\n * `secretsProvider.getSecret()` at point of use; env-on-disk is reserved\n * for bootstrap-critical config. The bootstrap-layer secrets (Postgres\n * password, JWT secret, Supabase admin tokens) ARE bootstrap-critical\n * (Postgres / kong / gotrue can't start without them, and Vault doesn't\n * exist until Postgres is up) — but they don't need to LIVE on disk in\n * plaintext to be available at compose-invocation time.\n *\n * This wrapper reads them from macOS Keychain (FileVault-encrypted at\n * rest) on every invocation and exports them only into the docker compose\n * subprocess's env. No plaintext .env file ever lands on disk; the\n * Keychain is the sole persistent store.\n *\n * **Why launchctl setenv isn't sufficient:**\n * `launchctl setenv` only propagates to processes spawned by launchd\n * AFTER the setenv call. SSH-spawned shells (sshd children) and\n * already-running Terminal.app instances never see the new vars, so\n * `docker compose` hard-fails on `${VAR:?…}` even though `launchctl\n * getenv` confirms launchd has them. The wrapper is shell-agnostic and\n * works the same in every invocation context.\n *\n * **Operator workflow:**\n * $ ./bin/op-compose -f docker-compose-prod.yml up -d\n * $ ./bin/op-compose -f docker-compose-prod.yml pull\n * $ ./bin/op-compose -f docker-compose-prod.yml down\n *\n * The wrapper accepts every argument `docker compose` accepts.\n *\n * **Security:**\n * - Script is mode 0755 (executable, world-readable). The script ITSELF\n * has no secrets — it's a static shell script with the region name\n * baked in. The secrets only exist in process env for the lifetime\n * of the docker compose invocation.\n * - Region name is the only baked-in value (used to scope the Keychain\n * service identifier `org.opuspopuli.<region>`); shell-injection is\n * prevented by the region-validation regex in bootstrap.ts.\n * - Errors when a required Keychain entry is missing point the operator\n * at `create-op-node bootstrap`.\n */\n\nconst REGION_RE = /^[a-z0-9-]{2,32}$/;\n\n/** URL-shape regex for values baked into the wrapper as\n * `export PROMPT_SERVICE_URL=\"…\"`. Matches what bootstrap.ts validates\n * via SAFE_URL_RE — letters, digits, `:`, `/`, `_`, `-`, `.`. Reject\n * shell metacharacters that would inject when the wrapper sources. */\nconst PROMPT_SERVICE_URL_RE = /^[A-Za-z0-9:/_.-]+$/;\n\nexport interface OpComposeScriptInput {\n /** Region slug — gets interpolated into the Keychain service identifier\n * `org.opuspopuli.<region>`. Validated against the same regex bootstrap\n * uses, so a tampered call site can't inject shell metacharacters. */\n region: string;\n /** Default value the wrapper sets for `PROMPT_SERVICE_URL` when nothing\n * in the docker compose service-level env overrides it. For\n * `region-with-prompts` deployments this is the in-network address\n * `http://opuspopuli-prompts:3210` (and the overlay still wins via\n * service-level env). For `region` (remote prompts) it's whatever URL\n * the operator pointed at — typically https://prompts.opuspopuli.org.\n * Omit and the wrapper won't export PROMPT_SERVICE_URL at all. */\n promptServiceUrl?: string;\n}\n\n/**\n * Render the wrapper script. Pure function — caller writes it to disk and\n * `chmod 0755`s the result.\n *\n * Throws on an invalid region label rather than emit a script with a\n * shell-injectable service identifier.\n */\nexport function renderOpComposeScript(input: OpComposeScriptInput): string {\n if (!REGION_RE.test(input.region)) {\n throw new Error(\n `region ${JSON.stringify(input.region)} contains characters not allowed in a launchd / Keychain service identifier`,\n );\n }\n if (input.promptServiceUrl !== undefined && !PROMPT_SERVICE_URL_RE.test(input.promptServiceUrl)) {\n throw new Error(\n `promptServiceUrl ${JSON.stringify(input.promptServiceUrl)} contains characters not allowed in a wrapper export`,\n );\n }\n const promptServiceUrlExport =\n input.promptServiceUrl !== undefined\n ? `# Backend services call prompt-service via this URL. Service-level env\n# from docker-compose-prompt-service.yml overlay (when layered) wins\n# over this default — so colocated deployments still hit\n# http://opuspopuli-prompts:3210 even though we may have a public URL\n# baked in here.\nexport PROMPT_SERVICE_URL=\"\\${PROMPT_SERVICE_URL:-${input.promptServiceUrl}}\"\n\n`\n : '';\n\n return `#!/bin/bash\n# op-compose — wrapper that reads region secrets from macOS Keychain just\n# before invoking \\`docker compose\\`. Auto-generated by\n# \\`create-op-node bootstrap --region ${input.region}\\`. Do not edit by\n# hand; re-run bootstrap to regenerate.\n#\n# Why: launchctl setenv only propagates to launchd-spawned processes, so\n# SSH shells and pre-existing Terminal.app instances never see the env\n# vars bootstrap exports. This wrapper hydrates the docker compose\n# subprocess directly, so every invocation works regardless of how the\n# operator's shell was started.\n#\n# Usage:\n# ./bin/op-compose -f docker-compose-prod.yml up -d\n# ./bin/op-compose -f docker-compose-prod.yml pull\n# ./bin/op-compose -f docker-compose-prod.yml down\n\nset -euo pipefail\n\nSVC=\"org.opuspopuli.${input.region}\"\n\n# macOS \\`security\\` exit codes:\n# 0 = success\n# 36 = errSecInteractionNotAllowed (keychain is locked)\n# 44 = errSecItemNotFound (entry doesn't exist)\n# Earlier wrapper versions conflated 36 and 44 into a generic \"missing\"\n# message, which sent operators down the wrong path (re-bootstrap when\n# the real fix was \\`security unlock-keychain\\`).\nrequire_secret() {\n local account=\"$1\"\n local value\n local rc=0\n value=$(security find-generic-password -s \"$SVC\" -a \"$account\" -w 2>/dev/null) || rc=$?\n case \"$rc\" in\n 0)\n printf '%s' \"$value\"\n return 0\n ;;\n 36)\n cat >&2 <<EOM\nop-compose: keychain is LOCKED — could not read entry '$account'.\nSSH sessions don't auto-unlock the login keychain. Unlock with:\n security unlock-keychain ~/Library/Keychains/login.keychain-db\nThen re-run this command.\nEOM\n exit 1\n ;;\n 44)\n cat >&2 <<EOM\nop-compose: keychain entry '$account' is MISSING under service '$SVC'.\nRun: create-op-node bootstrap --region ${input.region}\nEOM\n exit 1\n ;;\n *)\n echo \"op-compose: \\`security\\` failed reading '$account' (exit $rc).\" >&2\n exit 1\n ;;\n esac\n}\n\n# Used for entries that may legitimately not exist (TUNNEL_TOKEN in\n# local-only mode, prompt-service secrets when colocation isn't active).\n# Treats exit 44 (missing) as a silent OK — returns empty string.\n# Treats exit 36 (locked) as a hard error, since the require_secret calls\n# at the top of the wrapper would have caught this first in normal use;\n# reaching this path means something else bypassed the lock check.\noptional_secret() {\n local account=\"$1\"\n local value\n local rc=0\n value=$(security find-generic-password -s \"$SVC\" -a \"$account\" -w 2>/dev/null) || rc=$?\n case \"$rc\" in\n 0) printf '%s' \"$value\" ;;\n 44) ;; # legitimately absent — empty string is correct\n 36)\n cat >&2 <<EOM\nop-compose: keychain is LOCKED — could not probe optional entry '$account'.\nUnlock with: security unlock-keychain ~/Library/Keychains/login.keychain-db\nEOM\n exit 1\n ;;\n *)\n echo \"op-compose: \\`security\\` failed reading '$account' (exit $rc).\" >&2\n exit 1\n ;;\n esac\n}\n\n# Bootstrap-critical: Postgres + Supabase admin credentials.\nexport PGSODIUM_ROOT_KEY=\"$(require_secret pgsodium-root-key)\"\nexport POSTGRES_PASSWORD=\"$(require_secret postgres-password)\"\nexport JWT_SECRET=\"$(require_secret jwt-secret)\"\nexport SUPABASE_ANON_KEY=\"$(require_secret supabase-anon-key)\"\nexport SUPABASE_SERVICE_ROLE_KEY=\"$(require_secret supabase-service-role-key)\"\nexport DASHBOARD_PASSWORD=\"$(require_secret dashboard-password)\"\n\n# AUTH_JWT_SECRET historically equals JWT_SECRET in dev/UAT — supply that\n# default if the operator hasn't set one independently.\nexport AUTH_JWT_SECRET=\"\\${AUTH_JWT_SECRET:-$JWT_SECRET}\"\n\n# Optional: Cloudflare Tunnel token (only present in non-local-only mode).\nTUNNEL_TOKEN_VAL=\"$(optional_secret tunnel-token)\"\nif [ -n \"$TUNNEL_TOKEN_VAL\" ]; then\n export TUNNEL_TOKEN=\"$TUNNEL_TOKEN_VAL\"\nfi\n\n# SUPABASE_URL is not a secret — read from env if the operator set one,\n# default to localhost for --local-only.\nexport SUPABASE_URL=\"\\${SUPABASE_URL:-http://localhost:8000}\"\n\n${promptServiceUrlExport}# prompt-service credentials. Always exported — harmless when the operator\n# is NOT colocating prompt-service (the main compose doesn't read these\n# vars; the overlay does). The PROMPT_SERVICE_API_KEYS list is built from\n# the operator's region + the single HMAC key in Keychain, matching the\n# prompt-service env format \\`<region>:<key>,<region>:<key>,…\\`.\nPROMPTS_DB_PASSWORD_VAL=\"$(optional_secret prompts-db-password)\"\nPROMPT_SERVICE_API_KEY_VAL=\"$(optional_secret prompt-service-api-key)\"\nPROMPT_SERVICE_ADMIN_API_KEY_VAL=\"$(optional_secret prompt-service-admin-api-key)\"\nif [ -n \"$PROMPTS_DB_PASSWORD_VAL\" ]; then\n export PROMPTS_DB_PASSWORD=\"$PROMPTS_DB_PASSWORD_VAL\"\nfi\nif [ -n \"$PROMPT_SERVICE_API_KEY_VAL\" ]; then\n export PROMPT_SERVICE_API_KEY=\"$PROMPT_SERVICE_API_KEY_VAL\"\n # API_KEYS env on prompt-service is \\`<region>:<key>,…\\` — render the\n # single-region pair here so prompt-service accepts the same key the\n # backend sends. The prompts team adds additional regions on the\n # central deployment for Phase 2.\n export PROMPT_SERVICE_API_KEYS=\"${input.region}:$PROMPT_SERVICE_API_KEY_VAL\"\nfi\nif [ -n \"$PROMPT_SERVICE_ADMIN_API_KEY_VAL\" ]; then\n export PROMPT_SERVICE_ADMIN_API_KEYS=\"$PROMPT_SERVICE_ADMIN_API_KEY_VAL\"\nfi\n\nexec docker compose \"$@\"\n`;\n}\n","/**\n * Side-effecting installer for the `bin/op-compose` wrapper script.\n *\n * Pure rendering lives in op-compose-script.ts so it stays unit-testable.\n * This file owns:\n * 1. Creating `<repo>/bin/` if needed\n * 2. Atomically writing the script (temp file + rename) so an\n * interrupted bootstrap never leaves a half-written wrapper that\n * `exec` would crash on\n * 3. `chmod 0755` so the operator can run `./bin/op-compose`\n */\n\nimport { chmod, mkdir, rename, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { renderOpComposeScript, type OpComposeScriptInput } from './op-compose-script.js';\n\nexport interface InstallOpComposeInput extends OpComposeScriptInput {\n /** Directory containing the compose file. Script lands at `<repoDir>/bin/op-compose`. */\n repoDir: string;\n}\n\nexport interface InstallOpComposeResult {\n ok: boolean;\n /** Absolute path the script was written to, when ok=true. */\n path?: string;\n reason?: string;\n}\n\nexport async function installOpComposeWrapper(\n input: InstallOpComposeInput,\n): Promise<InstallOpComposeResult> {\n let content: string;\n try {\n content = renderOpComposeScript({\n region: input.region,\n ...(input.promptServiceUrl !== undefined ? { promptServiceUrl: input.promptServiceUrl } : {}),\n });\n } catch (err) {\n return { ok: false, reason: (err as Error).message };\n }\n\n const binDir = join(input.repoDir, 'bin');\n const target = join(binDir, 'op-compose');\n const tmp = `${target}.tmp.${process.pid}`;\n\n try {\n await mkdir(binDir, { recursive: true });\n await writeFile(tmp, content, { mode: 0o755 });\n // mkdir/writeFile respect umask; chmod ensures 0755 regardless.\n await chmod(tmp, 0o755);\n await rename(tmp, target); // atomic on POSIX\n return { ok: true, path: target };\n } catch (err) {\n return { ok: false, reason: `writing ${target} failed: ${(err as Error).message}` };\n }\n}\n","/**\n * Docker compose + ghcr.io login orchestration.\n *\n * Three concerns this lib covers:\n *\n * 1. Authenticate Docker to ghcr.io using the operator's `gh auth token`,\n * piped on stdin so the token never lands in argv.\n * 2. `docker compose pull / up -d` against the prod compose set in the\n * operator's node repo checkout.\n * 3. Poll `docker compose ps --format json` until every service reports\n * `(healthy)`, with the same two-phase-budget pattern as lib/polling.ts\n * (containers can take a while to start showing up; healthy check then\n * runs on its own clock).\n */\n\nimport { safeExeca } from './exec.js';\n\n/** Default registry. Constant so tests + the bootstrap command read the same\n * value and an op-region migration to a different registry only changes\n * one place. */\nexport const GHCR_REGISTRY = 'ghcr.io';\n\nexport interface LoginResult {\n ok: boolean;\n reason?: string;\n}\n\n/**\n * Authenticate Docker to ghcr.io. Pulls the token from `gh auth token`,\n * pipes it on stdin to `docker login --password-stdin`. The username comes\n * from `gh api user --jq .login`. Three execa calls; failure at any point\n * reports cleanly with the responsible step.\n */\nexport async function loginToGhcr(): Promise<LoginResult> {\n const tokenRes = await safeExeca('gh', ['auth', 'token']);\n if (tokenRes === null) return { ok: false, reason: '`gh` not installed' };\n if (tokenRes.exitCode !== 0) {\n return {\n ok: false,\n reason: `gh auth token failed (${tokenRes.exitCode ?? 'signal'}): ${tokenRes.stderr || tokenRes.stdout}`,\n };\n }\n const token = tokenRes.stdout.trim();\n if (token.length === 0) {\n return { ok: false, reason: 'gh auth token returned empty — run `gh auth login` first' };\n }\n\n const userRes = await safeExeca('gh', ['api', 'user', '--jq', '.login']);\n if (userRes === null || userRes.exitCode !== 0) {\n return {\n ok: false,\n reason: `couldn't resolve GitHub user via gh api: ${userRes?.stderr || userRes?.stdout || 'gh missing'}`,\n };\n }\n const user = userRes.stdout.trim();\n if (user.length === 0) {\n return { ok: false, reason: 'gh api user returned empty — gh not signed in' };\n }\n\n const loginRes = await safeExeca(\n 'docker',\n ['login', GHCR_REGISTRY, '-u', user, '--password-stdin'],\n { input: token },\n );\n if (loginRes === null) return { ok: false, reason: '`docker` not installed' };\n if (loginRes.exitCode !== 0) {\n return {\n ok: false,\n reason: `docker login ${GHCR_REGISTRY} failed (${loginRes.exitCode ?? 'signal'}): ${loginRes.stderr || loginRes.stdout}`,\n };\n }\n return { ok: true };\n}\n\n// ----------------------------------------------------------------------------\n// Compose pull / up\n// ----------------------------------------------------------------------------\n\nexport interface ComposeOptions {\n /** Compose file paths, in order. Becomes `-f X -f Y …` on the command line. */\n files: string[];\n /** Working directory the compose command runs from. */\n cwd: string;\n /** Optional env-file flag, in the same convention as `--env-file`. */\n envFile?: string;\n /** Compose profiles to activate. Repeats as `--profile X --profile Y`. The\n * template's `cloudflared` service is gated behind the `public` profile;\n * bootstrap in local-only mode passes an empty array so cloudflared\n * stays down. */\n profiles?: ReadonlyArray<string>;\n /** Extra env vars passed to the docker compose subprocess. Used by\n * bootstrap to hydrate Keychain-loaded secrets (POSTGRES_PASSWORD,\n * JWT_SECRET, the Supabase JWTs, etc.) at compose-invocation time\n * without writing them to a plaintext `.env` file on disk. Per the\n * vault-first principle (#811), the wrapper script (`bin/op-compose`)\n * is the operator-facing version of the same pattern. */\n env?: NodeJS.ProcessEnv;\n}\n\nfunction composeArgs(opts: ComposeOptions, sub: string[]): string[] {\n const files = opts.files.flatMap((f) => ['-f', f]);\n const env = opts.envFile ? ['--env-file', opts.envFile] : [];\n const profiles = (opts.profiles ?? []).flatMap((pr) => ['--profile', pr]);\n return ['compose', ...files, ...env, ...profiles, ...sub];\n}\n\nexport interface ComposeResult {\n ok: boolean;\n reason?: string;\n}\n\n/** Build the execa options object once — both env and cwd flow from\n * ComposeOptions to safeExeca so subprocess hydration works uniformly. */\nfunction execOpts(opts: ComposeOptions): { cwd: string; env?: NodeJS.ProcessEnv } {\n return opts.env ? { cwd: opts.cwd, env: opts.env } : { cwd: opts.cwd };\n}\n\n/** `docker compose -f … pull`. Idempotent on first run; pulls new image tags. */\nexport async function composePull(opts: ComposeOptions): Promise<ComposeResult> {\n const res = await safeExeca('docker', composeArgs(opts, ['pull']), execOpts(opts));\n return result(res, 'compose pull');\n}\n\n/** `docker compose -f … up -d --remove-orphans`. */\nexport async function composeUp(opts: ComposeOptions): Promise<ComposeResult> {\n const res = await safeExeca('docker', composeArgs(opts, ['up', '-d', '--remove-orphans']), execOpts(opts));\n return result(res, 'compose up');\n}\n\n/**\n * `docker compose -f … rm -sfv <service>`. Stops + removes a single service +\n * its anonymous volumes. Used by `bootstrap --local-only` to evict a\n * cloudflared container left over from a prior public bootstrap; otherwise it\n * lingers in `compose ps` and the health-check loop demands it reach healthy.\n *\n * Returns ok=true when the service doesn't exist (compose treats \"rm a\n * service that isn't there\" as a no-op exit 0), so callers can call this\n * unconditionally.\n */\nexport async function composeRemoveService(\n opts: ComposeOptions,\n service: string,\n): Promise<ComposeResult> {\n const res = await safeExeca('docker', composeArgs(opts, ['rm', '-sfv', service]), execOpts(opts));\n return result(res, `compose rm ${service}`);\n}\n\nexport interface ComposeDownOptions extends ComposeOptions {\n /** When true, adds `-v` — destroys named volumes. The default false is the\n * safe choice: stop the stack but preserve the database. Callers must\n * ALWAYS surface a typed confirmation before flipping this on. */\n wipeVolumes?: boolean;\n /** When true, adds `--remove-orphans` — drops containers from compose files\n * no longer present. Useful on first-after-rename runs. */\n removeOrphans?: boolean;\n /** When set, adds `--rmi <mode>` to also remove the images.\n * - `'all'`: removes all images referenced by services (forces re-pull\n * on next `compose up`).\n * - `'local'`: removes only images that don't have a custom tag (i.e.,\n * locally-built ones; pulled images stay).\n * Use 'all' for true \"wipe everything and start over\" iteration loops. */\n removeImages?: 'all' | 'local';\n}\n\n/** `docker compose -f … down [-v] [--remove-orphans] [--rmi MODE]`. */\nexport async function composeDown(opts: ComposeDownOptions): Promise<ComposeResult> {\n const flags: string[] = ['down'];\n if (opts.wipeVolumes) flags.push('-v');\n if (opts.removeOrphans) flags.push('--remove-orphans');\n if (opts.removeImages) flags.push('--rmi', opts.removeImages);\n const label = [\n 'compose down',\n opts.wipeVolumes ? '-v' : '',\n opts.removeImages ? `--rmi ${opts.removeImages}` : '',\n ]\n .filter(Boolean)\n .join(' ');\n const res = await safeExeca('docker', composeArgs(opts, flags), execOpts(opts));\n return result(res, label);\n}\n\n/**\n * `docker logout <registry>`.\n *\n * Behavior on \"not currently logged in\" varies by version: Docker 24+ returns\n * exit 0 with \"Not logged in to <registry>\" on stdout, but older Docker\n * Desktop releases (and some credential-helper configurations) return a\n * non-zero exit instead. `reset` therefore renders a non-zero outcome as a\n * warning rather than a failure — the goal is \"ensure no creds remain,\" and\n * \"no creds existed to begin with\" satisfies that goal.\n *\n * Note: this only clears the credential-store entry. If the operator's\n * credential helper has cached the token elsewhere, or if `~/.docker/config.json`\n * has stale entries from a different host, those need separate cleanup.\n */\nexport async function dockerLogout(registry: string = GHCR_REGISTRY): Promise<ComposeResult> {\n const res = await safeExeca('docker', ['logout', registry]);\n return result(res, `docker logout ${registry}`);\n}\n\nfunction result(\n res: { exitCode: number | undefined; stdout: string; stderr: string } | null,\n label: string,\n): ComposeResult {\n if (res === null) return { ok: false, reason: '`docker` not installed' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `${label} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\n// ----------------------------------------------------------------------------\n// Compose ps — for the health check loop\n// ----------------------------------------------------------------------------\n\nexport interface ContainerSnapshot {\n name: string;\n /** `running`, `exited`, etc. — the Docker container state. */\n state: string;\n /** `healthy`, `unhealthy`, `starting`, or `none` (no healthcheck defined). */\n health: 'healthy' | 'unhealthy' | 'starting' | 'none';\n exitCode: number | null;\n}\n\n/**\n * Parse `docker compose ps --format json` output. Compose v2 emits one JSON\n * object per line for each container. We tolerate either format (NDJSON or\n * a single-line JSON array, depending on version).\n */\nexport function parseComposePs(stdout: string): ContainerSnapshot[] {\n // First try NDJSON line-by-line.\n const trimmed = stdout.trim();\n if (trimmed.length === 0) return [];\n\n const lines = trimmed.split('\\n').map((l) => l.trim()).filter((l) => l.length > 0);\n const out: ContainerSnapshot[] = [];\n\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as unknown;\n if (Array.isArray(parsed)) {\n for (const item of parsed) out.push(normalize(item));\n } else {\n out.push(normalize(parsed));\n }\n } catch {\n // Skip non-JSON lines (compose sometimes emits warnings on stdout).\n }\n }\n return out;\n}\n\nfunction normalize(raw: unknown): ContainerSnapshot {\n const r = (raw ?? {}) as Record<string, unknown>;\n const name = (r['Name'] as string) ?? (r['Service'] as string) ?? '<unknown>';\n const state = ((r['State'] as string) ?? 'unknown').toLowerCase();\n const healthRaw = ((r['Health'] as string) ?? '').toLowerCase();\n const health: ContainerSnapshot['health'] =\n healthRaw === 'healthy' || healthRaw === 'unhealthy' || healthRaw === 'starting'\n ? healthRaw\n : 'none';\n const exitCodeRaw = r['ExitCode'];\n const exitCode = typeof exitCodeRaw === 'number' ? exitCodeRaw : null;\n return { name, state, health, exitCode };\n}\n\n/**\n * `docker compose ps --format json`. Returns:\n *\n * - `null` when the call itself failed (docker missing, compose file wrong,\n * non-zero exit). The caller can distinguish a real failure from a\n * stack-not-up-yet case.\n * - `[]` when the call succeeded but no containers are listed yet (compose\n * up still in flight).\n * - `ContainerSnapshot[]` populated on success.\n */\nexport async function composePs(opts: ComposeOptions): Promise<ContainerSnapshot[] | null> {\n const res = await safeExeca('docker', composeArgs(opts, ['ps', '--format', 'json']), execOpts(opts));\n if (res === null || res.exitCode !== 0) return null;\n return parseComposePs(res.stdout);\n}\n\n// ----------------------------------------------------------------------------\n// Health-check loop\n// ----------------------------------------------------------------------------\n\nexport interface WaitForHealthyOptions {\n /** Container names that MUST be healthy before we return success. Empty\n * array means \"every container compose ps reports must be healthy or no-op\n * (i.e. state=exited with code 0 — db-migrate-style one-shots).\" */\n requireHealthy?: string[];\n /** Max time to wait, ms. Default 5 minutes. */\n timeoutMs?: number;\n /** Poll interval, ms. Default 5s. */\n pollMs?: number;\n /** Optional progress callback. */\n onPoll?: (snapshots: ContainerSnapshot[]) => void;\n}\n\nexport type HealthOutcome =\n | { kind: 'healthy'; snapshots: ContainerSnapshot[] }\n | { kind: 'unhealthy'; snapshots: ContainerSnapshot[]; problem: string }\n | { kind: 'timeout'; snapshots: ContainerSnapshot[] };\n\nexport interface WaitForHealthyDeps {\n ps: (opts: ComposeOptions) => Promise<ContainerSnapshot[] | null>;\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n}\n\nexport const realWaitDeps: WaitForHealthyDeps = {\n ps: composePs,\n sleep: (ms) => new Promise((res) => setTimeout(res, ms)),\n now: () => Date.now(),\n};\n\n/**\n * Poll `compose ps` until either every container reaches a happy terminal\n * state or the timeout fires. A \"happy\" state is:\n *\n * - `state=running` AND `health` ∈ {healthy, none}\n * - `state=exited` AND `exitCode === 0` (one-shot containers like db-migrate)\n *\n * `state=running` + `health=starting` keeps polling; `health=unhealthy` or\n * `state=exited` with non-zero exit returns immediately as `unhealthy`.\n */\n// Map a single non-empty poll result to a terminal HealthOutcome, or null\n// when the caller should keep polling ('pending' or no containers yet).\nfunction terminalOutcome(\n ps: ContainerSnapshot[],\n requireHealthy?: string[],\n): HealthOutcome | null {\n if (ps.length === 0) return null;\n const verdict = assessHealth(ps, requireHealthy);\n if (verdict.kind === 'healthy') return { kind: 'healthy', snapshots: ps };\n if (verdict.kind === 'unhealthy') {\n return { kind: 'unhealthy', snapshots: ps, problem: verdict.problem ?? 'unhealthy' };\n }\n return null;\n}\n\nexport async function waitForHealthy(\n composeOpts: ComposeOptions,\n options: WaitForHealthyOptions = {},\n deps: WaitForHealthyDeps = realWaitDeps,\n): Promise<HealthOutcome> {\n const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;\n const basePollMs = options.pollMs ?? 5 * 1000;\n const start = deps.now();\n let last: ContainerSnapshot[] = [];\n let pollCount = 0;\n\n while (deps.now() - start < timeoutMs) {\n pollCount++;\n const ps = await deps.ps(composeOpts);\n if (ps !== null) {\n last = ps;\n options.onPoll?.(ps);\n // A terminal verdict (healthy / unhealthy) returns immediately;\n // 'pending' (null here) falls through to the sleep + next iteration.\n const outcome = terminalOutcome(ps, options.requireHealthy);\n if (outcome) return outcome;\n }\n // Gentle backoff: 1× the base poll for the first 3 polls (fast feedback\n // while containers are settling), 2× after that. Caps wasted subprocess\n // startup on long timeouts without slowing down the typical case.\n const interval = pollCount < 3 ? basePollMs : basePollMs * 2;\n await deps.sleep(interval);\n }\n return { kind: 'timeout', snapshots: last };\n}\n\ninterface AssessVerdict {\n kind: 'healthy' | 'unhealthy' | 'pending';\n problem?: string;\n}\n\nexport function assessHealth(\n snapshots: ContainerSnapshot[],\n requireHealthy?: string[],\n): AssessVerdict {\n // Hard failures short-circuit regardless of the required-list mode.\n const hard = firstHardFailure(snapshots);\n if (hard) return hard;\n\n const required = requireHealthy ?? [];\n return required.length > 0\n ? assessRequired(snapshots, required)\n : assessAllRunning(snapshots);\n}\n\n// Hard failure conditions: any unhealthy, any exited-with-non-zero.\nfunction firstHardFailure(snapshots: ContainerSnapshot[]): AssessVerdict | null {\n for (const s of snapshots) {\n if (s.health === 'unhealthy') {\n return { kind: 'unhealthy', problem: `${s.name} reports unhealthy` };\n }\n if (s.state === 'exited' && (s.exitCode ?? 0) !== 0) {\n return { kind: 'unhealthy', problem: `${s.name} exited with code ${s.exitCode}` };\n }\n }\n return null;\n}\n\n// The caller specified a required-healthy list — gate on exactly those.\nfunction assessRequired(snapshots: ContainerSnapshot[], required: string[]): AssessVerdict {\n const byName = new Map(snapshots.map((s) => [s.name, s]));\n for (const name of required) {\n const s = byName.get(name);\n if (!s) return { kind: 'pending' };\n if (s.state === 'exited' && s.exitCode === 0) continue;\n if (s.state !== 'running') return { kind: 'pending' };\n if (s.health === 'starting') return { kind: 'pending' };\n if (s.health === 'unhealthy') {\n return { kind: 'unhealthy', problem: `${s.name} reports unhealthy` };\n }\n }\n return { kind: 'healthy' };\n}\n\n// No required list — all snapshots must be in a happy state.\nfunction assessAllRunning(snapshots: ContainerSnapshot[]): AssessVerdict {\n for (const s of snapshots) {\n if (s.state === 'exited' && s.exitCode === 0) continue;\n if (s.state !== 'running') return { kind: 'pending' };\n if (s.health === 'starting') return { kind: 'pending' };\n }\n return { kind: 'healthy' };\n}\n","/**\n * Ollama service + model management.\n *\n * Ollama is installed via Homebrew (handled by `lib/homebrew.ts`) and started\n * as a `brew services` job. This lib covers what the wizard does after that:\n *\n * - HTTP health check on `localhost:11434` (the running daemon).\n * - List installed models via the HTTP API (avoids parsing `ollama list`'s\n * human-formatted output).\n * - Pull a model — shells out to `ollama pull <name>` because the HTTP\n * `/api/pull` endpoint streams NDJSON progress and is awkward to consume.\n * - Warm a model with a single trivial generation so the first user request\n * doesn't pay a ~90s cold-start.\n * - Probe that containers can reach the host's Ollama via\n * `host.docker.internal` — common Docker Desktop configuration mistake.\n */\n\nimport { safeExeca } from './exec.js';\n\nexport const OLLAMA_URL = 'http://localhost:11434';\n\n/** Default LLM the platform ships against — small enough to pull on a fresh\n * Studio in minutes, capable enough to validate the inference path\n * end-to-end. Operators can override at bootstrap time with `--llm-model`,\n * and we surface a sizing table in `docs/docker-resources.md` for the\n * 70B-class jump. */\nexport const DEFAULT_LLM_MODEL = 'qwen3.5:9b';\n\n/** Default embedding model used by the knowledge service when\n * `EMBEDDINGS_PROVIDER=ollama`. With the default `xenova` (in-process)\n * provider, this isn't pulled. Operators can override with\n * `--embedding-model`. */\nexport const DEFAULT_EMBEDDING_MODEL = 'nomic-embed-text';\n\n/** Default model pull set for `bootstrap`. Kept as a `as const`-typed array\n * so existing code can iterate without re-deriving from the two scalars. */\nexport const DEFAULT_MODELS = [DEFAULT_LLM_MODEL, DEFAULT_EMBEDDING_MODEL] as const;\n\n/** Pinned alpine tag for the host.docker.internal probe. Latest is fine in\n * practice (the image only runs `curl`) but pinning keeps the probe\n * reproducible across operator machines. Bump when alpine cuts a major. */\nexport const PROBE_ALPINE_TAG = '3.20';\n\nexport interface OllamaHealth {\n /** True when the daemon answered the `/api/tags` probe with 200. */\n reachable: boolean;\n /** Names of currently-installed models, when reachable. */\n models: string[];\n}\n\n/**\n * Probe the daemon. We use `/api/tags` because it's the cheapest endpoint\n * that proves both reachability AND that the server is past initial bring-up\n * (a bare TCP-accept-but-not-ready Ollama returns 404 here, not 200).\n */\n/**\n * Try to start the Ollama service via `brew services start ollama`.\n * Idempotent — brew services no-ops on an already-started service. Returns\n * `ok: false` only if brew itself is missing or the start command errored\n * for a non-trivial reason.\n */\nexport async function startOllamaService(): Promise<{ ok: boolean; reason?: string }> {\n const res = await safeExeca('brew', ['services', 'start', 'ollama']);\n if (res === null) return { ok: false, reason: '`brew` not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `brew services start ollama failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport async function checkOllamaHealth(url: string = OLLAMA_URL): Promise<OllamaHealth> {\n try {\n const res = await fetch(`${url}/api/tags`);\n if (!res.ok) return { reachable: false, models: [] };\n const body = (await res.json()) as { models?: Array<{ name?: string }> };\n const models = (body.models ?? [])\n .map((m) => m.name ?? '')\n .filter((n) => n.length > 0);\n return { reachable: true, models };\n } catch {\n return { reachable: false, models: [] };\n }\n}\n\nexport interface PullResult {\n ok: boolean;\n /** Set when ok=false. */\n reason?: string;\n}\n\n/**\n * Pull a model. `ollama pull` is idempotent — re-pulling a present model is\n * a fast no-op — so we don't pre-check installation.\n */\nexport async function pullModel(name: string): Promise<PullResult> {\n const res = await safeExeca('ollama', ['pull', name]);\n if (res === null) return { ok: false, reason: '`ollama` not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason: `ollama pull ${name} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true };\n}\n\nexport interface WarmResult {\n ok: boolean;\n reason?: string;\n}\n\n/**\n * Send a trivial `/api/generate` call so the model loads into memory. First\n * request on a cold daemon can take 30-90s; that latency lands on the wizard,\n * not on a real user. We stream=false + ignore the response body.\n */\nexport async function warmModel(name: string, url: string = OLLAMA_URL): Promise<WarmResult> {\n try {\n const res = await fetch(`${url}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: name, prompt: 'hi', stream: false }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n return {\n ok: false,\n reason: `warm ${name} returned HTTP ${res.status}: ${text || '(no body)'}`,\n };\n }\n // Drain the body to ensure the model finished loading.\n await res.text();\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n reason: `warm ${name} failed: ${(err as Error).message}`,\n };\n }\n}\n\n/**\n * Verify Docker containers can reach the host's Ollama via\n * `host.docker.internal`. Operators sometimes disable that hostname in Docker\n * Desktop settings; this probe catches the misconfig before the stack comes\n * up and fails opaquely.\n */\nexport async function probeHostDockerInternal(): Promise<{ ok: boolean; reason?: string }> {\n const res = await safeExeca('docker', [\n 'run',\n '--rm',\n `alpine:${PROBE_ALPINE_TAG}`,\n 'sh',\n '-c',\n 'apk add --no-cache curl >/dev/null 2>&1 && curl -fsS http://host.docker.internal:11434/api/tags',\n ]);\n if (res === null) return { ok: false, reason: '`docker` not on PATH' };\n if (res.exitCode !== 0) {\n return {\n ok: false,\n reason:\n `container couldn't reach host.docker.internal:11434 — check Docker Desktop ` +\n `settings → Resources → Network → Enable host.docker.internal`,\n };\n }\n return { ok: true };\n}\n\nexport interface SetupReport {\n pulled: string[];\n alreadyPresent: string[];\n failed: Array<{ model: string; reason: string }>;\n warmed: string[];\n}\n\n/**\n * Pull each model in `models` (skipping already-present ones) and warm the\n * first one. Continues past per-model failures so the operator sees the\n * whole landscape.\n */\nexport async function setupModels(\n models: readonly string[],\n onProgress?: (model: string, status: 'present' | 'pulling' | 'pulled' | 'failed' | 'warming' | 'warmed') => void,\n): Promise<SetupReport> {\n const report: SetupReport = {\n pulled: [],\n alreadyPresent: [],\n failed: [],\n warmed: [],\n };\n\n const health = await checkOllamaHealth();\n const present = new Set(health.models);\n\n for (const m of models) {\n if (present.has(m)) {\n report.alreadyPresent.push(m);\n onProgress?.(m, 'present');\n continue;\n }\n onProgress?.(m, 'pulling');\n const r = await pullModel(m);\n if (r.ok) {\n report.pulled.push(m);\n onProgress?.(m, 'pulled');\n } else {\n report.failed.push({ model: m, reason: r.reason ?? 'unknown' });\n onProgress?.(m, 'failed');\n }\n }\n\n // Warm the first model that exists by name in the user-supplied list, not\n // necessarily the first to pull successfully — keeps the warm target\n // predictable for tests + operator UX.\n const warmTarget = models.find((m) => present.has(m) || report.pulled.includes(m));\n if (warmTarget) {\n onProgress?.(warmTarget, 'warming');\n const w = await warmModel(warmTarget);\n if (w.ok) {\n report.warmed.push(warmTarget);\n onProgress?.(warmTarget, 'warmed');\n }\n // A failed warm-up isn't fatal — it just means the first real user\n // request pays the cold-start cost. Surface in the report.\n }\n\n return report;\n}\n","/**\n * Locate or clone the operator's node deployment repo on the Mac Studio.\n *\n * The bootstrap subcommand wants a working tree of the operator's region\n * deployment repo (created from `OpusPopuli/opuspopuli-node` by `init`) on\n * the Studio's filesystem — it's the source of `docker-compose-prod.yml`,\n * `supabase/init/`, `backup/scripts/`, `observability/`, etc.\n *\n * Three discovery paths the wizard tries in order:\n *\n * 1. **Explicit `--repo-dir`** — operator passed a path. Verify it's a\n * node repo (looks for the marker file) and use it.\n * 2. **Current directory** — operator may have already cloned + cd'd.\n * Same marker probe.\n * 3. **Clone fresh** — shell out to `gh repo clone <owner>/<repo>` into\n * `~/Development/<repo>`. The default location keeps it under the\n * operator's home (no sudo) and groups it with other dev work.\n */\n\nimport { access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nimport { safeExeca } from './exec.js';\n\n/** Files that a freshly-cloned (or template-derived) node repo always has.\n * Probing for these is how we distinguish a node repo from an arbitrary\n * directory the operator pointed us at. */\nexport const NODE_REPO_MARKERS = [\n 'docker-compose-prod.yml',\n 'supabase/init/pgsodium_getkey_env.sh',\n] as const;\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** True when every marker file is present at `dir`. False otherwise. */\nexport async function looksLikeNodeRepo(dir: string): Promise<boolean> {\n const checks = await Promise.all(\n NODE_REPO_MARKERS.map((m) => fileExists(join(dir, m))),\n );\n return checks.every((ok) => ok);\n}\n\nexport interface LocateInput {\n /** Owner of the node repo, e.g. `OpusPopuli`. */\n owner: string;\n /** Repo name, e.g. `opuspopuli-node-us-ca`. */\n name: string;\n /** Operator-supplied override (--repo-dir). When set, we use it iff it\n * looks like a node repo; otherwise return an error rather than fall\n * through to cloning a fresh copy. */\n explicit?: string;\n /** Where to put a fresh clone when neither --repo-dir nor cwd matches.\n * Default: ~/Development/<name>. */\n cloneInto?: string;\n /** When false, refuse to clone and require the operator to provide\n * a working tree (skip the gh shell-out). Default: true. */\n allowClone?: boolean;\n /** Working directory to probe as the \"already-cloned-and-cd'd\" path. */\n cwd?: string;\n}\n\nexport type LocateOutcome =\n | { kind: 'found'; path: string; source: 'explicit' | 'cwd' }\n | { kind: 'cloned'; path: string }\n | { kind: 'explicit-not-a-node-repo'; path: string }\n | { kind: 'gh-not-installed' }\n | { kind: 'clone-failed'; reason: string }\n | { kind: 'clone-disallowed' };\n\n/**\n * Walk the three discovery paths and return a discriminated outcome the\n * wizard can render. Cleanly separates \"operator-intentional path\" failures\n * from \"we tried but couldn't help\" failures.\n */\nexport async function locateOrCloneRepo(input: LocateInput): Promise<LocateOutcome> {\n // 1. Explicit --repo-dir.\n if (input.explicit) {\n if (await looksLikeNodeRepo(input.explicit)) {\n return { kind: 'found', path: input.explicit, source: 'explicit' };\n }\n return { kind: 'explicit-not-a-node-repo', path: input.explicit };\n }\n\n // 2. CWD probe.\n const cwd = input.cwd ?? process.cwd();\n if (await looksLikeNodeRepo(cwd)) {\n return { kind: 'found', path: cwd, source: 'cwd' };\n }\n\n // 3. Clone fresh.\n if (input.allowClone === false) {\n return { kind: 'clone-disallowed' };\n }\n\n const target = input.cloneInto ?? join(homedir(), 'Development', input.name);\n const res = await safeExeca('gh', ['repo', 'clone', `${input.owner}/${input.name}`, target]);\n if (res === null) return { kind: 'gh-not-installed' };\n if (res.exitCode !== 0) {\n return {\n kind: 'clone-failed',\n reason: `gh repo clone failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { kind: 'cloned', path: target };\n}\n","/**\n * Compile-time exhaustiveness guard. Passing a value that TypeScript has\n * not narrowed to `never` is a type error, so an unhandled `switch` / `if`\n * variant fails the build. At runtime this is a no-op — callers keep their\n * existing control flow (fall through, `return`, etc.).\n */\nexport function assertNever(_value: never): void {\n /* compile-time only */\n}\n","import { join } from 'node:path';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport {\n PGSODIUM_KEY_RE,\n SAFE_LAUNCHCTL_VALUE_RE,\n SAFE_URL_RE,\n TUNNEL_TOKEN_RE,\n URL_SAFE_PASSWORD_RE,\n} from '../lib/constants.js';\nimport {\n detectBrew,\n HOMEBREW_INSTALL_COMMAND,\n installPackages,\n STUDIO_PACKAGES,\n} from '../lib/homebrew.js';\nimport {\n detectUnifiedMemoryGB,\n disableDiskSleep,\n enableAutoRestartOnPowerFailure,\n inspectSystem,\n} from '../lib/macos.js';\nimport {\n detectKeychain,\n isKeychainLocked,\n isSshSession,\n readSecret,\n saveSecret,\n unlockKeychain,\n type SecretAccount,\n} from '../lib/keychain.js';\nimport {\n generateDashboardPassword,\n generateHmacApiKey,\n generateJwtSecret,\n generatePgsodiumRootKey,\n generatePostgresPassword,\n signSupabaseJwt,\n verifySupabaseJwt,\n} from '../lib/secrets.js';\nimport { setupLaunchAgent } from '../lib/launchagent.js';\nimport { installOpComposeWrapper } from '../lib/op-compose-install.js';\nimport {\n composePull,\n composeRemoveService,\n composeUp,\n loginToGhcr,\n waitForHealthy,\n} from '../lib/docker.js';\nimport {\n DEFAULT_EMBEDDING_MODEL,\n DEFAULT_LLM_MODEL,\n checkOllamaHealth,\n probeHostDockerInternal,\n setupModels,\n startOllamaService,\n} from '../lib/ollama.js';\nimport { locateOrCloneRepo, type LocateOutcome } from '../lib/noderepo.js';\nimport { safeExeca } from '../lib/exec.js';\nimport { unwrap } from '../lib/prompts.js';\nimport { assertNever } from '../lib/assert.js';\n\n/** Compose profile set used in production mode — activates cloudflared. */\nconst PUBLIC_PROFILES = ['public'] as const;\n/** Compose profile set used in --local-only mode — keeps cloudflared down\n * via the template's profile gating. */\nconst LOCAL_PROFILES = [] as const;\n\n/** Node deployment topology — selects which docker compose stack(s) +\n * Keychain entries bootstrap provisions.\n *\n * - `region` — standard region node (civic data for one region). Connects\n * to a REMOTE prompt-service via PROMPT_SERVICE_URL. The HMAC key for\n * that remote service is issued by the prompts team and pasted in;\n * bootstrap stores it under the same Keychain account as the colocated\n * case so the wrapper exports it transparently. This is the production\n * default for any operator who isn't on the prompts team.\n *\n * - `region-with-prompts` — region node + colocated prompt-service overlay\n * (the us-ca / team / dev case). Bootstrap generates a local HMAC key,\n * a prompt-service admin key, and a prompts-db password — all stored\n * in Keychain — and the op-compose wrapper exports them so the\n * `docker-compose-prompt-service.yml` overlay can layer on top.\n *\n * - `prompts-only` — STUB. Reserved for when the prompts team deploys the\n * central prompts.opuspopuli.org instance. No region services; only the\n * prompt-service + its DB. Bootstrap currently exits with a \"not yet\n * implemented\" message — the flag exists so the CLI surface is stable\n * for the future deployment.\n */\ntype NodeType = 'region' | 'region-with-prompts' | 'prompts-only';\n\ninterface BootstrapOptions {\n region?: string;\n owner?: string;\n repoDir?: string;\n composeFile?: string[];\n envFile?: string;\n skipBrew?: boolean;\n skipLaunchAgent?: boolean;\n skipOllama?: boolean;\n skipStack?: boolean;\n localOnly?: boolean;\n llmModel?: string;\n embeddingModel?: string;\n /** Public-facing Supabase URL. Defaults to `http://localhost:8000` in\n * --local-only mode, otherwise `https://supabase.<domain>` — operator\n * can override with --supabase-url. */\n supabaseUrl?: string;\n /** Selects which deployment stack to provision. Defaults to `region`. */\n nodeType?: NodeType;\n /** For `--node-type region` (remote prompt-service): the URL of the\n * central prompt-service the backend should call. Defaults to\n * `https://prompts.opuspopuli.org`. Ignored in `region-with-prompts`\n * (the overlay pins it to the in-network hostname). */\n promptServiceUrl?: string;\n yes?: boolean;\n}\n\nexport const bootstrapCommand = new Command('bootstrap')\n .description(\n 'Configure the Mac Studio and bring the stack up. Run this on the Studio itself, after `init` has finished on your laptop.',\n )\n .addOption(new Option('--region <slug>', 'Region label set during init (e.g. us-ca)'))\n .addOption(new Option('--owner <owner>', 'GitHub owner for the node repo').default('OpusPopuli'))\n .addOption(new Option('--repo-dir <path>', 'Explicit path to a checked-out node repo (overrides cwd + clone)'))\n .addOption(\n new Option(\n '--compose-file <path>',\n 'Repeatable. Compose file relative to repo root. Default: prod + backup (production), prod only (--local-only).',\n ),\n )\n .addOption(new Option('--env-file <path>', 'Compose --env-file. Default: .env.production'))\n .addOption(new Option('--skip-brew', \"Skip the Homebrew package install pass\").default(false))\n .addOption(\n new Option(\n '--skip-launch-agent',\n \"Skip the LaunchAgent setup (assumes one is already in place)\",\n ).default(false),\n )\n .addOption(new Option('--skip-ollama', \"Skip the Ollama model pull + warm\").default(false))\n .addOption(\n new Option(\n '--llm-model <model>',\n `Ollama LLM model to pull and warm. Default: ${DEFAULT_LLM_MODEL}. Examples: \\`llama3.3:70b\\`, \\`qwen2.5:72b\\`. Memory sizing table: docs/docker-resources.md in the opuspopuli-node template (or your region repo's checkout).`,\n ),\n )\n .addOption(\n new Option(\n '--embedding-model <model>',\n `Ollama embedding model. Default: ${DEFAULT_EMBEDDING_MODEL}. Only takes effect when the knowledge service runs with EMBEDDINGS_PROVIDER=ollama (otherwise embeddings are computed in-process via xenova).`,\n ),\n )\n .addOption(\n new Option(\n '--supabase-url <url>',\n 'Public-facing Supabase URL (what browsers + microservices use). Default: `http://localhost:8000` in --local-only mode, otherwise `https://supabase.<domain>` (which the operator can override).',\n ),\n )\n .addOption(\n new Option(\n '--node-type <type>',\n 'Deployment topology. `region` (default) = region node connecting to remote prompt-service. `region-with-prompts` = region node + colocated prompt-service overlay (team/dev use). `prompts-only` = future stub for the central prompts deployment.',\n ).choices(['region', 'region-with-prompts', 'prompts-only']),\n )\n .addOption(\n new Option(\n '--prompt-service-url <url>',\n \"Remote prompt-service URL. Only meaningful for --node-type=region (default: https://prompts.opuspopuli.org). Ignored for --node-type=region-with-prompts (the overlay pins it to http://opuspopuli-prompts:3210).\",\n ),\n )\n .addOption(new Option('--skip-stack', \"Stop before `docker compose pull && up`\").default(false))\n .addOption(\n new Option(\n '--local-only',\n \"Run for local dev / testing: no Tunnel token required, cloudflared stays down. Auto-generates the pgsodium key if not in Keychain (init unnecessary).\",\n ).default(false),\n )\n .addOption(new Option('-y, --yes', 'Skip confirmation prompts').default(false))\n .action(async (opts: BootstrapOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node bootstrap ')));\n\n const nodeType = await selectNodeType(opts);\n const region = await resolveRegion(opts);\n const owner = opts.owner ?? 'OpusPopuli';\n const repoName = `opuspopuli-node-${region}`;\n const composeFile = opts.composeFile ?? defaultComposeFiles(opts);\n\n // Model selection: flags override > interactive prompt > defaults. The\n // resolved values flow to both Ollama (pull + warm) and the LaunchAgent\n // (LLM_MODEL / EMBEDDINGS_MODEL). bootstrap is the source of truth for\n // what model runs. (N3)\n const llmModelChoice = opts.llmModel ?? (await selectLlmModel(opts));\n const [embeddingModel, llmModel] = resolveModels({\n llmModel: llmModelChoice,\n ...(opts.embeddingModel !== undefined ? { embeddingModel: opts.embeddingModel } : {}),\n });\n\n // ---- Phases 1–4: system checks, Homebrew, auth, locate repo ----\n await runSystemChecksPhase();\n await runBrewPhase(opts);\n await ensureGhAuth();\n await promptTailscaleSignin();\n const repoPath = await locateRegionRepoPhase(opts, owner, repoName);\n\n // ---- Phase 5: secrets (Keychain unlock, load/generate, URLs) ----\n await unlockKeychainPhase();\n\n const secrets = await collectSecretsPhase({ region, nodeType, opts });\n await runLaunchAgentPhase({ opts, secrets, llmModel, embeddingModel });\n await installWrapperPhase({ repoPath, region, promptServiceUrl: secrets.promptServiceUrl });\n await loginGhcrPhase();\n await runOllamaPhase({ opts, embeddingModel, llmModel });\n await runStackPhase({ opts, repoPath, region, composeFile, secrets, llmModel, embeddingModel });\n });\n\n// ----------------------------------------------------------------------------\n// Bootstrap phases\n// ----------------------------------------------------------------------------\n// The command action delegates to these phase helpers so no single function\n// exceeds the cognitive-complexity budget. Each is behavior-preserving — the\n// interactive prompts, spinners, and `process.exit` calls are relocated\n// verbatim, not changed. The orchestrator threads values through explicitly.\n\ninterface CollectedSecrets {\n pgsodiumKey: string;\n tunnelToken: string | undefined;\n postgresPassword: string;\n jwtSecret: string;\n supabaseAnonKey: string;\n supabaseServiceRoleKey: string;\n dashboardPassword: string;\n promptServiceUrl: string;\n supabaseUrl: string;\n}\n\n// Default compose file set by mode (review S4): production runs the\n// backup stack (restic / rclone) alongside the main stack; local-only\n// skips it (don't burn dev-machine disk on backups; don't try to push\n// to an R2 bucket that may not exist). Operator can still override\n// with explicit --compose-file flags.\nfunction defaultComposeFiles(opts: BootstrapOptions): string[] {\n return opts.localOnly\n ? ['docker-compose-prod.yml']\n : ['docker-compose-prod.yml', 'docker-compose-backup.yml'];\n}\n\n// Node type selects which stack to provision. Default is `region` — the\n// common case for any operator who isn't on the prompts team.\n// `region-with-prompts` covers the team/dev case where the operator runs\n// prompt-service alongside the region stack. `prompts-only` is a documented\n// stub for the future central prompts deployment — exits early to keep the\n// CLI surface stable now.\nasync function selectNodeType(opts: BootstrapOptions): Promise<NodeType> {\n const nodeType: NodeType = opts.nodeType\n ? opts.nodeType\n : (unwrap(\n await p.select({\n message: 'What kind of node are you provisioning?',\n options: [\n {\n value: 'region',\n label: 'Region node (civic data for one region, remote prompt-service)',\n },\n {\n value: 'region-with-prompts',\n label: 'Region + colocated prompt-service (team / dev)',\n },\n {\n value: 'prompts-only',\n label: 'Prompt-service node (central prompts deployment — future)',\n },\n ],\n initialValue: 'region',\n }),\n ) as NodeType);\n\n if (nodeType === 'prompts-only') {\n p.cancel(\n 'prompts-only node deployment is not yet implemented. ' +\n 'This flag exists so the CLI surface is stable for when the prompts team ' +\n 'deploys the central prompts.opuspopuli.org instance — but the deployment ' +\n 'stack (compose file, healthchecks, observability) is filled in later, ' +\n 'when there is an actual central prompt-service to deploy.',\n );\n process.exit(1);\n }\n return nodeType;\n}\n\n// Region label (required to find Keychain items + repo name).\nasync function resolveRegion(opts: BootstrapOptions): Promise<string> {\n return opts.region\n ? opts.region\n : unwrap(\n await p.text({\n message: 'Region label (the slug used during init — e.g. us-ca)?',\n placeholder: 'us-ca',\n validate: (v) =>\n /^[a-z0-9-]{2,32}$/.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens; 2–32 chars',\n }),\n );\n}\n\n// ---- Phase 1: macOS sanity ----\nasync function runSystemChecksPhase(): Promise<void> {\n const sysSpin = p.spinner();\n sysSpin.start('Inspecting macOS…');\n const snap = await inspectSystem();\n sysSpin.stop(pc.green('✓ macOS inspected.'));\n\n if (!snap.isAppleSilicon) {\n p.cancel(\n `Bootstrap requires an Apple Silicon Mac (the runbook targets M-series). Detected: ${snap.osVersion ?? 'unknown'} (uname -m != arm64).`,\n );\n process.exit(1);\n }\n\n p.note(\n [\n `Hostname: ${pc.cyan(snap.hostname)}`,\n `macOS: ${pc.cyan(snap.osVersion ?? '(sw_vers failed)')}`,\n `Auto-restart on power: ${kvBool(snap.autoRestartOnPowerFailure)}`,\n `Disk sleep disabled: ${kvBool(snap.diskSleepDisabled)}`,\n `FileVault: ${kvFileVault(snap.fileVaultEnabled)}`,\n ].join('\\n'),\n 'System snapshot',\n );\n\n if (!snap.autoRestartOnPowerFailure) {\n const fix = unwrap(\n await p.confirm({\n message: 'Auto-restart-on-power-failure is OFF. Enable now (requires sudo)?',\n initialValue: true,\n }),\n );\n if (fix) {\n const r = await enableAutoRestartOnPowerFailure();\n if (!r.ok) p.note(`${pc.red('✗')} ${r.reason}`, 'pmset failed');\n }\n }\n if (!snap.diskSleepDisabled) {\n const fix = unwrap(\n await p.confirm({\n message: 'Disk sleep is enabled. Disable now (requires sudo)?',\n initialValue: true,\n }),\n );\n if (fix) {\n const r = await disableDiskSleep();\n if (!r.ok) p.note(`${pc.red('✗')} ${r.reason}`, 'pmset failed');\n }\n }\n}\n\n// ---- Phase 2: Homebrew + tool installs ----\nasync function runBrewPhase(opts: BootstrapOptions): Promise<void> {\n if (opts.skipBrew) return;\n\n const brewInfo = await detectBrew();\n if (!brewInfo.installed) {\n p.note(\n [\n `Homebrew is not installed. Open another shell and run:`,\n '',\n pc.cyan(HOMEBREW_INSTALL_COMMAND),\n '',\n pc.dim('Then come back and press Enter.'),\n ].join('\\n'),\n 'Manual step',\n );\n unwrap(await p.confirm({ message: 'Homebrew installed?', initialValue: true }));\n }\n\n const brewSpin = p.spinner();\n brewSpin.start('Installing Studio packages… (~5–15 min first run)');\n const report = await installPackages(STUDIO_PACKAGES, (pkg, status) => {\n brewSpin.message(`${status}: ${pkg.name}`);\n });\n brewSpin.stop(\n report.failed.length === 0\n ? pc.green(\n `✓ ${report.installed.length} installed, ${report.alreadyPresent.length} already present`,\n )\n : pc.yellow(\n `⚠ ${report.installed.length} installed, ${report.alreadyPresent.length} present, ${report.failed.length} failed`,\n ),\n );\n if (report.failed.length > 0) {\n p.note(\n [\n report.failed.map((f) => `${pc.red('•')} ${f.pkg.name}: ${f.reason}`).join('\\n'),\n '',\n pc.dim('A partial install usually fails downstream (Docker / Ollama / compose).'),\n pc.dim('Install the failed packages manually and re-run with --skip-brew.'),\n ].join('\\n'),\n 'Brew failures',\n );\n const cont = unwrap(\n await p.confirm({\n message: 'Continue anyway? (Default no — recommended to fix and re-run.)',\n initialValue: false,\n }),\n );\n if (!cont) process.exit(1);\n }\n}\n\n// ---- Phase 4: Locate / clone the region repo (fail-fast — S6 review fix) ----\n// Moved up from Phase 8: a repo-not-found error after 5-10 minutes of\n// brew + Ollama work is operator-hostile. The clone only needs `gh`\n// (Phase 3), so we can validate the repo exists early and bail before\n// the slow stuff if it doesn't.\nasync function locateRegionRepoPhase(\n opts: BootstrapOptions,\n owner: string,\n repoName: string,\n): Promise<string> {\n const repoSpin = p.spinner();\n repoSpin.start('Locating your region node repo…');\n const located = await locateOrCloneRepo({\n owner,\n name: repoName,\n cwd: process.cwd(),\n ...(opts.repoDir ? { explicit: opts.repoDir } : {}),\n });\n const repoPath = repoPathFromLocate(located);\n if (!repoPath) {\n repoSpin.stop(pc.red('✗ Couldn\\'t locate or clone the region repo.'));\n handleLocateError(located, owner, repoName);\n process.exit(1);\n }\n repoSpin.stop(\n located.kind === 'cloned'\n ? pc.green(`✓ Cloned ${owner}/${repoName} to ${repoPath}`)\n : pc.green(`✓ Found region repo at ${repoPath}`),\n );\n return repoPath;\n}\n\n// ---- Phase 5: keychain availability + SSH unlock ----\n//\n// The Keychain item is local to the machine that wrote it (`init` on the\n// laptop). On a fresh Studio, both items will be missing on first run —\n// bootstrap prompts the operator to paste, validates the format, and writes\n// to the Studio's local Keychain for re-runs.\nasync function unlockKeychainPhase(): Promise<void> {\n const keychain = await detectKeychain();\n if (!keychain.available) {\n p.cancel(\n `${keychain.reason ?? 'Keychain unavailable'}. Bootstrap requires the macOS Keychain.`,\n );\n process.exit(1);\n }\n\n // SSH sessions don't auto-unlock the login keychain at session start.\n // When the operator is over SSH AND the keychain is currently locked,\n // every `security add-generic-password` call will fail with exit 36\n // (errSecInteractionNotAllowed). Prompt for the login password once\n // up front, unlock, then proceed — much better UX than 9 identical\n // failures (one per secret) before the operator figures it out.\n if (isSshSession() && (await isKeychainLocked())) {\n p.note(\n [\n 'SSH session detected with a locked login keychain.',\n 'macOS keychain operations require an unlocked keychain — your',\n 'login password will be used once to unlock it for this session.',\n 'The keychain remains unlocked until the session ends or it',\n 'idle-locks. To skip and unlock manually, press Ctrl+C and run',\n '`security unlock-keychain` yourself.',\n ].join('\\n'),\n 'Keychain unlock required',\n );\n const pw = unwrap(\n await p.password({\n message: 'macOS login password (for `security unlock-keychain`):',\n validate: (v) => (v && v.length > 0 ? undefined : 'password required'),\n }),\n );\n const unlock = await unlockKeychain(pw);\n if (!unlock.ok) {\n p.cancel(unlock.reason ?? 'security unlock-keychain failed.');\n process.exit(1);\n }\n p.note(`${pc.green('✓')} Keychain unlocked for this session.`, 'Keychain');\n }\n}\n\n// ---- Phase 5a: pgsodium key, tunnel token, and Supabase self-hosted creds ----\n//\n// In --local-only mode there's no Tunnel token at all (cloudflared stays\n// down via compose profile gating). The pgsodium key is still required\n// since the data services use it; if missing, we generate a fresh one\n// inline rather than requiring an `init` call first.\n//\n// The five Supabase values (postgres password, JWT secret, anon +\n// service_role JWTs, dashboard password) are auto-generated on first run\n// via the same `loadSecret` path used for the pgsodium key. The two JWTs\n// are derived from JWT_SECRET and re-validated against it so a stale token\n// cached from a prior bootstrap can't silently break auth.\nasync function collectCoreSecrets(args: {\n region: string;\n opts: BootstrapOptions;\n}): Promise<Omit<CollectedSecrets, 'promptServiceUrl' | 'supabaseUrl'>> {\n const { region, opts } = args;\n const pgsodiumKey = await loadSecret({\n region,\n account: 'pgsodium-root-key',\n label: 'pgsodium master key',\n validate: (v) =>\n PGSODIUM_KEY_RE.test(v) ? undefined : 'must be exactly 64 lowercase hex characters',\n ...(opts.localOnly ? { generate: generatePgsodiumRootKey } : {}),\n });\n\n const tunnelToken = opts.localOnly\n ? undefined\n : await loadSecret({\n region,\n account: 'tunnel-token',\n label: 'Cloudflare Tunnel token',\n placeholder: 'JWT-style base64url string from `terraform output tunnel_token`',\n validate: (v) =>\n TUNNEL_TOKEN_RE.test(v) ? undefined : 'tunnel token must be a base64-url JWT',\n });\n\n const postgresPassword = await loadSecret({\n region,\n account: 'postgres-password',\n label: 'Postgres password',\n // URL-safe alphabet required — value lands in postgres:// URIs where\n // `+`/`/`/`=` cause parser ambiguity in gotrue/postgrest/storage.\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generatePostgresPassword,\n });\n\n const jwtSecret = await loadSecret({\n region,\n account: 'jwt-secret',\n label: 'JWT signing secret',\n validate: (v) =>\n SAFE_LAUNCHCTL_VALUE_RE.test(v) && v.length >= 32\n ? undefined\n : 'must be ≥32 base64 characters',\n generate: generateJwtSecret,\n });\n\n // Derived JWTs MUST match the current jwtSecret's signature — otherwise\n // a stale anon/service_role token (cached from a previous bootstrap with\n // a different JWT_SECRET) sails past the shape check and breaks every\n // auth call silently. verifySupabaseJwt re-runs the HMAC and rejects on\n // mismatch, triggering regeneration with the current secret.\n const supabaseAnonKey = await loadSecret({\n region,\n account: 'supabase-anon-key',\n label: 'Supabase anon key',\n validate: (v) =>\n SAFE_LAUNCHCTL_VALUE_RE.test(v) && verifySupabaseJwt(v, jwtSecret)\n ? undefined\n : 'must be a base64url JWT signed by the current JWT_SECRET',\n generate: () => signSupabaseJwt({ role: 'anon', secret: jwtSecret }),\n });\n\n const supabaseServiceRoleKey = await loadSecret({\n region,\n account: 'supabase-service-role-key',\n label: 'Supabase service role key',\n validate: (v) =>\n SAFE_LAUNCHCTL_VALUE_RE.test(v) && verifySupabaseJwt(v, jwtSecret)\n ? undefined\n : 'must be a base64url JWT signed by the current JWT_SECRET',\n generate: () => signSupabaseJwt({ role: 'service_role', secret: jwtSecret }),\n });\n\n const dashboardPassword = await loadSecret({\n region,\n account: 'dashboard-password',\n label: 'Supabase Studio dashboard password',\n // URL-safe alphabet required — value lands in basic-auth headers via\n // kong's declarative config. Avoid `+`/`/`/`=` for the same reasons.\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generateDashboardPassword,\n });\n\n return {\n pgsodiumKey,\n tunnelToken,\n postgresPassword,\n jwtSecret,\n supabaseAnonKey,\n supabaseServiceRoleKey,\n dashboardPassword,\n };\n}\n\n// ---- Phase 5b: prompt-service credentials + URL ----\n//\n// Branches on nodeType:\n// `region-with-prompts` — operator owns both ends. Generate all three\n// secrets (DB password + HMAC + admin HMAC); the colocated overlay\n// consumes them via env.\n// `region` — operator's prompt-service is REMOTE. They received an HMAC\n// key from the prompts team; bootstrap prompts them to paste it. The DB\n// password + admin key are skipped (no local DB, no admin access).\nasync function collectPromptServiceSecrets(args: {\n region: string;\n nodeType: NodeType;\n opts: BootstrapOptions;\n}): Promise<string> {\n const { region, nodeType, opts } = args;\n if (nodeType === 'region-with-prompts') {\n await loadSecret({\n region,\n account: 'prompts-db-password',\n label: 'prompt-service Postgres password',\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generatePostgresPassword,\n });\n\n await loadSecret({\n region,\n account: 'prompt-service-api-key',\n label: 'prompt-service HMAC API key',\n // Same URL-safe alphabet as other HMAC keys; embedded in the\n // `<region>:<key>` API_KEYS list and in Authorization headers.\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generateHmacApiKey,\n });\n\n await loadSecret({\n region,\n account: 'prompt-service-admin-api-key',\n label: 'prompt-service admin API key',\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n generate: generateHmacApiKey,\n });\n } else {\n // nodeType === 'region': paste-only path. No `generate`, so loadSecret\n // falls through to the operator-paste prompt.\n await loadSecret({\n region,\n account: 'prompt-service-api-key',\n label: 'prompt-service HMAC API key (issued by the prompts team)',\n placeholder: 'paste the region-specific HMAC key',\n validate: (v) =>\n URL_SAFE_PASSWORD_RE.test(v) ? undefined : 'must be base64url chars only (no + / =)',\n });\n }\n\n // Remote prompt-service URL — only resolved when NOT colocating.\n // For region-with-prompts the overlay hardcodes http://opuspopuli-prompts:3210\n // on the relevant services; no shell env needed.\n const promptServiceUrl =\n nodeType === 'region-with-prompts'\n ? // eslint-disable-next-line sonarjs/no-clear-text-protocols -- in-network (docker) prompt-service URL is legitimately plaintext http; no TLS on the internal bridge\n 'http://opuspopuli-prompts:3210'\n : (opts.promptServiceUrl ?? 'https://prompts.opuspopuli.org');\n if (!SAFE_URL_RE.test(promptServiceUrl)) {\n p.cancel(\n `--prompt-service-url ${JSON.stringify(promptServiceUrl)} contains characters outside the allowed URL set`,\n );\n process.exit(1);\n }\n return promptServiceUrl;\n}\n\n// SUPABASE_URL gets baked into gotrue's API_EXTERNAL_URL and into every\n// magic-link callback gotrue emails to users. localhost is only correct\n// in --local-only mode; for a Tunnel-exposed production node, emailing\n// links pointing at http://localhost:8000 silently breaks signups.\n//\n// Resolution order:\n// --local-only mode → default http://localhost:8000 (no prompt)\n// non-local-only → require --supabase-url OR prompt for the\n// public-facing URL.\nasync function resolveSupabaseUrl(opts: BootstrapOptions): Promise<string> {\n let supabaseUrl: string;\n if (opts.supabaseUrl) {\n supabaseUrl = opts.supabaseUrl;\n } else if (opts.localOnly) {\n supabaseUrl = 'http://localhost:8000';\n } else {\n supabaseUrl = unwrap(\n await p.text({\n message: 'Public-facing Supabase URL (what browsers + microservices use to reach kong)?',\n placeholder: 'https://supabase.civicfeed.tx',\n validate: (v) => {\n if (!v) return 'required';\n return SAFE_URL_RE.test(v)\n ? undefined\n : 'contains characters outside the allowed URL set';\n },\n }),\n );\n }\n if (!SAFE_URL_RE.test(supabaseUrl)) {\n p.cancel(\n `--supabase-url ${JSON.stringify(supabaseUrl)} contains characters outside the allowed URL set`,\n );\n process.exit(1);\n }\n return supabaseUrl;\n}\n\n// Phase 5 aggregate: run all secret-collection sub-phases in order.\nasync function collectSecretsPhase(args: {\n region: string;\n nodeType: NodeType;\n opts: BootstrapOptions;\n}): Promise<CollectedSecrets> {\n const core = await collectCoreSecrets({ region: args.region, opts: args.opts });\n const promptServiceUrl = await collectPromptServiceSecrets(args);\n const supabaseUrl = await resolveSupabaseUrl(args.opts);\n return { ...core, promptServiceUrl, supabaseUrl };\n}\n\n// ---- Phase 6: LaunchAgent ----\nasync function runLaunchAgentPhase(args: {\n opts: BootstrapOptions;\n secrets: CollectedSecrets;\n llmModel: string;\n embeddingModel: string;\n}): Promise<void> {\n const { opts, secrets, llmModel, embeddingModel } = args;\n if (opts.skipLaunchAgent) return;\n\n const laSpin = p.spinner();\n laSpin.start('Writing pgsodium key file + LaunchAgent plist…');\n const la = await setupLaunchAgent({\n pgsodiumKey: secrets.pgsodiumKey,\n ...(secrets.tunnelToken !== undefined ? { tunnelToken: secrets.tunnelToken } : {}),\n llmModel,\n embeddingModel,\n postgresPassword: secrets.postgresPassword,\n jwtSecret: secrets.jwtSecret,\n supabaseAnonKey: secrets.supabaseAnonKey,\n supabaseServiceRoleKey: secrets.supabaseServiceRoleKey,\n dashboardPassword: secrets.dashboardPassword,\n supabaseUrl: secrets.supabaseUrl,\n });\n if (!la.ok) {\n laSpin.stop(pc.red(`✗ LaunchAgent step ${la.step} failed.`));\n p.cancel(la.reason ?? 'LaunchAgent setup failed.');\n process.exit(1);\n }\n laSpin.stop(\n pc.green(\n `✓ LaunchAgent loaded (${la.paths.plistFile})${opts.localOnly ? ' — local-only mode, no TUNNEL_TOKEN set' : ''}.`,\n ),\n );\n}\n\n// ---- Phase 6b: install op-compose wrapper ----\n//\n// launchctl setenv doesn't reach pre-existing shells or sshd children, so\n// operator-driven `docker compose` invocations would hard-fail on the\n// `${VAR:?…}` enforcement in the template even though the values sit safely\n// in Keychain. The wrapper reads Keychain on every invocation and exports\n// the values only into the docker compose subprocess's env.\nasync function installWrapperPhase(args: {\n repoPath: string;\n region: string;\n promptServiceUrl: string;\n}): Promise<void> {\n const { repoPath, region, promptServiceUrl } = args;\n const wrapperSpin = p.spinner();\n wrapperSpin.start('Installing bin/op-compose wrapper…');\n const wrapper = await installOpComposeWrapper({ repoDir: repoPath, region, promptServiceUrl });\n if (!wrapper.ok) {\n wrapperSpin.stop(pc.red('✗ op-compose wrapper install failed.'));\n p.cancel(wrapper.reason ?? 'op-compose wrapper install failed.');\n process.exit(1);\n }\n wrapperSpin.stop(pc.green(`✓ Installed ${wrapper.path} (mode 0755).`));\n}\n\n// ---- Phase 7: ghcr.io login ----\nasync function loginGhcrPhase(): Promise<void> {\n const ghcrSpin = p.spinner();\n ghcrSpin.start('Authenticating Docker to ghcr.io…');\n const ghcr = await loginToGhcr();\n if (!ghcr.ok) {\n ghcrSpin.stop(pc.red('✗ ghcr.io login failed.'));\n p.cancel(ghcr.reason ?? 'ghcr.io login failed.');\n process.exit(1);\n }\n ghcrSpin.stop(pc.green('✓ Logged in to ghcr.io.'));\n}\n\n// ---- Phase 8: Ollama ----\nasync function runOllamaPhase(args: {\n opts: BootstrapOptions;\n embeddingModel: string;\n llmModel: string;\n}): Promise<void> {\n const { opts, embeddingModel, llmModel } = args;\n if (opts.skipOllama) return;\n\n const olSpin = p.spinner();\n olSpin.start(`Pulling + warming Ollama models… (${estimatedPullTime(llmModel)})`);\n let olHealth = await checkOllamaHealth();\n if (!olHealth.reachable) {\n // S5 review fix: try to start the service before bailing. The\n // operator's pretty much always going to want this anyway, and\n // `brew services start` is no-op-safe.\n olSpin.message('Ollama not reachable — running `brew services start ollama`…');\n const start = await startOllamaService();\n if (!start.ok) {\n olSpin.stop(pc.red('✗ Couldn\\'t start Ollama service.'));\n p.cancel(\n `${start.reason ?? 'unknown'} — start it manually with \\`brew services start ollama\\` and re-run with --skip-brew --skip-launch-agent.`,\n );\n process.exit(1);\n }\n // Brew services start returns immediately; the daemon needs a few\n // seconds before /api/tags responds. Quick wait + re-probe.\n await new Promise((res) => setTimeout(res, 3000));\n olHealth = await checkOllamaHealth();\n if (!olHealth.reachable) {\n olSpin.stop(\n pc.yellow('⚠ Ollama service started but daemon not yet answering on :11434.'),\n );\n p.cancel(\n 'Give it another few seconds, then re-run with --skip-brew --skip-launch-agent.',\n );\n process.exit(1);\n }\n }\n const modelReport = await setupModels([embeddingModel, llmModel], (model, status) => {\n olSpin.message(`${status}: ${model}`);\n });\n olSpin.stop(\n modelReport.failed.length === 0\n ? pc.green(\n `✓ ${modelReport.pulled.length} pulled, ${modelReport.alreadyPresent.length} present, ${modelReport.warmed.length} warmed`,\n )\n : pc.yellow(`⚠ ${modelReport.failed.length} model pull(s) failed`),\n );\n const probe = await probeHostDockerInternal();\n if (!probe.ok) {\n p.note(`${pc.yellow('⚠')} ${probe.reason}`, 'Docker host networking');\n }\n}\n\n// Hydrate every `${VAR:?…}`-enforced env var on the compose subprocess.\n// launchctl setenv doesn't reach pre-existing shells or sshd children, so\n// bootstrap's own compose calls would otherwise hard-fail even though every\n// value sits in process scope from the loadSecret pass. Pure builder — kept\n// separate so the env-hydration rule stays unit-testable.\nexport function buildComposeEnv(args: {\n secrets: CollectedSecrets;\n llmModel: string;\n embeddingModel: string;\n}): NodeJS.ProcessEnv {\n const { secrets, llmModel, embeddingModel } = args;\n return {\n PGSODIUM_ROOT_KEY: secrets.pgsodiumKey,\n POSTGRES_PASSWORD: secrets.postgresPassword,\n JWT_SECRET: secrets.jwtSecret,\n SUPABASE_ANON_KEY: secrets.supabaseAnonKey,\n SUPABASE_SERVICE_ROLE_KEY: secrets.supabaseServiceRoleKey,\n DASHBOARD_PASSWORD: secrets.dashboardPassword,\n SUPABASE_URL: secrets.supabaseUrl,\n AUTH_JWT_SECRET: process.env['AUTH_JWT_SECRET'] ?? secrets.jwtSecret,\n ...(secrets.tunnelToken !== undefined ? { TUNNEL_TOKEN: secrets.tunnelToken } : {}),\n ...(llmModel ? { LLM_MODEL: llmModel } : {}),\n ...(embeddingModel ? { EMBEDDINGS_MODEL: embeddingModel } : {}),\n };\n}\n\n// ---- Phase 9 + 10: docker compose pull + up, then health-check loop ----\nasync function runStackPhase(args: {\n opts: BootstrapOptions;\n repoPath: string;\n region: string;\n composeFile: string[];\n secrets: CollectedSecrets;\n llmModel: string;\n embeddingModel: string;\n}): Promise<void> {\n const { opts, repoPath, region, composeFile, secrets, llmModel, embeddingModel } = args;\n\n if (opts.skipStack) {\n const profileFlag = opts.localOnly ? '' : '--profile public ';\n p.outro(\n pc.cyan(\n `Stack-up skipped. Run \\`./bin/op-compose -f ${composeFile.join(' -f ')} ${profileFlag}pull && ./bin/op-compose -f ${composeFile.join(' -f ')} ${profileFlag}up -d\\` from ${repoPath} when ready. (op-compose hydrates Keychain secrets per-invocation; use it instead of raw \\`docker compose\\`.)`,\n ),\n );\n return;\n }\n\n const composeFiles = resolveComposeFiles(repoPath, composeFile);\n const composeEnv = buildComposeEnv({ secrets, llmModel, embeddingModel });\n // In production mode, activate the `public` compose profile so cloudflared\n // starts. In --local-only mode pass no profiles — the template gates\n // cloudflared behind `public`, so an empty profiles array keeps it down.\n const composeOpts = {\n files: composeFiles,\n cwd: repoPath,\n ...(opts.envFile ? { envFile: opts.envFile } : {}),\n profiles: opts.localOnly ? LOCAL_PROFILES : PUBLIC_PROFILES,\n env: composeEnv,\n };\n\n // In --local-only mode, evict any cloudflared container left over from a\n // prior public bootstrap on this Studio. Without this, `compose ps` would\n // still list cloudflared and the health-check loop would demand it reach\n // healthy with no TUNNEL_TOKEN — hanging until timeout. (review S3)\n if (opts.localOnly) {\n const evict = p.spinner();\n evict.start('Evicting any cloudflared from a prior public bootstrap…');\n const rm = await composeRemoveService(\n { ...composeOpts, profiles: PUBLIC_PROFILES },\n 'cloudflared',\n );\n evict.stop(\n rm.ok\n ? pc.green('✓ cloudflared not present (or removed).')\n : pc.yellow(`⚠ cloudflared eviction reported: ${rm.reason ?? 'unknown'} — continuing.`),\n );\n }\n\n const pullSpin = p.spinner();\n pullSpin.start('Pulling images from ghcr.io… (~5–15 min first run, < 1 min cached)');\n const pull = await composePull(composeOpts);\n if (!pull.ok) {\n pullSpin.stop(pc.red('✗ compose pull failed.'));\n p.cancel(pull.reason ?? 'compose pull failed.');\n process.exit(1);\n }\n pullSpin.stop(pc.green('✓ Images pulled.'));\n\n const upSpin = p.spinner();\n upSpin.start('Starting the stack…');\n const up = await composeUp(composeOpts);\n if (!up.ok) {\n upSpin.stop(pc.red('✗ compose up failed.'));\n p.cancel(up.reason ?? 'compose up failed.');\n process.exit(1);\n }\n upSpin.stop(pc.green('✓ Containers started — waiting for healthy…'));\n\n // ---- Phase 10: health-check loop ----\n const healthSpin = p.spinner();\n healthSpin.start('Polling for healthy containers… (every 5s, up to 5 min)');\n const outcome = await waitForHealthy(composeOpts, {\n onPoll: (snaps) => {\n const healthy = snaps.filter((s) => s.health === 'healthy').length;\n const running = snaps.filter((s) => s.state === 'running').length;\n healthSpin.message(`${healthy}/${running} healthy`);\n },\n });\n healthSpin.stop(healthOutcomeHeadline(outcome));\n finishHealthOutcome(outcome, { region, opts, composeFiles });\n}\n\n// Spinner headline for the terminal state of the health loop.\nfunction healthOutcomeHeadline(\n outcome: Awaited<ReturnType<typeof waitForHealthy>>,\n): string {\n switch (outcome.kind) {\n case 'healthy':\n return pc.green(`✓ All ${outcome.snapshots.length} containers healthy.`);\n case 'unhealthy':\n return pc.red(`✗ ${outcome.problem}`);\n case 'timeout':\n return pc.yellow('⚠ Timed out waiting for all containers to report healthy.');\n default:\n return assertNever(outcome) as never;\n }\n}\n\n// Print the outro / diagnostics and exit for the terminal health state.\nfunction finishHealthOutcome(\n outcome: Awaited<ReturnType<typeof waitForHealthy>>,\n args: { region: string; opts: BootstrapOptions; composeFiles: string[] },\n): void {\n const { region, opts, composeFiles } = args;\n switch (outcome.kind) {\n case 'healthy':\n if (opts.localOnly) {\n p.outro(\n pc.cyan(\n [\n `Region ${region} is up locally (no public Cloudflare Tunnel — cloudflared stays down).`,\n `Access from your laptop over Tailscale at this Studio's tailnet IP.`,\n `When you're ready to expose publicly, re-run \\`bootstrap\\` without --local-only.`,\n ].join('\\n'),\n ),\n );\n } else {\n p.outro(\n pc.cyan(\n `Region ${region} is up. Next: verify off-LAN with \\`npx create-op-node verify --domain <your-domain>\\`.`,\n ),\n );\n }\n return;\n case 'unhealthy':\n // Surface the full snapshot table for diagnosis — N10 review fix.\n p.note(\n outcome.snapshots\n .map((s) => ` ${kvHealth(s.health)} ${s.name} (${s.state})`)\n .join('\\n'),\n 'Container state',\n );\n p.cancel(\n `Inspect with \\`docker compose -f ${composeFiles.join(' -f ')} logs\\`. Fix and re-run.`,\n );\n process.exit(1);\n // eslint-disable-next-line no-fallthrough\n case 'timeout':\n p.note(\n outcome.snapshots\n .map((s) => ` ${kvHealth(s.health)} ${s.name} (${s.state})`)\n .join('\\n'),\n 'Container state at timeout',\n );\n // B1 review fix: don't print the success outro. The stack hasn't\n // settled and `verify` would mislead — instruct the operator to\n // re-poll and exit non-zero.\n p.cancel(\n `Re-run \\`create-op-node bootstrap --skip-brew --skip-launch-agent --skip-ollama\\` to skip the already-done phases and poll again once containers settle.`,\n );\n process.exit(1);\n // eslint-disable-next-line no-fallthrough\n default:\n // Exhaustiveness check — adding a new HealthOutcome variant without\n // updating this switch fails the type check.\n assertNever(outcome);\n return;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n/**\n * Resolve the compose-file paths the wizard will pass to docker. Absolute\n * paths pass through; relative paths are resolved against `repoPath`. Pure\n * helper for unit testing — keeps the path-resolution rule in one place.\n */\nexport function resolveComposeFiles(\n repoPath: string,\n composeFile: string[] | undefined,\n): string[] {\n const inputs = composeFile ?? ['docker-compose-prod.yml'];\n return inputs.map((f) => (f.startsWith('/') ? f : join(repoPath, f)));\n}\n\n/**\n * Resolve the Ollama model identifiers from operator flags + defaults.\n * Pure helper — mirrors `resolveComposeFiles` so the flag-resolution rule\n * lives in one place and stays unit-testable.\n *\n * Returned in the order Ollama pulls + warms them: `[embedding, llm]`.\n * The embedding model is typically tiny (~500 MB), so emitting it first\n * gives the operator a visible \"✓ pulled\" milestone before the LLM's\n * potentially-tens-of-gigabytes download dominates the spinner. (S3)\n */\nexport function resolveModels(opts: {\n llmModel?: string;\n embeddingModel?: string;\n}): readonly [embedding: string, llm: string] {\n return [\n opts.embeddingModel ?? DEFAULT_EMBEDDING_MODEL,\n opts.llmModel ?? DEFAULT_LLM_MODEL,\n ] as const;\n}\n\n/** Curated LLM choices shown in the interactive picker. Qwen-only because\n * the Opus Populi platform serves Spanish-speaking civic users and Qwen\n * has the strongest Spanish (and broader multilingual) capability of the\n * open-weight models in this tier. Other Ollama models are still\n * reachable via the \"Other…\" sentinel. Sized per\n * docs/docker-resources.md in the opuspopuli-node template.\n * Order = display order. */\nexport const LLM_MODEL_CHOICES = [\n {\n value: 'qwen2.5:72b',\n label: 'qwen2.5:72b',\n hint: '72B, ~50 GB Ollama RAM. Pre-selected on 96 GB+ Studios. Best Spanish + multilingual quality. Pull ~40 GB, 30–60 min.',\n },\n {\n value: 'qwen2.5:32b',\n label: 'qwen2.5:32b',\n hint: '32B, ~22 GB Ollama RAM. Pre-selected on 48–95 GB Studios. Solid Spanish, faster than 72B. Pull ~20 GB, 15–30 min.',\n },\n {\n value: 'qwen3.5:9b',\n label: 'qwen3.5:9b',\n hint: '9B, ~8 GB Ollama RAM. Pre-selected on smaller Studios (< 48 GB); also the -y / scripted default. Pull ~5 GB, 3–5 min.',\n },\n] as const;\n\nconst OTHER_SENTINEL = '__OTHER__';\n\n/**\n * Pick the LLM that fits the operator's unified-memory budget. Ollama uses\n * roughly the model's parameter count in GB (in q4 quantization), plus a\n * context-window buffer. The Studio also needs RAM for macOS + Docker +\n * the data services. Thresholds below leave 30–40 GB headroom for that.\n *\n * Returns null when `ramGB` is null (sysctl unavailable) so the caller\n * falls back to the platform-default recommendation. (Pure helper —\n * exported for unit tests.)\n */\nexport function recommendLlmModel(ramGB: number | null): string | null {\n if (ramGB === null) return null;\n if (ramGB >= 96) return 'qwen2.5:72b';\n if (ramGB >= 48) return 'qwen2.5:32b';\n return 'qwen3.5:9b';\n}\n\n/**\n * Prompt the operator to pick an LLM model. Skipped when `--yes` is set\n * (returns the conservative default) or when `--llm-model` was passed\n * (caller short-circuits before this is reached).\n *\n * Pre-selects based on the Studio's detected unified memory — 128 GB\n * studios get qwen2.5:72b, 64 GB get qwen2.5:32b, smaller fall back to\n * qwen3.5:9b. When detection fails (non-macOS, sysctl missing), defaults\n * to qwen2.5:72b (the documented platform target).\n *\n * \"Other...\" branches to a text input validated against the same\n * MODEL_NAME_RE the LaunchAgent uses for setenv injection safety.\n */\nasync function selectLlmModel(opts: { yes?: boolean }): Promise<string> {\n if (opts.yes) return DEFAULT_LLM_MODEL;\n\n const ramGB = await detectUnifiedMemoryGB();\n const recommended = recommendLlmModel(ramGB) ?? 'qwen2.5:72b';\n const ramNote = ramGB !== null\n ? `Detected ${ramGB} GB unified memory — pre-selecting ${recommended}.`\n : `Couldn't detect Studio memory — defaulting to ${recommended} (override if your config differs).`;\n\n p.note(ramNote, 'Hardware');\n\n const choice = unwrap(\n await p.select({\n message: 'Choose the LLM model to pull + run',\n initialValue: recommended,\n options: [\n ...LLM_MODEL_CHOICES.map((c) => ({ value: c.value, label: c.label, hint: c.hint })),\n {\n value: OTHER_SENTINEL,\n label: 'Other…',\n hint: 'Specify any Ollama model name (e.g. mistral-small:24b)',\n },\n ],\n }),\n );\n\n if (choice !== OTHER_SENTINEL) return choice;\n\n return unwrap(\n await p.text({\n message: 'Ollama model name',\n placeholder: 'e.g. mistral-small:24b',\n validate: (v) =>\n /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/.test(v ?? '')\n ? undefined\n : 'Letters, digits, `.`, `:`, `_`, `-`, `/` only; must start with alphanumeric',\n }),\n );\n}\n\n/** Rough wall-clock estimate for pulling an Ollama model, based on the\n * size suffix in the tag. Used to populate the Ollama-pull spinner so\n * the operator knows whether to wait or step away. Estimates assume a\n * ~100 Mbps connection; faster networks finish proportionally sooner.\n *\n * Sparse-MoE shapes (`8x22b`) are matched before the plain `Nb` parse\n * because their size suffix in the tag refers to per-expert size, not\n * the total model footprint. */\nexport function estimatedPullTime(model: string): string {\n // Bounded digit runs (real Ollama tags never exceed 3-digit expert counts\n // / 4-digit sizes) so the search can't backtrack super-linearly on a long\n // input.\n if (/\\d{1,3}x\\d{1,3}b/i.test(model)) return '~60+ min for frontier MoE';\n const match = /(\\d{1,4})b\\b/i.exec(model);\n if (!match) return 'time depends on model size';\n const size = Number.parseInt(match[1]!, 10);\n if (size <= 13) return '~3–5 min for ≤ 13B-class';\n if (size <= 35) return '~15–30 min for ~32B-class';\n if (size <= 80) return '~30–60 min for 70B-class';\n return '~60+ min for frontier-class';\n}\n\nfunction kvBool(b: boolean): string {\n return b ? pc.green('on') : pc.yellow('off');\n}\n\nfunction kvFileVault(v: boolean | 'unknown'): string {\n if (v === 'unknown') return pc.dim('unknown');\n return v ? pc.green('on') : pc.dim('off');\n}\n\nfunction kvHealth(h: 'healthy' | 'unhealthy' | 'starting' | 'none'): string {\n switch (h) {\n case 'healthy':\n return pc.green('✓');\n case 'unhealthy':\n return pc.red('✗');\n case 'starting':\n return pc.yellow('…');\n case 'none':\n return pc.dim('-');\n }\n}\n\nfunction repoPathFromLocate(out: LocateOutcome): string | null {\n if (out.kind === 'found' || out.kind === 'cloned') return out.path;\n return null;\n}\n\nfunction handleLocateError(out: LocateOutcome, owner: string, name: string): void {\n switch (out.kind) {\n case 'explicit-not-a-node-repo':\n p.cancel(\n `${out.path} doesn't look like a node repo (missing one of docker-compose-prod.yml / supabase/init/pgsodium_getkey_env.sh). Point --repo-dir at the right place.`,\n );\n return;\n case 'gh-not-installed':\n p.cancel('`gh` not installed — install via `brew install gh` and re-run.');\n return;\n case 'clone-failed':\n p.cancel(\n `Couldn't clone ${owner}/${name}: ${out.reason}. Check repo exists + you have access.`,\n );\n return;\n case 'clone-disallowed':\n p.cancel(\n 'No checked-out node repo found and --no-clone (or similar) was set. Provide --repo-dir.',\n );\n return;\n case 'found':\n case 'cloned':\n // Success cases — handleLocateError shouldn't be called for them, but\n // listing here makes the switch exhaustive so the `never` check below\n // catches any new variant added to LocateOutcome.\n return;\n default: {\n // Compile-time exhaustiveness — if LocateOutcome gains a new variant\n // and isn't handled above, TypeScript fails this assignment.\n assertNever(out);\n return;\n }\n }\n}\n\n/**\n * Verify `gh` is signed in. If not, surface the one-line command to fix and\n * wait for the operator. Doesn't auto-run `gh auth login` since it opens a\n * browser flow and we don't want to fight it. Surfaces `gh auth status`'s\n * stderr so a wrong-account / missing-scope situation isn't silent.\n */\nasync function ensureGhAuth(): Promise<void> {\n const status = await safeExeca('gh', ['auth', 'status']);\n if (status === null) {\n p.cancel('`gh` not on PATH. Install via `brew install gh` and re-run.');\n process.exit(1);\n }\n if (status.exitCode === 0) return;\n\n const detail = (status.stderr || status.stdout).trim();\n p.note(\n [\n '`gh` is not signed in (or signed in to a different account / missing scope).',\n detail ? '' : undefined,\n detail ? pc.dim(detail) : undefined,\n '',\n 'In another shell:',\n '',\n pc.cyan('gh auth login --web'),\n '',\n pc.dim('Then come back and press Enter.'),\n ]\n .filter((l): l is string => typeof l === 'string')\n .join('\\n'),\n 'Manual step',\n );\n unwrap(await p.confirm({ message: 'gh signed in?', initialValue: true }));\n}\n\n/**\n * Tailscale needs an interactive browser signin. We surface the command +\n * wait for confirmation rather than spawning it ourselves — operators run\n * different node setups (start at login vs. on-demand) and we don't want\n * to second-guess. Tailscale is optional; the rest of the bootstrap\n * continues without it (out-of-band SSH is just less convenient).\n */\nasync function promptTailscaleSignin(): Promise<void> {\n const status = await safeExeca('tailscale', ['status']);\n if (status !== null && status.exitCode === 0) return;\n\n p.note(\n [\n 'Tailscale needs to be signed in (or you can skip — Tailscale is',\n 'optional; it provides out-of-band SSH from your laptop. The rest',\n 'of the bootstrap continues without it).',\n '',\n 'In another shell:',\n '',\n pc.cyan('tailscale up'),\n '',\n pc.dim('Accept the device on your tailnet, then come back and press Enter.'),\n ].join('\\n'),\n 'Manual step',\n );\n unwrap(await p.confirm({ message: 'Tailscale signed in (or skipped)?', initialValue: true }));\n}\n\ninterface LoadSecretInput {\n region: string;\n account: SecretAccount;\n /** Friendly name for prompts and notes. */\n label: string;\n /** Placeholder hint shown in the paste prompt. Ignored when `generate` is set. */\n placeholder?: string;\n /** Format check applied to both Keychain reads (so a stale-bad value is\n * treated as missing) and operator paste input. */\n validate: (v: string) => string | undefined;\n /** When set, on Keychain miss / validate-fail, generate a fresh value\n * instead of prompting. Used by `--local-only` for the pgsodium key —\n * no `init` needed.\n *\n * CRITICAL: when `generate` is set we MUST be able to persist the\n * generated value to Keychain. Otherwise the next bootstrap re-run\n * generates a different fresh key and silently destroys any data\n * encrypted under the previous key. So save failure in the generate\n * path is a hard exit, not a warning. (review B1) */\n generate?: () => string;\n}\n\n/**\n * Materialize a secret. Three paths, in order:\n *\n * 1. Keychain hit + valid → return it.\n * 2. Else if `generate` is set → generate fresh, MUST persist (hard fail\n * if save fails), return. The Keychain item is the durable record;\n * losing it later means losing whatever it encrypted.\n * 3. Else → prompt operator to paste, validate, persist with a warning\n * on save failure (the operator can paste again next time).\n *\n * If `validate` rejects an existing Keychain item, we surface the swap\n * explicitly before regenerating/reprompting — destructive overwrites\n * shouldn't be invisible. (review S1)\n */\nasync function loadSecret(input: LoadSecretInput): Promise<string> {\n const coords = { region: input.region, account: input.account };\n const spin = p.spinner();\n spin.start(`Reading ${input.label} from Keychain…`);\n const existing = await readSecret(coords);\n if (existing && input.validate(existing) === undefined) {\n spin.stop(pc.green(`✓ ${input.label} read from Keychain.`));\n return existing;\n }\n\n // Differentiate \"missing\" from \"present-but-bad-format\" — the latter is a\n // destructive replacement so we say so out loud.\n spin.stop(\n existing\n ? pc.yellow(`⚠ ${input.label} in Keychain failed format validation — will replace.`)\n : pc.dim(`· ${input.label} not in Keychain.`),\n );\n\n if (input.generate) {\n const fresh = input.generate();\n const save = await saveSecret(coords, fresh);\n if (!save.written) {\n // Hard fail (review B1) — we generated a fresh value but couldn't\n // persist it. If we continued, the next bootstrap re-run would\n // generate a DIFFERENT fresh value and destroy whatever this one\n // encrypted. Better to bail loudly and let the operator fix the\n // underlying Keychain issue.\n p.cancel(\n `Generated a fresh ${input.label} but couldn't persist it to Keychain: ${save.reason ?? 'unknown'}. ` +\n `Continuing would risk silent key rotation on the next re-run. ` +\n `Resolve the Keychain access (re-grant via Keychain Access.app or check the security CLI) and re-run.`,\n );\n process.exit(1);\n }\n p.note(`${pc.green('✓')} Generated fresh ${input.label} and stored in Keychain.`, 'Keychain');\n return fresh;\n }\n\n const pasted = unwrap(\n await p.password({\n message: `Paste the ${input.label} for region ${input.region}:`,\n validate: (v) => input.validate(v ?? ''),\n }),\n );\n const save = await saveSecret(coords, pasted);\n if (!save.written) {\n // Paste path: warning is fine since the operator can paste again on the\n // next run. The value isn't lost — it's still wherever they pasted from.\n p.note(\n `${pc.yellow('⚠')} Couldn't persist to Keychain: ${save.reason ?? 'unknown'}. You'll need to paste it again next run.`,\n 'Keychain',\n );\n } else {\n p.note(`${pc.green('✓')} Stored ${input.label} in Keychain for re-runs.`, 'Keychain');\n }\n return pasted;\n}\n","/**\n * `create-op-node reset` — reverse of bootstrap. Stops the stack, unloads\n * the LaunchAgent, removes the pgsodium key file. By default the docker\n * volumes (and therefore the database) are PRESERVED. Pass `--wipe-data`\n * for the destructive variant; it requires retyping the region label as\n * confirmation.\n *\n * Reset does NOT touch cloud-side state (Cloudflare resources, the GitHub\n * repo, the TFC workspace). It also leaves the Keychain items in place —\n * delete those manually via Keychain Access or `security delete-generic-\n * password -s org.opuspopuli.<region> -a <account>` if you want a truly\n * clean slate.\n *\n * Accounts to wipe (under service `org.opuspopuli.<region>`):\n * pgsodium-root-key, tunnel-token, postgres-password, jwt-secret,\n * supabase-anon-key, supabase-service-role-key, dashboard-password\n *\n * Wiping pgsodium-root-key permanently destroys every value in\n * supabase_vault for this region. Wiping postgres-password locks you out\n * of the existing database. Don't do either without a backup.\n */\n\nimport { access } from 'node:fs/promises';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport { composeDown, composePs, dockerLogout, GHCR_REGISTRY } from '../lib/docker.js';\nimport { defaultPaths as defaultLaunchAgentPaths, teardownLaunchAgent } from '../lib/launchagent.js';\nimport { locateOrCloneRepo, NODE_REPO_MARKERS } from '../lib/noderepo.js';\nimport { unwrap } from '../lib/prompts.js';\nimport { assertNever } from '../lib/assert.js';\nimport type { ContainerSnapshot } from '../lib/docker.js';\nimport type { LaunchAgentPaths, TeardownResult } from '../lib/launchagent.js';\n\nimport { resolveComposeFiles } from './bootstrap.js';\n\ninterface ResetOptions {\n region?: string;\n owner?: string;\n repoDir?: string;\n composeFile?: string[];\n envFile?: string;\n wipeData?: boolean;\n wipeImages?: boolean;\n removeOrphans?: boolean;\n skipStack?: boolean;\n skipLaunchAgent?: boolean;\n keepKeyFile?: boolean;\n skipDockerLogout?: boolean;\n registry?: string;\n dryRun?: boolean;\n yes?: boolean;\n}\n\nconst REGION_RE = /^[a-z0-9-]{2,32}$/;\n\n/* ------------------------------------------------------------------ *\n * Phase-name constants (review S4 / N7) *\n * *\n * Exported so the CLI wrapper, runReset, and tests all share one *\n * source of truth — renames flow through automatically instead of *\n * drifting between the CLI's spinner setup and the orchestration's *\n * emitted phase names. *\n * ------------------------------------------------------------------ */\n\nexport const RESET_PHASES = {\n STOP_STACK: 'Stop stack',\n LAUNCH_AGENT: 'LaunchAgent',\n DOCKER_LOGOUT: 'docker logout',\n} as const;\n\ntype ResetPhaseName = (typeof RESET_PHASES)[keyof typeof RESET_PHASES];\n\n/* ------------------------------------------------------------------ *\n * Orchestration *\n * ------------------------------------------------------------------ */\n\nexport interface ResetPhase {\n readonly name: string;\n /** `dry-run` is reset-specific — verify uses `skipped` for both\n * \"configured-off\" and \"would-do-but-not-running\" because verify\n * has no preview mode. Reset's preview mode wants a distinct icon. */\n readonly status: 'ok' | 'warn' | 'fail' | 'skipped' | 'dry-run';\n readonly detail: string;\n}\n\nexport interface ResetReport {\n readonly phases: ReadonlyArray<ResetPhase>;\n}\n\nexport interface ResetDeps {\n composeDown: typeof composeDown;\n teardownLaunchAgent: typeof teardownLaunchAgent;\n dockerLogout: typeof dockerLogout;\n /** Notification fan-out — lets the CLI render spinners. */\n onPhase?: (phase: ResetPhase) => void;\n}\n\nexport interface ResetInput {\n /** Set when we have a repo path + compose files. When missing the stack\n * phase is reported as skipped. */\n stack?: {\n repoPath: string;\n composeFiles: string[];\n envFile?: string;\n wipeVolumes: boolean;\n /** When true, also remove all images referenced by the compose files\n * (passes `--rmi all` to compose down). Forces a fresh pull on the\n * next bootstrap — used for \"wipe everything and start over\" loops. */\n wipeImages: boolean;\n removeOrphans: boolean;\n };\n launchAgent?: {\n paths: LaunchAgentPaths;\n keepKeyFile: boolean;\n };\n /** Set when the docker-logout phase should run. The registry value is\n * the argument passed to `docker logout <registry>`. */\n dockerLogout?: { registry: string };\n dryRun: boolean;\n}\n\nconst DEFAULT_DEPS: ResetDeps = {\n composeDown,\n teardownLaunchAgent,\n dockerLogout,\n};\n\n/**\n * Run the three reset phases in reverse-bootstrap order.\n *\n * **Continue-on-failure policy**: each phase runs independently — a\n * `composeDown` failure does NOT short-circuit the LaunchAgent or\n * docker-logout phases. This is intentional: reset is best-effort\n * cleanup, and the operator usually wants the LaunchAgent gone even if\n * the docker daemon is down. Use the returned `ResetReport` to inspect\n * which phases failed.\n *\n * Each phase calls `deps.onPhase` exactly once before runReset moves\n * on, so a CLI consumer can render spinners in lockstep.\n */\nexport async function runReset(input: ResetInput, deps: ResetDeps = DEFAULT_DEPS): Promise<ResetReport> {\n // Each phase computes its ResetPhase; push() records it and fires onPhase\n // in lockstep (same order + timing as the original inline loop) so CLI\n // consumers can render spinners one at a time.\n const phases: ResetPhase[] = [];\n const push = (ph: ResetPhase): void => {\n phases.push(ph);\n deps.onPhase?.(ph);\n };\n\n push(await resetStopStackPhase(input, deps));\n push(await resetLaunchAgentPhase(input, deps));\n push(await resetDockerLogoutPhase(input, deps));\n\n return { phases };\n}\n\n// ---- Phase 1: stop the stack ---------------------------------------\nasync function resetStopStackPhase(input: ResetInput, deps: ResetDeps): Promise<ResetPhase> {\n if (!input.stack) {\n return {\n name: RESET_PHASES.STOP_STACK,\n status: 'skipped',\n detail: '--skip-stack or no repo path resolved',\n };\n }\n if (input.dryRun) {\n return {\n name: RESET_PHASES.STOP_STACK,\n status: 'dry-run',\n detail: `would run: docker compose -f ${input.stack.composeFiles.join(' -f ')} down${input.stack.wipeVolumes ? ' -v' : ''}${input.stack.removeOrphans ? ' --remove-orphans' : ''}${input.stack.wipeImages ? ' --rmi all' : ''}`,\n };\n }\n const result = await deps.composeDown({\n files: input.stack.composeFiles,\n cwd: input.stack.repoPath,\n ...(input.stack.envFile ? { envFile: input.stack.envFile } : {}),\n wipeVolumes: input.stack.wipeVolumes,\n removeOrphans: input.stack.removeOrphans,\n ...(input.stack.wipeImages ? { removeImages: 'all' as const } : {}),\n });\n if (!result.ok) {\n return { name: RESET_PHASES.STOP_STACK, status: 'fail', detail: result.reason ?? 'unknown failure' };\n }\n const bits = [\n input.stack.wipeVolumes ? 'volumes destroyed' : 'containers stopped, volumes preserved',\n input.stack.wipeImages ? 'images removed (next bootstrap will re-pull)' : null,\n ].filter(Boolean);\n return { name: RESET_PHASES.STOP_STACK, status: 'ok', detail: bits.join('; ') };\n}\n\n// ---- Phase 2: LaunchAgent ------------------------------------------\nasync function resetLaunchAgentPhase(input: ResetInput, deps: ResetDeps): Promise<ResetPhase> {\n if (!input.launchAgent) {\n return { name: RESET_PHASES.LAUNCH_AGENT, status: 'skipped', detail: '--skip-launch-agent or no plist found' };\n }\n if (input.dryRun) {\n return {\n name: RESET_PHASES.LAUNCH_AGENT,\n status: 'dry-run',\n detail: `would unload ${input.launchAgent.paths.plistFile}, rm plist${\n input.launchAgent.keepKeyFile ? '' : ' + key file'\n }`,\n };\n }\n const result: TeardownResult = await deps.teardownLaunchAgent(\n input.launchAgent.paths,\n { keepKeyFile: input.launchAgent.keepKeyFile },\n );\n if (!result.ok) {\n const fail = result.steps.find((s) => !s.ok);\n return {\n name: RESET_PHASES.LAUNCH_AGENT,\n status: 'fail',\n detail: `${fail?.step}: ${fail?.reason ?? 'unknown'}`,\n };\n }\n const removed = result.steps.filter((s) => s.step !== 'unload').map((s) => s.step).join(', ');\n return { name: RESET_PHASES.LAUNCH_AGENT, status: 'ok', detail: `unloaded + ${removed}` };\n}\n\n// ---- Phase 3: docker logout ----------------------------------------\nasync function resetDockerLogoutPhase(input: ResetInput, deps: ResetDeps): Promise<ResetPhase> {\n if (!input.dockerLogout) {\n return { name: RESET_PHASES.DOCKER_LOGOUT, status: 'skipped', detail: '--skip-docker-logout' };\n }\n if (input.dryRun) {\n return {\n name: RESET_PHASES.DOCKER_LOGOUT,\n status: 'dry-run',\n detail: `would run: docker logout ${input.dockerLogout.registry}`,\n };\n }\n const result = await deps.dockerLogout(input.dockerLogout.registry);\n if (result.ok) {\n return {\n name: RESET_PHASES.DOCKER_LOGOUT,\n status: 'ok',\n detail: `credentials removed from ${input.dockerLogout.registry}`,\n };\n }\n // See dockerLogout() docstring — older Docker versions return non-zero\n // when not currently logged in. Render as warn so reset doesn't fail\n // overall when the operator wasn't logged in to begin with.\n return { name: RESET_PHASES.DOCKER_LOGOUT, status: 'warn', detail: result.reason ?? 'unknown' };\n}\n\n/* ------------------------------------------------------------------ *\n * CLI wrapper *\n * ------------------------------------------------------------------ */\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction phaseIcon(ph: ResetPhase): string {\n switch (ph.status) {\n case 'ok': return pc.green('✓');\n case 'warn': return pc.yellow('⚠');\n case 'skipped': return pc.dim('·');\n case 'dry-run': return pc.cyan('?');\n case 'fail': return pc.red('✗');\n }\n}\n\nexport const resetCommand = new Command('reset')\n .description(\n 'Reverse the Mac Studio side of bootstrap: stop containers, unload the LaunchAgent, ' +\n 'remove the pgsodium key file. Preserves docker volumes by default — pass --wipe-data ' +\n 'for a full data nuke (requires retyping the region label).',\n )\n .addOption(new Option('--region <slug>', 'Region label (used for --wipe-data confirmation + finding the repo)'))\n .addOption(new Option('--owner <owner>', 'GitHub owner for the node repo').default('OpusPopuli'))\n .addOption(new Option('--repo-dir <path>', 'Explicit path to a checked-out node repo'))\n .addOption(\n new Option(\n '--compose-file <path>',\n 'Repeatable. Compose file relative to repo root. Default: docker-compose-prod.yml',\n ).default(['docker-compose-prod.yml'] as string[]),\n )\n .addOption(new Option('--env-file <path>', 'Compose --env-file. Default: .env.production'))\n .addOption(\n new Option(\n '--wipe-data',\n 'DESTROYS docker volumes (adds -v to `compose down`). Requires retyping the region label as confirmation. Default off — volumes preserved.',\n ).default(false),\n )\n .addOption(\n new Option(\n '--wipe-images',\n 'ALSO remove all docker images referenced by the compose file (adds --rmi all). Forces a fresh pull on next bootstrap. Implies --wipe-data semantics for the iteration loop (\"wipe everything and start over\"). Default off.',\n ).default(false),\n )\n .addOption(\n new Option(\n '--no-remove-orphans',\n 'Do NOT pass --remove-orphans to compose down. Preserves containers from compose files no longer included.',\n ),\n )\n .addOption(new Option('--skip-stack', \"Don't touch docker compose\").default(false))\n .addOption(new Option('--skip-launch-agent', \"Don't touch the LaunchAgent\").default(false))\n .addOption(\n new Option(\n '--keep-key-file',\n \"Preserve the pgsodium key file (only matters when LaunchAgent teardown runs). Useful as belt-and-suspenders backup before a wipe-data run.\",\n ).default(false),\n )\n .addOption(new Option('--skip-docker-logout', \"Don't run `docker logout`\").default(false))\n .addOption(new Option('--registry <registry>', 'Registry to log out of').default(GHCR_REGISTRY))\n .addOption(new Option('--dry-run', 'Show what would happen without acting').default(false))\n .addOption(new Option('-y, --yes', 'Skip non-destructive confirmations (wipe still confirms)').default(false))\n .action(async (opts: ResetOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node reset ')));\n\n const wipeImages = opts.wipeImages ?? false;\n // --wipe-images implies --wipe-data — \"wipe everything\" semantics: no\n // point keeping data tied to images that are about to disappear.\n const wipeData = (opts.wipeData ?? false) || wipeImages;\n const removeOrphans = opts.removeOrphans ?? true; // commander --no-remove-orphans sets this to false\n\n const region = await resolveResetRegion(opts);\n const owner = opts.owner ?? 'OpusPopuli';\n const repoName = `opuspopuli-node-${region}`;\n\n const launchAgentPaths = defaultLaunchAgentPaths();\n const plistExists = await fileExists(launchAgentPaths.plistFile);\n const keyFileExists = await fileExists(launchAgentPaths.keyFile);\n const { repoPath, stackSkipReason } = await locateResetRepo(opts, owner, repoName);\n\n const runningContainers = repoPath\n ? await composePs({\n files: resolveComposeFiles(repoPath, opts.composeFile),\n cwd: repoPath,\n ...(opts.envFile ? { envFile: opts.envFile } : {}),\n })\n : null;\n\n renderSnapshotNote({\n region,\n repoPath,\n stackSkipReason,\n runningContainers,\n plistExists,\n keyFileExists,\n launchAgentPaths,\n opts,\n wipeData,\n wipeImages,\n });\n\n await confirmReset({ opts, region, wipeData });\n\n const input = buildResetInput({\n opts,\n repoPath,\n plistExists,\n launchAgentPaths,\n wipeData,\n wipeImages,\n removeOrphans,\n });\n await runResetWithSpinners({ opts, region, wipeData, input });\n });\n\n// ----------------------------------------------------------------------------\n// Reset command phases\n// ----------------------------------------------------------------------------\n// The action delegates to these so no single function exceeds the\n// cognitive-complexity budget. Behavior-preserving: interactive prompts,\n// spinners, and process.exit calls are relocated verbatim.\n\n// ---- Region (needed for confirmation phrase + repo discovery) ----\nasync function resolveResetRegion(opts: ResetOptions): Promise<string> {\n const region = opts.region\n ? opts.region\n : unwrap(\n await p.text({\n message: 'Region label (the slug used during init — e.g. us-ca)?',\n placeholder: 'us-ca',\n validate: (v) =>\n REGION_RE.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens; 2–32 chars',\n }),\n );\n if (!REGION_RE.test(region)) {\n p.cancel(`--region ${JSON.stringify(region)} is not a valid region slug.`);\n process.exit(2);\n }\n return region;\n}\n\n// ---- Locate the node repo (or explain why the stack phase is skipped) ----\n// Exhaustive: every LocateOutcome variant has a deliberate path —\n// operator-supplied --repo-dir mismatch is HARD-fail, ambient cwd miss is\n// SOFT-skip with a visible reason. (review B1)\nasync function locateResetRepo(\n opts: ResetOptions,\n owner: string,\n repoName: string,\n): Promise<{ repoPath?: string; stackSkipReason?: string }> {\n if (opts.skipStack) {\n return { stackSkipReason: '--skip-stack' };\n }\n const located = await locateOrCloneRepo({\n owner,\n name: repoName,\n cwd: process.cwd(),\n allowClone: false,\n ...(opts.repoDir ? { explicit: opts.repoDir } : {}),\n });\n switch (located.kind) {\n case 'found':\n return { repoPath: located.path };\n case 'explicit-not-a-node-repo':\n p.cancel(\n `--repo-dir ${JSON.stringify(located.path)} doesn't look like a node repo ` +\n `(missing one of: ${NODE_REPO_MARKERS.join(', ')}). ` +\n `Verify the path or drop --repo-dir to let reset search the cwd.`,\n );\n return process.exit(2);\n case 'clone-disallowed':\n return { stackSkipReason: `no checkout found at ${process.cwd()}; pass --repo-dir to target one` };\n case 'cloned':\n case 'gh-not-installed':\n case 'clone-failed':\n // Should not be reachable — allowClone: false above. Treat as\n // soft-skip if it ever happens.\n return {\n stackSkipReason: `unexpected outcome ${located.kind} from locateOrCloneRepo with allowClone=false`,\n };\n default:\n return assertNever(located) as never;\n }\n}\n\n// ---- Snapshot note: what's currently present ----\nfunction renderSnapshotNote(args: {\n region: string;\n repoPath: string | undefined;\n stackSkipReason: string | undefined;\n runningContainers: ContainerSnapshot[] | null;\n plistExists: boolean;\n keyFileExists: boolean;\n launchAgentPaths: LaunchAgentPaths;\n opts: ResetOptions;\n wipeData: boolean;\n wipeImages: boolean;\n}): void {\n const {\n region,\n repoPath,\n stackSkipReason,\n runningContainers,\n plistExists,\n keyFileExists,\n launchAgentPaths,\n opts,\n wipeData,\n wipeImages,\n } = args;\n\n let runningContainersLabel: string;\n if (runningContainers === null) {\n runningContainersLabel = pc.dim('unknown');\n } else if (runningContainers.length === 0) {\n runningContainersLabel = pc.dim('none');\n } else {\n runningContainersLabel = pc.cyan(`${runningContainers.length} listed by compose ps`);\n }\n\n p.note(\n [\n `Region: ${pc.cyan(region)}`,\n `Repo path: ${\n repoPath\n ? pc.cyan(repoPath)\n : pc.dim(`not used (${stackSkipReason ?? 'no repo path resolved'})`)\n }`,\n `Running containers: ${runningContainersLabel}`,\n `LaunchAgent plist: ${plistExists ? pc.cyan(launchAgentPaths.plistFile) : pc.dim('not present')}`,\n `pgsodium key file: ${keyFileExists ? pc.cyan(launchAgentPaths.keyFile) : pc.dim('not present')}`,\n `Registry to log out: ${pc.cyan(opts.registry ?? GHCR_REGISTRY)}`,\n `Volume policy: ${wipeData ? pc.red('WIPE') : pc.green('preserve (default)')}`,\n `Image policy: ${wipeImages ? pc.red('WIPE (re-pull on next bootstrap)') : pc.green('keep (default)')}`,\n `Dry run: ${opts.dryRun ? pc.yellow('yes') : pc.dim('no')}`,\n ].join('\\n'),\n 'Snapshot',\n );\n}\n\n// ---- Confirmation gates ----\n// wipe-data requires retyping the region label (modeled on `terraform\n// destroy` — the friction is the point, review B2); otherwise a plain\n// proceed confirm unless --yes / --dry-run.\nasync function confirmReset(args: {\n opts: ResetOptions;\n region: string;\n wipeData: boolean;\n}): Promise<void> {\n const { opts, region, wipeData } = args;\n if (wipeData && !opts.dryRun) {\n unwrap(\n await p.text({\n message: pc.red(`Type the region label to confirm WIPING all volumes (the slug you'd use with --region):`),\n validate: (v) => (v === region ? undefined : `must match the region label exactly`),\n }),\n );\n return;\n }\n if (!opts.dryRun && !opts.yes) {\n const cont = unwrap(\n await p.confirm({\n message: 'Proceed with reset? (volumes will be preserved)',\n initialValue: true,\n }),\n );\n if (!cont) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n }\n}\n\n// ---- Build the runReset input from the resolved snapshot + flags ----\nexport function buildResetInput(args: {\n opts: ResetOptions;\n repoPath: string | undefined;\n plistExists: boolean;\n launchAgentPaths: LaunchAgentPaths;\n wipeData: boolean;\n wipeImages: boolean;\n removeOrphans: boolean;\n}): ResetInput {\n const { opts, repoPath, plistExists, launchAgentPaths, wipeData, wipeImages, removeOrphans } = args;\n const stack = repoPath\n ? {\n repoPath,\n composeFiles: resolveComposeFiles(repoPath, opts.composeFile),\n wipeVolumes: wipeData,\n wipeImages,\n removeOrphans,\n ...(opts.envFile ? { envFile: opts.envFile } : {}),\n }\n : undefined;\n const launchAgent =\n plistExists && !opts.skipLaunchAgent\n ? {\n paths: launchAgentPaths,\n keepKeyFile: opts.keepKeyFile ?? false,\n }\n : undefined;\n const dockerLogoutInput = !opts.skipDockerLogout\n ? { registry: opts.registry ?? GHCR_REGISTRY }\n : undefined;\n return {\n ...(stack ? { stack } : {}),\n ...(launchAgent ? { launchAgent } : {}),\n ...(dockerLogoutInput ? { dockerLogout: dockerLogoutInput } : {}),\n dryRun: opts.dryRun ?? false,\n };\n}\n\n// ---- Run runReset with a spinner per acting phase, then report ----\nasync function runResetWithSpinners(args: {\n opts: ResetOptions;\n region: string;\n wipeData: boolean;\n input: ResetInput;\n}): Promise<void> {\n const { opts, region, wipeData, input } = args;\n\n // Start a spinner per phase that will actually act (not skipped, not\n // dry-run). The phase name comes from RESET_PHASES so it can't drift from\n // runReset's emitted names. (review S4 / N7)\n const phaseSpins = new Map<ResetPhaseName, ReturnType<typeof p.spinner>>();\n const actingPhases: ResetPhaseName[] = [];\n if (input.stack && !input.dryRun) actingPhases.push(RESET_PHASES.STOP_STACK);\n if (input.launchAgent && !input.dryRun) actingPhases.push(RESET_PHASES.LAUNCH_AGENT);\n if (input.dockerLogout && !input.dryRun) actingPhases.push(RESET_PHASES.DOCKER_LOGOUT);\n for (const name of actingPhases) {\n const s = p.spinner();\n s.start(`${name}…`);\n phaseSpins.set(name, s);\n }\n\n const renderPhase = (ph: ResetPhase): void => {\n const spin = phaseSpins.get(ph.name as ResetPhaseName);\n const line = `${phaseIcon(ph)} ${ph.name}: ${pc.dim(ph.detail)}`;\n if (spin) {\n spin.stop(line);\n phaseSpins.delete(ph.name as ResetPhaseName);\n } else {\n p.log.info(line);\n }\n };\n\n const report = await runReset(input, { ...DEFAULT_DEPS, onPhase: renderPhase });\n\n // Belt-and-suspenders: stop any orphan spinners runReset didn't fire\n // onPhase for. Shouldn't happen given the constants-based wiring above.\n for (const [, spin] of phaseSpins) spin.stop(pc.dim('— skipped'));\n\n reportResetOutcome({ report, opts, wipeData, region });\n}\n\n// ---- Final outro / exit code ----\nfunction reportResetOutcome(args: {\n report: ResetReport;\n opts: ResetOptions;\n wipeData: boolean;\n region: string;\n}): void {\n const { report, opts, wipeData, region } = args;\n const failed = report.phases.filter((ph) => ph.status === 'fail').length;\n if (failed > 0) {\n p.outro(pc.red(`${failed} step${failed === 1 ? '' : 's'} failed.`));\n process.exit(1);\n }\n if (opts.dryRun) {\n p.outro(pc.cyan('Dry run complete. Re-run without --dry-run to apply.'));\n return;\n }\n p.outro(\n pc.green(\n wipeData\n ? `Reset complete — volumes wiped. Re-run \\`create-op-node bootstrap --region ${region}\\` to start fresh.`\n : `Reset complete — volumes preserved. Re-run \\`create-op-node bootstrap --region ${region}\\` to bring the stack back up.`,\n ),\n );\n}\n","/**\n * `cosign verify` wrapper for the verify wizard.\n *\n * Keyless verification path: cosign maps the image to a Fulcio-issued\n * certificate, checks the certificate's identity (GitHub Actions workflow URL)\n * + OIDC issuer, AND consults the Rekor transparency log (cosign default,\n * `rekor.sigstore.dev`) for an inclusion proof. So a passing verify means\n * the image was signed by the expected workflow AND that signing event is\n * publicly logged.\n *\n * If `cosign` isn't on PATH we report it as a skip rather than a failure —\n * verify can still pass without it (TLS + GraphQL probes are load-bearing).\n */\n\nimport { safeExeca } from './exec.js';\n\nexport const COSIGN_OIDC_ISSUER = 'https://token.actions.githubusercontent.com';\n\nexport interface CosignVerifyInput {\n image: string;\n /** Glob/regex passed as `--certificate-identity-regexp`. Defaults to the\n * publishing workflow path in the opuspopuli-node template. */\n certificateIdentityRegexp?: string;\n /** OIDC issuer that signed the image. Defaults to GitHub Actions. */\n certificateOidcIssuer?: string;\n}\n\nexport type CosignVerifyResult =\n | { ok: true; output: string }\n | { ok: false; skipped: true; reason: string }\n | { ok: false; skipped: false; reason: string };\n\nexport const DEFAULT_IDENTITY_REGEXP =\n '^https://github\\\\.com/OpusPopuli/opuspopuli/\\\\.github/workflows/.*$';\n\n/**\n * Verify a single OCI image's cosign signature against the GitHub Actions\n * OIDC issuer. Returns one of three shapes:\n *\n * - `{ ok: true }` — signature valid.\n * - `{ ok: false, skipped: true }` — cosign binary not on PATH; caller\n * should render this as a warning, not a failure.\n * - `{ ok: false, skipped: false }` — cosign ran and rejected the image.\n */\nexport async function cosignVerifyImage(input: CosignVerifyInput): Promise<CosignVerifyResult> {\n const idRegex = input.certificateIdentityRegexp ?? DEFAULT_IDENTITY_REGEXP;\n const issuer = input.certificateOidcIssuer ?? COSIGN_OIDC_ISSUER;\n\n const res = await safeExeca('cosign', [\n 'verify',\n '--certificate-identity-regexp',\n idRegex,\n '--certificate-oidc-issuer',\n issuer,\n input.image,\n ]);\n\n if (res === null) {\n return {\n ok: false,\n skipped: true,\n reason: '`cosign` not on PATH (install with `brew install cosign` and rerun to enable signature checks)',\n };\n }\n if (res.exitCode !== 0) {\n return {\n ok: false,\n skipped: false,\n reason: `cosign verify ${input.image} failed (${res.exitCode ?? 'signal'}): ${res.stderr || res.stdout}`,\n };\n }\n return { ok: true, output: res.stdout || res.stderr };\n}\n","/**\n * HTTP probes for `verify`. Two helpers:\n *\n * - `httpProbe` — GET against a URL, return status + truncated body.\n * Used for the `/health` endpoint check.\n * - `graphqlProbe` — POST `{ query: \"{ __typename }\" }`, parse the\n * envelope, confirm it looks like a GraphQL response\n * rather than (say) an HTML error page from the proxy.\n *\n * Both swallow network errors into a `{ ok: false, reason }` so the verify\n * wizard reports them as a phase failure instead of crashing.\n */\n\nimport { BODY_PREVIEW_MAX, VERIFY_NETWORK_TIMEOUT_MS } from './constants.js';\n\n/** Spec-preferred GraphQL response media type. Apollo Gateway accepts plain\n * `application/json` too, but stricter or future implementations may not —\n * send both. (graphql-over-http spec) */\nconst GRAPHQL_ACCEPT = 'application/graphql-response+json, application/json';\n\n/** Slice cap when reading a response body for diagnostics. Streaming would\n * let us bail at this byte count too; for now we read the whole text and\n * cap on display, which is fine for the small bodies these endpoints\n * return. If a pathological server returns gigabytes, the AbortController\n * will fire first. */\nasync function readBodyCapped(res: Response): Promise<string> {\n const text = await res.text();\n return text.slice(0, BODY_PREVIEW_MAX);\n}\n\nexport interface HttpProbeOk {\n ok: true;\n status: number;\n /** First N chars of the response body — useful for surface-level diagnostics\n * (\"got HTML when expecting JSON\"). Capped at BODY_PREVIEW_MAX. */\n bodyPreview: string;\n}\n\nexport interface HttpProbeFailed {\n ok: false;\n reason: string;\n /** Set when we got a response back but the status was unexpected; the\n * wizard renders this in the failure block. */\n status?: number;\n}\n\nexport type HttpProbeResult = HttpProbeOk | HttpProbeFailed;\n\nexport interface HttpProbeInput {\n url: string;\n /** Default 200. Set to e.g. 204 if you're probing a no-content endpoint. */\n expectedStatus?: number;\n timeoutMs?: number;\n /** Injectable for tests. Defaults to globalThis.fetch. */\n fetchImpl?: typeof fetch;\n}\n\nexport async function httpProbe(input: HttpProbeInput): Promise<HttpProbeResult> {\n const expected = input.expectedStatus ?? 200;\n const timeoutMs = input.timeoutMs ?? VERIFY_NETWORK_TIMEOUT_MS;\n const fetchImpl = input.fetchImpl ?? fetch;\n\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), timeoutMs);\n try {\n const res = await fetchImpl(input.url, { method: 'GET', signal: ctrl.signal });\n const bodyPreview = await readBodyCapped(res);\n if (res.status !== expected) {\n // (review N5) Surface the body on a status mismatch the same way\n // graphqlProbe does, so the operator can see the actual error page.\n return {\n ok: false,\n status: res.status,\n reason: bodyPreview\n ? `expected HTTP ${expected}, got ${res.status}: ${bodyPreview}`\n : `expected HTTP ${expected}, got ${res.status}`,\n };\n }\n return { ok: true, status: res.status, bodyPreview };\n } catch (err) {\n const reason =\n (err as Error).name === 'AbortError'\n ? `GET ${input.url} timed out after ${timeoutMs}ms`\n : `GET ${input.url} failed: ${(err as Error).message}`;\n return { ok: false, reason };\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport interface GraphqlProbeOk {\n ok: true;\n /** The value of `data.__typename` from the response envelope. Usually\n * \"Query\" on a healthy Apollo Gateway. */\n typename: string;\n}\n\nexport interface GraphqlProbeFailed {\n ok: false;\n reason: string;\n status?: number;\n}\n\nexport type GraphqlProbeResult = GraphqlProbeOk | GraphqlProbeFailed;\n\nexport interface GraphqlProbeInput {\n url: string;\n timeoutMs?: number;\n fetchImpl?: typeof fetch;\n}\n\n/**\n * POST `{ \"query\": \"{ __typename }\" }` and confirm the envelope shape. Apollo\n * Federation gateways respond with `{ data: { __typename: \"Query\" } }` for\n * this; a misconfigured proxy or a 404 from a wrong path returns HTML or a\n * JSON error envelope that we surface as a failure reason.\n */\nexport async function graphqlProbe(input: GraphqlProbeInput): Promise<GraphqlProbeResult> {\n const timeoutMs = input.timeoutMs ?? VERIFY_NETWORK_TIMEOUT_MS;\n const fetchImpl = input.fetchImpl ?? fetch;\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), timeoutMs);\n try {\n const res = await fetchImpl(input.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Accept: GRAPHQL_ACCEPT },\n body: JSON.stringify({ query: '{ __typename }' }),\n signal: ctrl.signal,\n });\n const text = await readBodyCapped(res);\n if (res.status !== 200) {\n return {\n ok: false,\n status: res.status,\n reason: `expected HTTP 200, got ${res.status}: ${text}`,\n };\n }\n let envelope: unknown;\n try {\n envelope = JSON.parse(text);\n } catch {\n return {\n ok: false,\n status: res.status,\n reason: `response was not JSON: ${text}`,\n };\n }\n const data = (envelope as { data?: { __typename?: unknown } }).data;\n const typename = data?.__typename;\n if (typeof typename !== 'string') {\n return {\n ok: false,\n status: res.status,\n reason: `response missing { data: { __typename: string } }: ${text}`,\n };\n }\n return { ok: true, typename };\n } catch (err) {\n const reason =\n (err as Error).name === 'AbortError'\n ? `POST ${input.url} timed out after ${timeoutMs}ms`\n : `POST ${input.url} failed: ${(err as Error).message}`;\n return { ok: false, reason };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Off-LAN TLS handshake probe. Verify uses this to confirm `api.<domain>`\n * actually negotiates a real, in-date cert from anywhere on the internet\n * before bothering with HTTP probes.\n *\n * We use `tls.connect` rather than just letting fetch do its thing because\n * fetch swallows cert-chain details — we want to surface days-to-expiry so\n * the operator can see \"TLS green, but cert expires in 12 days\" as a soft\n * warning, not just \"fetch failed.\"\n */\n\nimport * as tls from 'node:tls';\n\nimport { VERIFY_NETWORK_TIMEOUT_MS } from './constants.js';\n\nexport interface TlsHandshakeOk {\n ok: true;\n /** Negotiated subject CN (from the leaf cert). */\n subject: string;\n /** Issuer organization (e.g. \"Let's Encrypt\"). */\n issuer: string;\n /** Whole days until the leaf cert's `notAfter` field. Negative when the\n * cert is already expired but the server still happened to return one. */\n daysToExpiry: number;\n}\n\nexport interface TlsHandshakeFailed {\n ok: false;\n reason: string;\n}\n\nexport type TlsHandshakeResult = TlsHandshakeOk | TlsHandshakeFailed;\n\nexport interface TlsProbeInput {\n host: string;\n port?: number;\n /** Socket-level timeout in milliseconds. Anything that doesn't ALPN/SNI\n * within this window is reported as a timeout reason, not a hang. */\n timeoutMs?: number;\n /** Injectable for tests. Defaults to the real `tls.connect`. */\n connect?: typeof tls.connect;\n /** Reference time for daysToExpiry math. Injectable for tests so the\n * expected value doesn't drift. */\n now?: Date;\n}\n\n/** Cert subject/issuer fields can be string or string[] (multi-valued RDNs).\n * We render the first item for display. */\nfunction first(v: string | string[] | undefined): string | undefined {\n if (v === undefined) return undefined;\n return Array.isArray(v) ? v[0] : v;\n}\n\n/**\n * One-shot TLS handshake. Returns the result rather than throwing — the\n * verify wizard wants to fold every failure into a single report.\n */\nexport function tlsHandshake(input: TlsProbeInput): Promise<TlsHandshakeResult> {\n const host = input.host;\n const port = input.port ?? 443;\n const timeoutMs = input.timeoutMs ?? VERIFY_NETWORK_TIMEOUT_MS;\n const connect = input.connect ?? tls.connect;\n const now = input.now ?? new Date();\n\n return new Promise<TlsHandshakeResult>((resolve) => {\n let socket: tls.TLSSocket;\n let settled = false;\n const settle = (r: TlsHandshakeResult): void => {\n if (settled) return;\n settled = true;\n socket?.destroy();\n resolve(r);\n };\n\n // `tls.connect` is async by contract, but the injectable `connect` plus\n // certain pathological options (bad servername length, etc.) can throw\n // synchronously. Convert that into a failure result so callers keep\n // seeing the discriminated union instead of a rejection. (review B2)\n try {\n socket = connect({\n host,\n port,\n servername: host,\n timeout: timeoutMs,\n });\n } catch (err) {\n settle({ ok: false, reason: `tls.connect to ${host}:${port} threw: ${(err as Error).message}` });\n return;\n }\n\n socket.once('secureConnect', () => {\n const cert = socket.getPeerCertificate(false);\n if (!cert || Object.keys(cert).length === 0) {\n settle({ ok: false, reason: 'TLS connected but peer presented no certificate' });\n return;\n }\n const notAfter = new Date(cert.valid_to);\n if (Number.isNaN(notAfter.getTime())) {\n settle({ ok: false, reason: `cert presented an unparseable notAfter: ${cert.valid_to}` });\n return;\n }\n const msPerDay = 1000 * 60 * 60 * 24;\n const daysToExpiry = Math.floor((notAfter.getTime() - now.getTime()) / msPerDay);\n const subject = first(cert.subject?.CN) ?? '<no CN>';\n const issuer = first(cert.issuer?.O) ?? first(cert.issuer?.CN) ?? '<no issuer>';\n settle({ ok: true, subject, issuer, daysToExpiry });\n });\n\n socket.once('timeout', () => {\n settle({ ok: false, reason: `TLS handshake to ${host}:${port} timed out after ${timeoutMs}ms` });\n });\n\n socket.once('error', (err) => {\n settle({ ok: false, reason: `TLS handshake to ${host}:${port} failed: ${err.message}` });\n });\n });\n}\n","import { readFileSync } from 'node:fs';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport { tunnelStatus, type TunnelStatusInput, type TunnelStatusResult } from '../lib/cloudflare.js';\nimport { cosignVerifyImage, type CosignVerifyInput, type CosignVerifyResult } from '../lib/cosign.js';\nimport { graphqlProbe, httpProbe, type GraphqlProbeInput, type GraphqlProbeResult, type HttpProbeInput, type HttpProbeResult } from '../lib/http.js';\nimport { unwrap } from '../lib/prompts.js';\nimport { tlsHandshake, type TlsProbeInput, type TlsHandshakeResult } from '../lib/tls.js';\n\ninterface VerifyOptions {\n domain?: string;\n apiHost?: string;\n cfToken?: string;\n cfTokenFile?: string;\n cfAccountId?: string;\n tunnelId?: string;\n image?: string[];\n certWarnDays?: string;\n showSkipped?: boolean;\n}\n\nconst DOMAIN_RE = /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i;\n\nexport interface VerifyPhase {\n readonly name: string;\n readonly status: 'ok' | 'warn' | 'fail' | 'skipped';\n readonly detail: string;\n}\n\nexport interface VerifyReport {\n readonly phases: ReadonlyArray<VerifyPhase>;\n}\n\nexport function summarize(report: VerifyReport): { ok: boolean; failed: number; warned: number } {\n let failed = 0;\n let warned = 0;\n for (const ph of report.phases) {\n if (ph.status === 'fail') failed++;\n if (ph.status === 'warn') warned++;\n }\n return { ok: failed === 0, failed, warned };\n}\n\nfunction formatExpiry(days: number): string {\n if (days < 0) return `expired ${-days}d ago`;\n if (days === 0) return 'expires today';\n return `${days}d to expiry`;\n}\n\n/* ------------------------------------------------------------------ *\n * Injectable orchestration (review S3) *\n * ------------------------------------------------------------------ */\n\nexport interface VerifyDeps {\n tls: (input: TlsProbeInput) => Promise<TlsHandshakeResult>;\n http: (input: HttpProbeInput) => Promise<HttpProbeResult>;\n graphql: (input: GraphqlProbeInput) => Promise<GraphqlProbeResult>;\n tunnel: (input: TunnelStatusInput) => Promise<TunnelStatusResult>;\n cosign: (input: CosignVerifyInput) => Promise<CosignVerifyResult>;\n /** Called once per phase as it resolves — lets the CLI render spinners.\n * Pass a no-op for tests that just want the report. */\n onPhase?: (phase: VerifyPhase) => void;\n}\n\nexport interface VerifyInput {\n apiHost: string;\n certWarnDays: number;\n /** All three OR none. Mid-set is treated as a `warn` phase by runVerify. */\n cf?: {\n token?: string;\n accountId?: string;\n tunnelId?: string;\n };\n images: ReadonlyArray<string>;\n}\n\nconst DEFAULT_DEPS: VerifyDeps = {\n tls: tlsHandshake,\n http: httpProbe,\n graphql: graphqlProbe,\n tunnel: tunnelStatus,\n cosign: cosignVerifyImage,\n};\n\ntype PushVerifyPhase = (ph: VerifyPhase) => void;\n\nexport async function runVerify(input: VerifyInput, deps: VerifyDeps = DEFAULT_DEPS): Promise<VerifyReport> {\n // Each phase pushes its result(s) via push(), which records + fires onPhase\n // in lockstep. push is threaded into the phase helpers (rather than having\n // them return arrays) so the cosign loop keeps firing onPhase per-image,\n // interleaved with its async calls — exactly as the original inline loop.\n const phases: VerifyPhase[] = [];\n const push: PushVerifyPhase = (ph) => {\n phases.push(ph);\n deps.onPhase?.(ph);\n };\n\n await verifyTlsPhase(input, deps, push);\n await verifyHealthPhase(input, deps, push);\n await verifyGraphqlPhase(input, deps, push);\n await verifyCloudflarePhase(input, deps, push);\n await verifyCosignPhase(input, deps, push);\n\n return { phases };\n}\n\n// ---- Phase 1: TLS handshake ---------------------------------------\nasync function verifyTlsPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const tls = await deps.tls({ host: input.apiHost });\n if (!tls.ok) {\n push({ name: 'TLS handshake', status: 'fail', detail: tls.reason });\n return;\n }\n const line = `subject=${tls.subject}, issuer=${tls.issuer}, ${formatExpiry(tls.daysToExpiry)}`;\n if (tls.daysToExpiry < input.certWarnDays) {\n push({\n name: 'TLS handshake',\n status: 'warn',\n detail: tls.daysToExpiry < 0 ? line : `${line} (< warn threshold ${input.certWarnDays}d)`,\n });\n return;\n }\n push({ name: 'TLS handshake', status: 'ok', detail: line });\n}\n\n// ---- Phase 2: GET /health ------------------------------------------\nasync function verifyHealthPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const health = await deps.http({ url: `https://${input.apiHost}/health` });\n if (health.ok) {\n push({ name: 'GET /health', status: 'ok', detail: `HTTP ${health.status}` });\n } else {\n push({ name: 'GET /health', status: 'fail', detail: health.reason });\n }\n}\n\n// ---- Phase 3: GraphQL { __typename } -------------------------------\nasync function verifyGraphqlPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const gql = await deps.graphql({ url: `https://${input.apiHost}/api` });\n if (gql.ok) {\n push({ name: 'GraphQL { __typename }', status: 'ok', detail: `typename=${gql.typename}` });\n } else {\n push({ name: 'GraphQL { __typename }', status: 'fail', detail: gql.reason });\n }\n}\n\n// ---- Phase 4: Cloudflare Tunnel status (optional) ------------------\nasync function verifyCloudflarePhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n const cfFields: ReadonlyArray<[string, string | undefined]> = [\n ['--cf-token', input.cf?.token],\n ['--cf-account-id', input.cf?.accountId],\n ['--tunnel-id', input.cf?.tunnelId],\n ];\n const cfSet = cfFields.filter(([, v]) => v !== undefined && v !== '');\n if (cfSet.length === 0) {\n push({\n name: 'Cloudflare Tunnel',\n status: 'skipped',\n detail: 'pass --cf-token + --cf-account-id + --tunnel-id to enable',\n });\n return;\n }\n if (cfSet.length < cfFields.length) {\n // (review S1) Partial config is operator-hostile — they almost certainly\n // meant to enable the check. Warn so the missing flag names are visible.\n const missing = cfFields.filter(([, v]) => v === undefined || v === '').map(([name]) => name).join(', ');\n push({\n name: 'Cloudflare Tunnel',\n status: 'warn',\n detail: `partial CF config — missing ${missing}; check skipped`,\n });\n return;\n }\n const tun = await deps.tunnel({\n token: input.cf!.token!,\n accountId: input.cf!.accountId!,\n tunnelId: input.cf!.tunnelId!,\n });\n if (!tun.ok) {\n push({ name: 'Cloudflare Tunnel', status: 'fail', detail: tun.reason });\n } else if (tun.connections === 0) {\n push({\n name: 'Cloudflare Tunnel',\n status: 'warn',\n detail: `status=${tun.status}, 0 connections — cloudflared on the Studio appears offline`,\n });\n } else {\n push({\n name: 'Cloudflare Tunnel',\n status: 'ok',\n detail: `${tun.connections} connections, status=${tun.status}`,\n });\n }\n}\n\n// ---- Phase 5: cosign signature check (optional) --------------------\nasync function verifyCosignPhase(input: VerifyInput, deps: VerifyDeps, push: PushVerifyPhase): Promise<void> {\n if (input.images.length === 0) {\n push({\n name: 'cosign verify',\n status: 'skipped',\n detail: 'pass --image <ref> (repeatable) to enable',\n });\n return;\n }\n for (const image of input.images) {\n const cos = await deps.cosign({ image });\n if (cos.ok) {\n push({ name: `cosign verify ${image}`, status: 'ok', detail: 'signature valid' });\n } else if (cos.skipped) {\n push({ name: `cosign verify ${image}`, status: 'skipped', detail: cos.reason });\n } else {\n push({ name: `cosign verify ${image}`, status: 'fail', detail: cos.reason });\n }\n }\n}\n\n/* ------------------------------------------------------------------ *\n * CLI wrapper *\n * ------------------------------------------------------------------ */\n\nfunction readTokenFile(path: string): string {\n const raw = readFileSync(path, 'utf8').trim();\n if (!raw) throw new Error(`--cf-token-file ${path} was empty`);\n return raw;\n}\n\nexport const verifyCommand = new Command('verify')\n .description(\n 'Off-LAN health probe of a live node — TLS, Apollo Federation reachability, GraphQL smoke. ' +\n 'Run from anywhere with internet access.',\n )\n .addOption(\n new Option('--domain <domain>', 'Domain to probe (e.g. example.org → checks api.example.org)'),\n )\n .addOption(new Option('--api-host <host>', 'Override the API hostname (default: api.<domain>)'))\n .addOption(new Option('--cf-token <token>', 'Cloudflare API token (enables tunnel-status probe)'))\n .addOption(\n new Option('--cf-token-file <path>', 'Read CF token from a file (avoids exposing it via ps)'),\n )\n .addOption(new Option('--cf-account-id <id>', 'Cloudflare account ID (required with --cf-token)'))\n .addOption(\n new Option('--tunnel-id <id>', 'Cloudflare Tunnel ID to query (required with --cf-token)'),\n )\n .addOption(\n new Option('--image <ref>', 'Repeatable. Image to cosign-verify (e.g. ghcr.io/opuspopuli/api:tag)').default(\n [] as string[],\n ),\n )\n .addOption(\n new Option('--cert-warn-days <n>', 'Warn if cert expires within N days').default('14'),\n )\n .addOption(\n new Option('--show-skipped', 'Include skipped phases in the summary').default(false),\n )\n .action(async (opts: VerifyOptions) => {\n p.intro(pc.bgCyan(pc.black(' create-op-node verify ')));\n\n const domain = await resolveDomain(opts);\n const certWarnDays = resolveCertWarnDays(opts);\n const cfToken = resolveCfToken(opts);\n\n const apiHost = opts.apiHost ?? `api.${domain}`;\n const images = opts.image ?? [];\n const totalPhases = 4 + (images.length === 0 ? 1 : images.length);\n\n const report = await runVerifyWithSpinner({\n apiHost,\n certWarnDays,\n cfToken,\n opts,\n images,\n totalPhases,\n });\n\n renderVerifySummary(report, { opts, totalPhases });\n reportVerifyOutcome(report);\n });\n\nfunction phaseIcon(ph: VerifyPhase): string {\n switch (ph.status) {\n case 'ok': return pc.green('✓');\n case 'warn': return pc.yellow('⚠');\n case 'skipped': return pc.dim('·');\n case 'fail': return pc.red('✗');\n }\n}\n\nfunction phaseColor(status: VerifyPhase['status']): (text: string) => string {\n switch (status) {\n case 'ok': return pc.green;\n case 'warn': return pc.yellow;\n case 'skipped': return pc.dim;\n case 'fail': return pc.red;\n }\n}\n\nfunction formatPhaseLine(prefix: string, ph: VerifyPhase): string {\n const icon = phaseIcon(ph);\n const colorize = phaseColor(ph.status);\n return colorize(`${icon} ${prefix}: ${ph.detail}`);\n}\n\n// ----------------------------------------------------------------------------\n// Verify command phases\n// ----------------------------------------------------------------------------\n// The action delegates to these so no single function exceeds the\n// cognitive-complexity budget. Behavior-preserving: interactive prompts,\n// spinners, and process.exit calls are relocated verbatim.\n\nasync function resolveDomain(opts: VerifyOptions): Promise<string> {\n const domain = opts.domain\n ? opts.domain\n : unwrap(\n await p.text({\n message: 'Public domain of the node?',\n placeholder: 'yournode.example.org',\n validate: (v) =>\n DOMAIN_RE.test(v ?? '') ? undefined : 'lowercase letters, digits, hyphens, dots; must contain a dot and a TLD',\n }),\n );\n if (!DOMAIN_RE.test(domain)) {\n p.cancel(`--domain ${JSON.stringify(domain)} doesn't look like a domain.`);\n process.exit(2);\n }\n return domain;\n}\n\n// (review B1) Validate --cert-warn-days to a non-negative integer.\nfunction resolveCertWarnDays(opts: VerifyOptions): number {\n const rawDays = opts.certWarnDays ?? '14';\n const certWarnDays = Number.parseInt(rawDays, 10);\n if (!Number.isFinite(certWarnDays) || certWarnDays < 0 || !/^\\d+$/.test(rawDays)) {\n p.cancel(`--cert-warn-days must be a non-negative integer (got ${JSON.stringify(rawDays)}).`);\n process.exit(2);\n }\n return certWarnDays;\n}\n\n// Resolve the CF token from --cf-token or --cf-token-file (mutually exclusive).\nfunction resolveCfToken(opts: VerifyOptions): string | undefined {\n if (opts.cfToken && opts.cfTokenFile) {\n p.cancel('Pass either --cf-token or --cf-token-file, not both.');\n process.exit(2);\n }\n if (opts.cfToken) return opts.cfToken;\n if (!opts.cfTokenFile) return undefined;\n try {\n return readTokenFile(opts.cfTokenFile);\n } catch (err) {\n p.cancel((err as Error).message);\n process.exit(2);\n }\n}\n\n// Run the checks behind a single spinner that advances per phase.\nasync function runVerifyWithSpinner(args: {\n apiHost: string;\n certWarnDays: number;\n cfToken: string | undefined;\n opts: VerifyOptions;\n images: string[];\n totalPhases: number;\n}): Promise<VerifyReport> {\n const { apiHost, certWarnDays, cfToken, opts, images, totalPhases } = args;\n\n let phaseIndex = 0;\n let activeSpin: ReturnType<typeof p.spinner> | null = null;\n const renderPhase = (ph: VerifyPhase): void => {\n phaseIndex++;\n const prefix = `[${phaseIndex}/${totalPhases}] ${ph.name}`;\n activeSpin?.stop(formatPhaseLine(prefix, ph));\n activeSpin = null;\n };\n\n const deps: VerifyDeps = { ...DEFAULT_DEPS, onPhase: renderPhase };\n\n activeSpin = p.spinner();\n activeSpin.start('Running checks…');\n\n const report = await runVerify(\n {\n apiHost,\n certWarnDays,\n cf: {\n ...(cfToken ? { token: cfToken } : {}),\n ...(opts.cfAccountId ? { accountId: opts.cfAccountId } : {}),\n ...(opts.tunnelId ? { tunnelId: opts.tunnelId } : {}),\n },\n images,\n },\n deps,\n );\n // If `runVerify` finished without firing onPhase for some pathological\n // reason, stop the spinner cleanly.\n activeSpin?.stop('Done.');\n return report;\n}\n\n// Render the per-phase summary note (hiding skipped phases unless asked).\nfunction renderVerifySummary(\n report: VerifyReport,\n args: { opts: VerifyOptions; totalPhases: number },\n): void {\n const { opts, totalPhases } = args;\n const visible = (opts.showSkipped ?? false)\n ? report.phases\n : report.phases.filter((ph) => ph.status !== 'skipped');\n const lines = visible.map((ph) => {\n const idx = report.phases.indexOf(ph) + 1;\n return `${phaseIcon(ph)} [${idx}/${totalPhases}] ${ph.name}: ${pc.dim(ph.detail)}`;\n });\n const skippedCount = report.phases.length - visible.length;\n if (skippedCount > 0 && !opts.showSkipped) {\n lines.push(pc.dim(`· ${skippedCount} phase${skippedCount === 1 ? '' : 's'} skipped (run with --show-skipped to see them)`));\n }\n p.note(lines.join('\\n'), 'Summary');\n}\n\n// Final outro + exit code from the phase report.\nfunction reportVerifyOutcome(report: VerifyReport): void {\n const summary = summarize(report);\n if (!summary.ok) {\n p.outro(pc.red(`${summary.failed} check${summary.failed === 1 ? '' : 's'} failed.`));\n process.exit(1);\n }\n if (summary.warned === 0) {\n p.outro(pc.green('All checks passed.'));\n } else {\n p.outro(pc.yellow(`Passed with ${summary.warned} warning${summary.warned === 1 ? '' : 's'}.`));\n }\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://github.com/OpusPopuli/opuspopuli-regions/schema/region-plugin.schema.json\",\n \"title\": \"Region Plugin File\",\n \"description\": \"A declarative region configuration file for the Opus Populi civic data platform. A handful of string-valued fields (ApiSourceConfig.queryParams, BulkDownloadConfig.filters) support ${variableName} placeholders that the consumer resolves at runtime — see those field descriptions for the supported variable list.\",\n \"type\": \"object\",\n \"required\": [\"name\", \"displayName\", \"description\", \"version\", \"config\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Region identifier (e.g., 'california')\"\n },\n \"displayName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Human-readable region name (e.g., 'California')\"\n },\n \"description\": {\n \"type\": \"string\",\n \"description\": \"Brief description of this region's data coverage\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\",\n \"description\": \"Semantic version of this config file\"\n },\n \"config\": {\n \"$ref\": \"#/definitions/DeclarativeRegionConfig\"\n }\n },\n \"definitions\": {\n \"DeclarativeRegionConfig\": {\n \"type\": \"object\",\n \"required\": [\"regionId\", \"regionName\", \"description\", \"timezone\", \"dataSources\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"regionId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Region identifier (e.g., 'california')\"\n },\n \"regionName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Human-readable region name (e.g., 'California')\"\n },\n \"description\": {\n \"type\": \"string\",\n \"description\": \"Region description\"\n },\n \"timezone\": {\n \"type\": \"string\",\n \"description\": \"IANA timezone (e.g., 'America/Los_Angeles')\"\n },\n \"stateCode\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Z]{2}$\",\n \"description\": \"Two-letter US state code (e.g., 'CA')\"\n },\n \"parentRegionId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Region identifier of this region's parent in the geographic hierarchy. Top-level regions (states, federal) omit this field. Counties set parentRegionId to their state's regionId (e.g., 'california'); cities will set it to their county's regionId. Presence of this field is the canonical signal that a region is a sub-region; the consumer loader uses it to build the region tree.\"\n },\n \"fipsCode\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d{2,7}$\",\n \"description\": \"Census FIPS code: 2 digits for states (e.g., '06' for CA), 5 digits for counties (e.g., '06037' for Los Angeles County — state FIPS + county FIPS), 7 digits for places/cities. This is the canonical join key against the consumer's PostGIS counties/places tables used today for user-to-district placement.\"\n },\n \"dataSources\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": \"#/definitions/DataSourceConfig\"\n },\n \"description\": \"Data sources to scrape\"\n },\n \"rateLimit\": {\n \"type\": \"object\",\n \"properties\": {\n \"requestsPerSecond\": { \"type\": \"number\", \"minimum\": 0 },\n \"burstSize\": { \"type\": \"integer\", \"minimum\": 1 }\n },\n \"required\": [\"requestsPerSecond\", \"burstSize\"],\n \"additionalProperties\": false,\n \"description\": \"Rate limiting defaults\"\n },\n \"cacheTtlMs\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Cache TTL in milliseconds\"\n },\n \"requestTimeoutMs\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Request timeout in milliseconds\"\n },\n \"normalizeExternalIdDistrict\": {\n \"type\": \"boolean\",\n \"description\": \"Strip leading zeros from representative externalId trailing segment (e.g. ca-assembly-01 → ca-assembly-1). Opt-in; default false. Only needed for regions whose LLM manifests emit zero-padded district numbers.\"\n },\n \"bioNoisePatterns\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Regex pattern strings (case-insensitive) matched against scraped representative bio text. Bios matching any pattern are treated as nav junk and discarded. Defaults to no filtering if omitted.\"\n },\n \"boundarySources\": {\n \"$ref\": \"#/definitions/BoundarySourcesConfig\",\n \"description\": \"Civic-boundary geometry sources used to populate the consumer's `jurisdictions` table (counties, cities, state legislative districts, school districts, special districts). The consumer's BoundaryLoaderService reads this block, dispatches to TIGER and ArcGIS FeatureServer fetchers, and upserts on fipsCode/ocdId. Omit when a region has no public boundary data — addresses still resolve via Census Geocoder string fields, but PostGIS point-in-polygon queries return no matches. See opuspopuli#804.\"\n }\n }\n },\n \"BoundarySourcesConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"ocdIdPrefix\"],\n \"description\": \"Per-region declarative recipe for loading civic boundaries. Pure config — no per-region code lives in the consumer.\",\n \"properties\": {\n \"ocdIdPrefix\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Open Civic Data ID prefix for this region, e.g. 'ocd-division/country:us/state:ca'. All jurisdiction OCD-IDs are composed as `${ocdIdPrefix}${TigerLayerConfig.ocdIdSegment}` (or the Geoportal equivalent).\"\n },\n \"tigerLayers\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"$ref\": \"#/definitions/TigerLayerConfig\" },\n \"description\": \"US Census TIGER/Line layers to ingest as jurisdictions. Each entry maps one ArcGIS MapServer layer to a JurisdictionType. Omit the field entirely when the region has no TIGER coverage — do not pass an empty array (the schema rejects it to prevent silent typos that strip the configured layers).\"\n },\n \"geoportalLayers\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"$ref\": \"#/definitions/GeoportalLayerConfig\" },\n \"description\": \"Region-specific ArcGIS FeatureServer endpoints — typically state geoportals serving boundary data Census TIGER doesn't cover (fire districts, water districts, transit districts, etc.). Omit when unused — empty arrays are rejected (see tigerLayers note).\"\n }\n }\n },\n \"JurisdictionTypeEnum\": {\n \"type\": \"string\",\n \"enum\": [\"COUNTY\", \"CITY\", \"STATE_SENATE_DISTRICT\", \"STATE_ASSEMBLY_DISTRICT\", \"CONGRESSIONAL_DISTRICT\", \"SCHOOL_DISTRICT_UNIFIED\", \"SCHOOL_DISTRICT_ELEMENTARY\", \"SCHOOL_DISTRICT_HIGH\", \"COMMUNITY_COLLEGE_DISTRICT\", \"WATER_DISTRICT\", \"FIRE_DISTRICT\", \"TRANSIT_DISTRICT\", \"SPECIAL_DISTRICT\"],\n \"description\": \"Maps each feature to a JurisdictionType row in the consumer's `jurisdictions` table. Single source of truth — TigerLayerConfig and GeoportalLayerConfig both reference this so a new jurisdiction type can't be added to one without the other.\"\n },\n \"JurisdictionLevelEnum\": {\n \"type\": \"string\",\n \"enum\": [\"FEDERAL\", \"STATE\", \"COUNTY\", \"MUNICIPAL\", \"DISTRICT\"],\n \"description\": \"Hierarchy level for the resulting jurisdiction rows. Single source of truth — referenced from TigerLayerConfig and GeoportalLayerConfig.\"\n },\n \"TigerLayerConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"layer\", \"outFields\", \"jurisdictionType\", \"level\", \"nameField\"],\n \"description\": \"One TIGER/Line layer mapped to a JurisdictionType. The consumer hits `https://tigerweb.geo.census.gov/arcgis/rest/services/TIGERweb/${layer}/query` with GeoJSON output. Supported placeholders inside `where`, `ocdIdSegment`, `nameTemplate`: ${fipsCode} (this region's fipsCode), ${stateCode} (two-letter code), ${name} (the layer's nameField value for a given feature), ${district} (the districtField value).\",\n \"properties\": {\n \"layer\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"TIGER MapServer service+layer path, e.g. 'State_County/MapServer/1', 'Legislative/MapServer/1' (state senate), 'Legislative/MapServer/2' (state assembly), 'School/MapServer/0' (unified school districts).\"\n },\n \"where\": {\n \"type\": \"string\",\n \"description\": \"ESRI WHERE clause filtering features. Defaults to `STATE='${fipsCode}'` when omitted. Use `${fipsCode}` / `${stateCode}` placeholders.\"\n },\n \"outFields\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Comma-separated TIGER attribute fields to return, e.g. 'GEOID,NAME' or 'GEOID,SLDUST'.\"\n },\n \"jurisdictionType\": {\n \"$ref\": \"#/definitions/JurisdictionTypeEnum\"\n },\n \"level\": {\n \"$ref\": \"#/definitions/JurisdictionLevelEnum\"\n },\n \"nameField\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"TIGER attribute key whose value becomes the substitution for `${name}` placeholders. Typically 'NAME' for human-readable layers, or a district code field like 'SLDUST'/'SLDLST' for legislative layers.\"\n },\n \"fipsField\": {\n \"type\": \"string\",\n \"description\": \"TIGER attribute key holding the canonical fips_code for an upsert. Defaults to 'GEOID'.\"\n },\n \"fipsPrefix\": {\n \"type\": \"string\",\n \"description\": \"Optional prefix prepended to the fipsField value before persisting as fips_code. Use when the raw GEOID would collide with another layer's GEOID (e.g. state senate GEOID overlapping county GEOID format). Example: 'sldu-' for state senate, 'sldl-' for state assembly.\"\n },\n \"districtField\": {\n \"type\": \"string\",\n \"description\": \"TIGER attribute key supplying the ${district} placeholder. Required when ocdIdSegment or nameTemplate contains ${district}.\"\n },\n \"ocdIdSegment\": {\n \"type\": \"string\",\n \"description\": \"Segment appended to `boundarySources.ocdIdPrefix` to form the full OCD-ID, e.g. '/county:${name}', '/sldu:${district}'. Supports ${name} and ${district} placeholders. Inside `${name}` substitutions the consumer normalizes whitespace to underscores and lowercases the value for OCD-ID compatibility — so a NAME of 'Alameda County' produces 'alameda_county' in the OCD-ID. Omit when this layer's rows don't carry an OCD-ID.\"\n },\n \"nameTemplate\": {\n \"type\": \"string\",\n \"description\": \"Template for the persisted jurisdiction name (NOT for OCD-ID composition). Supports ${name}, ${district}, ${stateCode}. The ${name} value is substituted verbatim (case + whitespace preserved). Defaults to ${name} when omitted.\"\n }\n }\n },\n \"GeoportalLayerConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"url\", \"outFields\", \"jurisdictionType\", \"level\", \"nameField\"],\n \"description\": \"One arbitrary ArcGIS FeatureServer layer for jurisdictions Census TIGER doesn't cover. Same placeholder rules as TigerLayerConfig.\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\",\n \"pattern\": \"^https://\",\n \"description\": \"Full ArcGIS FeatureServer layer URL ending in /FeatureServer/<n>. Must be HTTPS — the consumer rejects other schemes. The consumer paginates via resultOffset/resultRecordCount.\"\n },\n \"where\": {\n \"type\": \"string\",\n \"description\": \"ESRI WHERE clause. Defaults to '1=1'.\"\n },\n \"outFields\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Comma-separated FeatureServer attribute fields to return.\"\n },\n \"jurisdictionType\": {\n \"$ref\": \"#/definitions/JurisdictionTypeEnum\"\n },\n \"level\": {\n \"$ref\": \"#/definitions/JurisdictionLevelEnum\"\n },\n \"nameField\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"FeatureServer attribute key supplying the human-readable name and the ${name} placeholder.\"\n },\n \"fipsField\": {\n \"type\": \"string\",\n \"description\": \"FeatureServer attribute key used as fips_code. No default — geoportal attribute names vary widely (no GEOID convention). Omit when the layer has no FIPS analog; the upsert then matches on ocdId only.\"\n },\n \"fipsPrefix\": {\n \"type\": \"string\",\n \"description\": \"Optional prefix prepended to fipsField, mirroring TigerLayerConfig.fipsPrefix.\"\n },\n \"ocdIdSegment\": {\n \"type\": \"string\",\n \"description\": \"Appended to boundarySources.ocdIdPrefix. Supports ${name} placeholder. Same OCD-ID normalization as TigerLayerConfig.ocdIdSegment — whitespace to underscores, lowercased.\"\n },\n \"nameTemplate\": {\n \"type\": \"string\",\n \"description\": \"Template for persisted name (NOT for OCD-ID). ${name} substituted verbatim. Defaults to ${name}.\"\n }\n }\n },\n \"DataSourceConfig\": {\n \"type\": \"object\",\n \"required\": [\"url\", \"dataType\", \"contentGoal\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\",\n \"description\": \"URL to fetch data from\"\n },\n \"dataType\": {\n \"type\": \"string\",\n \"enum\": [\"propositions\", \"meetings\", \"representatives\", \"campaign_finance\", \"lobbying\", \"civics\", \"bills\"],\n \"description\": \"What type of content this source provides. Daily journals / meeting minutes go under 'meetings' with sourceType=pdf_archive — the consumer partitions by sourceType internally. 'civics' marks a source of region governmental structure, process, and vocabulary; the civics-ingest handler scrapes it and uses the private prompt-service to extract structured shape (chambers, measure types, lifecycle stages with status patterns, glossary) plus a plain-language rewrite for laypeople. Verbatim source text and the AI rewrite are stored together — never one without the other. 'bills' marks a source of individual legislative bills (AB, SB, ACA, SCA, etc.) scraped from an official legislature website; the bills-ingest handler BFS-crawls from the seed URL and extracts one Bill record per detail page. See opuspopuli#686.\"\n },\n \"contentGoal\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Natural language description of what to find/extract\"\n },\n \"category\": {\n \"type\": \"string\",\n \"description\": \"Sub-category for grouping (e.g., 'Assembly', 'Senate')\"\n },\n \"hints\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Hints to help the AI find the right content\"\n },\n \"rateLimitOverride\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"description\": \"Override rate limit for this specific source\"\n },\n \"syncCadence\": {\n \"type\": \"string\",\n \"pattern\": \"^[^ ]+ [^ ]+ [^ ]+ [^ ]+ [^ ]+$\",\n \"description\": \"5-field cron expression (minute hour dom month dow) controlling how often this source is synced. The worker applies a deterministic per-source minute offset at registration time to spread load across gov hosts — the minute field you specify is the base, not the exact fire time. Omit to inherit the global daily fallback. Common patterns: '0 2 * * *' daily at 2 AM, '0 2 * * 0' weekly on Sunday, '0 * * * *' hourly.\"\n },\n \"statusScanCadence\": {\n \"type\": \"string\",\n \"pattern\": \"^[^ ]+ [^ ]+ [^ ]+ [^ ]+ [^ ]+$\",\n \"description\": \"5-field cron expression for a periodic full status-page sweep of all bills (dataType='bills' only). Runs forceStatusRecheck=true — bypasses the needsStatusRecheck flag and the sourcePublishedAt skip to catch governor actions and off-session changes the journal linker can't see. Per-source minute offset is applied like syncCadence. Typical: '0 2 * * 0' weekly Sunday 2 AM. See #689.\"\n },\n \"sourceType\": {\n \"type\": \"string\",\n \"enum\": [\"html_scrape\", \"bulk_download\", \"api\", \"pdf\", \"pdf_archive\"],\n \"description\": \"Source type determines the extraction strategy (default: html_scrape). 'pdf_archive' selects the listing-walk + per-PDF-extract pipeline: the URL is a paginated listing page that links to a series of dated PDF documents, each fetched and parsed (text only at V1) into one Minutes record.\"\n },\n \"bulk\": {\n \"$ref\": \"#/definitions/BulkDownloadConfig\"\n },\n \"api\": {\n \"$ref\": \"#/definitions/ApiSourceConfig\"\n },\n \"pdf\": {\n \"$ref\": \"#/definitions/PdfSourceConfig\"\n },\n \"pdfArchive\": {\n \"$ref\": \"#/definitions/PdfArchiveConfig\"\n },\n \"billDiscovery\": {\n \"$ref\": \"#/definitions/BillDiscoveryConfig\"\n },\n \"detailFields\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"string\" },\n { \"$ref\": \"#/definitions/StructuredFieldConfig\" }\n ]\n },\n \"description\": \"Detail page extraction plan: maps domain field names to CSS selectors (string) or structured array configs (object). Supports dot notation and '|attr:name' suffix.\"\n },\n \"staticManifest\": {\n \"type\": \"object\",\n \"required\": [\"containerSelector\", \"itemSelector\", \"fieldMappings\"],\n \"additionalProperties\": false,\n \"description\": \"Explicit extraction selectors that bypass AI structural analysis entirely. Use when the page structure is known and stable, or when the local LLM consistently generates wrong selectors.\",\n \"properties\": {\n \"containerSelector\": { \"type\": \"string\" },\n \"itemSelector\": { \"type\": \"string\" },\n \"fieldMappings\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\"fieldName\", \"selector\", \"extractionMethod\", \"required\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"fieldName\": { \"type\": \"string\" },\n \"selector\": { \"type\": \"string\" },\n \"extractionMethod\": { \"type\": \"string\" },\n \"attribute\": { \"type\": \"string\" },\n \"regexPattern\": { \"type\": \"string\" },\n \"regexGroup\": { \"type\": \"integer\" },\n \"transform\": { \"type\": \"object\" },\n \"required\": { \"type\": \"boolean\" },\n \"defaultValue\": { \"type\": \"string\" },\n \"scope\": {\n \"type\": \"string\",\n \"enum\": [\"item\", \"container\"]\n },\n \"children\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"string\" },\n { \"$ref\": \"#/definitions/ChildFieldConfig\" }\n ]\n },\n \"description\": \"For extractionMethod='structured': child field selectors. Each value is a string shortcut or a ChildFieldConfig object.\"\n }\n }\n }\n }\n }\n },\n \"crawlDepth\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Crawl depth from the seed URL for sync handlers that walk a site's link graph (currently civics — see opuspopuli#669). 0 (default) = no crawl, fetch only the seed. N = N hops from seed. Crawls are scoped to same host + same path prefix as the seed, HTML responses only.\"\n },\n \"crawlMaxPages\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Cap on total pages a crawler will visit per sync run regardless of crawlDepth. Defaults to 20. Each page costs one LLM call, so this bounds runtime + token spend.\"\n },\n \"llmMaxTokens\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Per-source override for the LLM maxTokens generation cap. Useful when a source needs a much longer or shorter output than its siblings (e.g., a 150-term glossary needs ~32000; a short bio prompt finishes well under 2000). Overrides the sync handler's hardcoded default.\"\n },\n \"llmRequestTimeoutMs\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Per-source override for the LLM provider request timeout (milliseconds). Useful when a single source legitimately runs much longer than the platform-wide default — civics-glossary extraction on qwen3.5:9b can take 15-20 min, while bio gen finishes in 2 min on the same hardware. Overrides the provider's constructor-configured default.\"\n }\n }\n },\n \"BulkDownloadConfig\": {\n \"type\": \"object\",\n \"required\": [\"format\", \"columnMappings\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"format\": {\n \"type\": \"string\",\n \"enum\": [\"tsv\", \"csv\", \"zip_tsv\", \"zip_csv\"],\n \"description\": \"File format\"\n },\n \"filePattern\": {\n \"type\": \"string\",\n \"description\": \"For ZIP archives: path/glob of target file(s) within the ZIP\"\n },\n \"delimiter\": {\n \"type\": \"string\",\n \"description\": \"Column delimiter override\"\n },\n \"headerLines\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Number of header lines to skip\"\n },\n \"headers\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Explicit column headers for files without a header row (e.g., FEC bulk files)\"\n },\n \"columnMappings\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Column name mappings: source column name -> domain field name\"\n },\n \"filters\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Filter expressions applied during parse. Values support ${variableName} placeholders that the consumer resolves at runtime from the active local region. Supported variables: ${stateCode} (the 2-letter US state code of the active local region, e.g. 'CA'). Placeholders must appear verbatim. Example: '\\\"STATE\\\": \\\"${stateCode}\\\"' on an FEC bulk filter.\"\n },\n \"batchSize\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Records per batch for streaming processing (default: 10000)\"\n }\n }\n },\n \"ApiSourceConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"method\": {\n \"type\": \"string\",\n \"enum\": [\"GET\", \"POST\"],\n \"description\": \"HTTP method (default: GET)\"\n },\n \"apiKeyEnvVar\": {\n \"type\": \"string\",\n \"description\": \"Environment variable name containing the API key\"\n },\n \"apiKeyHeader\": {\n \"type\": \"string\",\n \"description\": \"Header name for the API key\"\n },\n \"pagination\": {\n \"$ref\": \"#/definitions/ApiPaginationConfig\"\n },\n \"resultsPath\": {\n \"type\": \"string\",\n \"description\": \"JSON path to the items array in the response\"\n },\n \"queryParams\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Query parameters appended to every request. Values support ${variableName} placeholders that the consumer resolves at runtime from the active local region. Supported variables: ${stateCode} (the 2-letter US state code of the active local region, e.g. 'CA'). Placeholders must appear verbatim — no escaping, no nested expressions. Example: '\\\"contributor_state\\\": \\\"${stateCode}\\\"'.\"\n },\n \"fieldMappings\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"description\": \"Field name mappings: API response field -> domain model field (e.g., committee_id -> committeeId)\"\n }\n }\n },\n \"ApiPaginationConfig\": {\n \"type\": \"object\",\n \"required\": [\"type\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"offset\", \"cursor\", \"page\"],\n \"description\": \"Pagination strategy type\"\n },\n \"pageParam\": {\n \"type\": \"string\",\n \"description\": \"Query parameter name for page/offset\"\n },\n \"limitParam\": {\n \"type\": \"string\",\n \"description\": \"Query parameter name for page size\"\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Number of items per page\"\n }\n }\n },\n \"PdfSourceConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"skipPages\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Skip first N pages (e.g., skip cover page)\"\n },\n \"maxPages\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Maximum pages to process (default: all)\"\n },\n \"followPdfLink\": {\n \"type\": \"boolean\",\n \"description\": \"If true, treats the URL as a gateway page and follows the first PDF link\"\n }\n }\n },\n \"StructuredFieldConfig\": {\n \"type\": \"object\",\n \"required\": [\"selector\", \"children\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"selector\": {\n \"type\": \"string\",\n \"description\": \"CSS selector matching each repeating item (e.g., '.office-card')\"\n },\n \"children\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"string\" },\n { \"$ref\": \"#/definitions/ChildFieldConfig\" }\n ]\n },\n \"description\": \"Child field selectors relative to each item. Each entry is either a string shortcut (e.g. 'h3', 'a|attr:href') or a richer ChildFieldConfig object with extractionMethod / regex / transform.\"\n },\n \"multiple\": {\n \"type\": \"boolean\",\n \"description\": \"If true, extracts all matches as an array (default: true)\"\n }\n }\n },\n \"ChildFieldConfig\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Per-child extraction config for structured extraction. Object form supports the same shape as the top-level FieldMapping (selector + extractionMethod + attribute / regex / transform), minus fieldName/required/defaultValue which don't apply at child scope.\",\n \"properties\": {\n \"selector\": {\n \"type\": \"string\",\n \"description\": \"CSS selector relative to the matched parent item. Optional for regex on full element text.\"\n },\n \"extractionMethod\": {\n \"type\": \"string\",\n \"description\": \"How to extract: 'text', 'attribute', 'regex', 'html', etc.\"\n },\n \"attribute\": {\n \"type\": \"string\",\n \"description\": \"For extractionMethod='attribute': which attribute to read (e.g. 'href', 'src').\"\n },\n \"regexPattern\": {\n \"type\": \"string\",\n \"description\": \"For extractionMethod='regex': the pattern.\"\n },\n \"regexGroup\": {\n \"type\": \"integer\",\n \"description\": \"For extractionMethod='regex': capture group (default: 1).\"\n },\n \"transform\": {\n \"type\": \"object\",\n \"description\": \"Optional transform applied after extraction (e.g. trim, regex_replace, url_resolve).\"\n }\n }\n },\n \"BillDiscoveryConfig\": {\n \"type\": \"object\",\n \"required\": [\"navLinkPattern\", \"statusPageTemplate\", \"votesPageTemplate\"],\n \"additionalProperties\": false,\n \"description\": \"Declarative bill discovery for legislature sites that list per-bill nav-hub links on a search results page (e.g. CA leginfo). The bills-ingest handler fetches the seed once, extracts bill IDs with navLinkPattern, and constructs status + votes URLs from the templates — bypassing generic BFS which would exhaust crawlMaxPages with nav-hub links before reaching detail pages.\",\n \"properties\": {\n \"navLinkPattern\": {\n \"type\": \"string\",\n \"description\": \"Regex string applied to the decoded seed-page HTML to extract bill IDs. Capture group 1 must be the bill ID. Example for CA leginfo: \\\"/faces/billNavClient\\\\\\\\.xhtml\\\\\\\\?bill_id=([^\\\\\\\"&\\\\\\\\s]+)\\\"\"\n },\n \"statusPageTemplate\": {\n \"type\": \"string\",\n \"description\": \"URL path + query template for the bill status page. Use {bill_id} as the placeholder; the service prepends the seed origin. Example: \\\"/faces/billStatusClient.xhtml?bill_id={bill_id}\\\"\"\n },\n \"votesPageTemplate\": {\n \"type\": \"string\",\n \"description\": \"URL path + query template for the bill votes page. Same substitution as statusPageTemplate. Example: \\\"/faces/billVotesClient.xhtml?bill_id={bill_id}\\\"\"\n },\n \"textPageTemplate\": {\n \"type\": \"string\",\n \"description\": \"Optional URL path + query template for the bill text page. When set, the sync fetches this page before LLM extraction to check the 'Date Published' timestamp and skip unchanged bills. Example: \\\"/faces/billTextClient.xhtml?bill_id={bill_id}\\\"\"\n }\n }\n },\n \"PdfArchiveConfig\": {\n \"type\": \"object\",\n \"required\": [\"linkSelector\"],\n \"additionalProperties\": false,\n \"description\": \"Listing-walk configuration for sourceType=pdf_archive. The page at `url` is treated as a paginated index of dated PDF documents; each linked PDF is fetched, pdf-parsed, and stored as a Minutes record. Cold-start work is bounded by maxNew (default 10) so first-run sync doesn't ingest years of historical archives. Per-document parsing (text → action records) is a downstream backend pass — this block carries no parser DSL.\",\n \"properties\": {\n \"linkSelector\": {\n \"type\": \"string\",\n \"description\": \"CSS selector for PDF anchor elements on the listing page. Each match yields a candidate document.\"\n },\n \"datePattern\": {\n \"type\": \"string\",\n \"description\": \"Regex applied to the link href (falling back to anchor text) to extract the document's date. Capture groups depend on dateFormat.\"\n },\n \"dateFormat\": {\n \"type\": \"string\",\n \"description\": \"Date format hint for interpreting datePattern's captures. Supported: 'MMDDYY' (3 captures: month, day, two-digit year — assumed 20YY), 'YYYY-MM-DD' (3 captures), 'MM/DD/YYYY' (3 captures).\"\n },\n \"revisionPattern\": {\n \"type\": \"string\",\n \"description\": \"Regex against the link href whose match indicates this URL is a revision. Capture group 1 is the revision sequence number (1, 2, ...). Unmatched URLs are revisionSeq=0.\"\n },\n \"maxPages\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Maximum number of listing pages to walk during one sync cycle. Default: 10.\"\n },\n \"maxNew\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Hard cap on number of new documents ingested per sync cycle. Cold-start protection. Default: 10.\"\n },\n \"paginationParam\": {\n \"type\": \"string\",\n \"description\": \"Query parameter name used to paginate the listing page (e.g., 'page'). Omitted when the listing isn't paginated.\"\n }\n }\n }\n }\n}","/**\n * Pure logic for scaffolding a region config for the\n * [`OpusPopuli/opuspopuli-regions`](https://github.com/OpusPopuli/opuspopuli-regions)\n * repo.\n *\n * Region configs are declarative JSON files validated against\n * `schema/region-plugin.schema.json` in that repo. We vendor a copy of that\n * schema at `./region-schema.json` so the wizard is self-contained and\n * validates against the **canonical contract** rather than a hand-rolled\n * approximation. Anything the schema enforces is enforced here; we layer a\n * small set of cross-field invariants on top that the regions repo's\n * `pnpm test` also checks (e.g. `name === config.regionId`).\n *\n * Everything here is side-effect free and unit tested. The interactive shell\n * and filesystem writes live in `src/commands/region.ts`.\n */\n\n// ESM-native JSON Schema validator. Picked over Ajv 8 because Ajv ships only\n// CJS, which forces a `.default` interop dance under `verbatimModuleSyntax`.\n// `@cfworker/json-schema` is a clean ESM module with no peer dep and supports\n// the Draft 7 / 2019-09 / 2020-12 schemas the regions repo uses.\nimport { Validator, type Schema } from '@cfworker/json-schema';\n\n// Schema imported as JSON so tsup inlines it into the bundle — no need to\n// ship a separate file in dist/.\nimport REGION_SCHEMA from './region-schema.json' with { type: 'json' };\n\n/** `dataType` values the regions schema accepts on a data source. Mirrors the\n * enum block in `region-plugin.schema.json` so the CLI prompt matches. */\nexport const DATA_TYPES = [\n 'propositions',\n 'meetings',\n 'representatives',\n 'campaign_finance',\n 'lobbying',\n 'civics',\n 'bills',\n] as const;\nexport type DataType = (typeof DATA_TYPES)[number];\n\n/** `sourceType` values the regions schema accepts on a data source. */\nexport const SOURCE_TYPES = [\n 'html_scrape',\n 'bulk_download',\n 'api',\n 'pdf',\n 'pdf_archive',\n] as const;\nexport type SourceType = (typeof SOURCE_TYPES)[number];\n\n/** The two region levels this scaffolder authors. `federal` is a singleton that\n * already exists in the regions repo, so it is intentionally not offered. */\nexport type RegionLevel = 'state' | 'county';\n\nexport interface DataSourceInput {\n url: string;\n dataType: DataType;\n sourceType: SourceType;\n contentGoal: string;\n category?: string;\n}\n\nexport interface RegionInput {\n level: RegionLevel;\n /** kebab-case; for a county this is the combined `state-county` id. */\n regionId: string;\n /** kebab-case county slug only — the trailing segment of a county regionId.\n * Required for counties so we never have to re-derive it from string\n * prefixes; ignored for states. */\n countySlug?: string;\n displayName: string;\n regionName: string;\n description: string;\n /** semver, e.g. `0.1.0`. */\n version: string;\n /** IANA tz, e.g. `America/Los_Angeles`. */\n timezone: string;\n /** Two-letter US state code, uppercase. */\n stateCode: string;\n /** 2 digits for a state, 5 digits for a county. */\n fipsCode: string;\n /** kebab-case parent state id; required for counties, omitted for states. */\n parentRegionId?: string;\n dataSources: DataSourceInput[];\n}\n\ninterface DeclarativeRegionConfig {\n regionId: string;\n regionName: string;\n description: string;\n timezone: string;\n stateCode?: string;\n parentRegionId?: string;\n fipsCode?: string;\n dataSources: DataSourceInput[];\n}\n\nexport interface RegionPluginFile {\n name: string;\n displayName: string;\n description: string;\n version: string;\n config: DeclarativeRegionConfig;\n}\n\nexport const SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst STATE_CODE_RE = /^[A-Z]{2}$/;\n\n/** Lower-cases, strips accents, and collapses anything non-alphanumeric into\n * single hyphens — turning \"Los Angeles County\" into \"los-angeles\". */\nexport function slugify(input: string): string {\n return input\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n // The collapse above leaves at most a single hyphen at each edge, so a\n // quantifier-free `^-|-$` trim is equivalent to `^-+|-+$` and can't\n // backtrack super-linearly.\n .replace(/^-|-$/g, '');\n}\n\nexport function isValidSlug(v: string): boolean {\n return SLUG_RE.test(v);\n}\n\nexport function isValidStateCode(v: string): boolean {\n return STATE_CODE_RE.test(v);\n}\n\n/** A state FIPS is exactly 2 digits; a county FIPS is exactly 5 (state prefix +\n * 3-digit county). */\nexport function isValidFips(v: string, level: RegionLevel): boolean {\n return level === 'state' ? /^\\d{2}$/.test(v) : /^\\d{5}$/.test(v);\n}\n\n/** Set of IANA zone names on this runtime, or `null` if the host VM doesn't\n * expose `Intl.supportedValuesOf` (in which case callers should skip the\n * membership check rather than reject everything). */\nfunction supportedTimeZones(): Set<string> | null {\n const intl = Intl as typeof Intl & {\n supportedValuesOf?: (key: string) => string[];\n };\n if (typeof intl.supportedValuesOf !== 'function') return null;\n try {\n return new Set(intl.supportedValuesOf('timeZone'));\n } catch {\n return null;\n }\n}\n\nexport function isValidTimezone(v: string): boolean {\n if (!v.includes('/')) return false;\n const zones = supportedTimeZones();\n // If the runtime can't enumerate zones, fall back to a shape check so we\n // don't reject a perfectly good \"Region/City\" string.\n return zones ? zones.has(v) : true;\n}\n\n/**\n * Build the `RegionPluginFile` object from collected input. Optional config\n * fields are only set when present so the JSON stays minimal and we don't trip\n * the schema's `additionalProperties: false` / `exactOptionalPropertyTypes`.\n */\nexport function buildRegionConfig(input: RegionInput): RegionPluginFile {\n const config: DeclarativeRegionConfig = {\n // The regions repo requires `name === config.regionId`; we tie them\n // together at construction so they can never drift.\n regionId: input.regionId,\n regionName: input.regionName,\n description: input.description,\n timezone: input.timezone,\n stateCode: input.stateCode,\n fipsCode: input.fipsCode,\n dataSources: input.dataSources.map(normalizeDataSource),\n };\n if (input.parentRegionId) {\n config.parentRegionId = input.parentRegionId;\n }\n\n return {\n name: input.regionId,\n displayName: input.displayName,\n description: input.description,\n version: input.version,\n config,\n };\n}\n\nfunction normalizeDataSource(src: DataSourceInput): DataSourceInput {\n const out: DataSourceInput = {\n url: src.url,\n dataType: src.dataType,\n sourceType: src.sourceType,\n contentGoal: src.contentGoal,\n };\n if (src.category) out.category = src.category;\n return out;\n}\n\n/**\n * Canonical path of a region file inside the regions repo, relative to the repo\n * root:\n * state → `regions/<state>/<state>.json`\n * county → `regions/<state>/counties/<county>/<county>.json`\n *\n * Counties pass `countySlug` explicitly so we never have to back out a slug\n * from a string prefix — important when a parent state slug contains a hyphen\n * (`new-jersey-cumberland` shouldn't be sliced on the first `-`).\n */\nexport function regionFilePath(input: {\n level: RegionLevel;\n regionId: string;\n parentRegionId?: string;\n countySlug?: string;\n}): string {\n if (input.level === 'state') {\n return `regions/${input.regionId}/${input.regionId}.json`;\n }\n const parent = input.parentRegionId;\n const countySlug = input.countySlug;\n if (!parent || !countySlug) {\n throw new Error(\n 'regionFilePath: county requires both parentRegionId and countySlug',\n );\n }\n return `regions/${parent}/counties/${countySlug}/${countySlug}.json`;\n}\n\n// ---------------------------------------------------------------------------\n// Schema-based validation (single source of truth)\n// ---------------------------------------------------------------------------\n\n// The JSON import resolves to a narrower literal type than `Schema` accepts\n// (e.g. `type: \"object\"` as a string literal vs the union enum). The cast is\n// a TS-only widening — runtime data is unchanged.\nconst schemaValidator = new Validator(REGION_SCHEMA as unknown as Schema, '7');\n\n/**\n * Re-check the invariants the regions repo enforces in CI, returning a list of\n * human-readable problems (empty means valid). Two layers:\n *\n * 1. **JSON Schema** — run the vendored `region-plugin.schema.json` (the same\n * file `pnpm test` validates against). Catches every structural rule the\n * schema declares.\n * 2. **Cross-field invariants** — checks the regions repo enforces in custom\n * test code that don't live in the schema: `name === config.regionId`,\n * county regionId prefixed by its parent, no duplicate data sources keyed by\n * `(dataType, url)`.\n */\nexport function validateRegionConfig(file: RegionPluginFile): string[] {\n // Cross-field invariants run first so their human-friendlier messages\n // (\"not a valid semver\", \"must be 5 digits for a county\", \"name mismatch\")\n // surface ahead of the corresponding raw Ajv pattern errors. Order of the\n // groups here IS the order issues are reported in.\n return [\n ...validateVersionAndIds(file),\n ...validateFipsCode(file),\n ...validateDataSourceUniqueness(file),\n ...validateAgainstSchema(file),\n ];\n}\n\n// version semver + name/regionId agreement + kebab-case + county prefix.\nfunction validateVersionAndIds(file: RegionPluginFile): string[] {\n const issues: string[] = [];\n const { config } = file;\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(file.version)) {\n issues.push(`version \"${file.version}\" is not a valid semver (expected MAJOR.MINOR.PATCH)`);\n }\n if (file.name !== config.regionId) {\n issues.push(`name \"${file.name}\" must equal config.regionId \"${config.regionId}\"`);\n }\n if (!isValidSlug(config.regionId)) {\n issues.push(`regionId \"${config.regionId}\" must be kebab-case`);\n }\n if (\n config.parentRegionId !== undefined &&\n !config.regionId.startsWith(`${config.parentRegionId}-`)\n ) {\n issues.push(\n `county regionId \"${config.regionId}\" should be prefixed with its parent \"${config.parentRegionId}-\"`,\n );\n }\n return issues;\n}\n\n// The JSON schema only checks the FIPS shape (2–7 digits). Per-level lengths\n// (\"2 for state, 5 for county\") are a cross-field rule the regions repo\n// enforces in custom test code — re-checked here.\nfunction validateFipsCode(file: RegionPluginFile): string[] {\n const { config } = file;\n if (config.fipsCode === undefined) return [];\n const isCounty = config.parentRegionId !== undefined;\n const expected = isCounty ? 5 : 2;\n if (!/^\\d+$/.test(config.fipsCode) || config.fipsCode.length !== expected) {\n return [\n `fipsCode \"${config.fipsCode}\" must be ${expected} digits for a ${isCounty ? 'county' : 'state'}`,\n ];\n }\n return [];\n}\n\n// dataSources is required by the schema — if it's missing the schema layer\n// below will flag that, so we just skip the duplicate scan here rather than\n// throwing on a malformed-but-not-yet-validated file.\nfunction validateDataSourceUniqueness(file: RegionPluginFile): string[] {\n const { config } = file;\n if (!Array.isArray(config.dataSources)) return [];\n const issues: string[] = [];\n const seen = new Set<string>();\n for (const src of config.dataSources) {\n const key = `${src.dataType} ${src.url}`;\n if (seen.has(key)) {\n issues.push(`duplicate data source: ${src.dataType} ${src.url}`);\n }\n seen.add(key);\n }\n return issues;\n}\n\n// Layer the schema on last — catches anything the friendly checks didn't\n// pre-empt (missing required fields, wrong types, unknown extras, etc.).\nfunction validateAgainstSchema(file: RegionPluginFile): string[] {\n const result = schemaValidator.validate(file);\n if (result.valid) return [];\n return result.errors.map((err) => `schema: ${err.instanceLocation || '<root>'} ${err.error}`);\n}\n","import { mkdir, writeFile, access } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\n\nimport { Command, Option } from 'commander';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\nimport {\n DATA_TYPES,\n SOURCE_TYPES,\n buildRegionConfig,\n isValidFips,\n isValidSlug,\n isValidStateCode,\n isValidTimezone,\n regionFilePath,\n slugify,\n validateRegionConfig,\n type DataSourceInput,\n type DataType,\n type RegionInput,\n type RegionLevel,\n type RegionPluginFile,\n type SourceType,\n} from '../lib/region.js';\nimport { unwrap } from '../lib/prompts.js';\n\ninterface RegionOptions {\n level?: string;\n name?: string;\n parent?: string;\n stateCode?: string;\n fips?: string;\n timezone?: string;\n outDir?: string;\n force?: boolean;\n}\n\nexport const regionCommand = new Command('region')\n .description(\n 'Scaffold a schema-valid region config for the OpusPopuli/opuspopuli-regions repo. ' +\n 'Run this from inside your checkout of that repo.',\n )\n .addOption(\n new Option('--level <level>', 'Region level').choices(['state', 'county']),\n )\n .addOption(new Option('--name <name>', 'Region name (e.g. \"California\" or \"Alameda\")'))\n .addOption(\n new Option('--parent <slug>', 'Parent state slug for a county (e.g. california)'),\n )\n .addOption(new Option('--state-code <code>', 'Two-letter US state code (e.g. CA)'))\n .addOption(new Option('--fips <code>', 'FIPS code (2 digits state, 5 digits county)'))\n .addOption(new Option('--timezone <tz>', 'IANA timezone (e.g. America/Los_Angeles)'))\n .addOption(\n new Option('--out-dir <dir>', 'Repo root to write under').default(\n process.cwd(),\n 'current directory',\n ),\n )\n .addOption(new Option('-f, --force', 'Overwrite an existing config file').default(false))\n .action(async (opts: RegionOptions) => {\n p.intro(pc.bgMagenta(pc.black(' create-op-node region ')));\n printRegionWelcome();\n\n const targetDir = await resolveTargetDir(opts);\n const level = await resolveLevel(opts);\n const identity = await collectIdentity(opts, level);\n const codes = await collectCodes(opts, level);\n const dataSources = await collectDataSources();\n\n const input = buildRegionInput({ level, identity, codes, dataSources });\n const file = buildAndValidateConfig(input);\n await writeRegionConfig({ opts, targetDir, level, identity, file });\n });\n\n// ----------------------------------------------------------------------------\n// Region wizard steps\n// ----------------------------------------------------------------------------\n// The action delegates to these so no single function exceeds the\n// cognitive-complexity budget. Behavior-preserving: prompts, validation, and\n// process.exit calls are relocated verbatim.\n\ninterface RegionIdentity {\n rawName: string;\n parentSlug: string | undefined;\n ownSlug: string;\n regionId: string;\n regionName: string;\n description: string;\n}\n\ninterface RegionCodes {\n stateCode: string;\n fipsCode: string;\n timezone: string;\n}\n\nconst requireNonEmpty = (v: string | undefined): string | undefined =>\n v && v.trim().length > 0 ? undefined : 'Required';\n\nfunction printRegionWelcome(): void {\n p.note(\n [\n 'Scaffolds a declarative region config JSON for opuspopuli-regions —',\n 'the file that defines WHAT civic data a region collects.',\n '',\n pc.dim('Run this from the root of your opuspopuli-regions checkout.'),\n pc.dim('It validates the same invariants the repo’s `pnpm test` enforces,'),\n pc.dim('so the file lands green and you just commit + open a PR.'),\n ].join('\\n'),\n 'Welcome',\n );\n}\n\n// ---- Step 0: sanity-check we're inside an opuspopuli-regions checkout ----\nasync function resolveTargetDir(opts: RegionOptions): Promise<string> {\n const targetDir = opts.outDir ?? process.cwd();\n const looksRight = await looksLikeRegionsRepo(targetDir);\n if (!looksRight) {\n const proceed = unwrap(\n await p.confirm({\n message: `${targetDir} doesn't look like an opuspopuli-regions checkout (no schema/region-plugin.schema.json). Continue anyway?`,\n initialValue: false,\n }),\n );\n if (!proceed) {\n p.cancel('Cancelled — run again from your opuspopuli-regions checkout, or pass --out-dir.');\n process.exit(0);\n }\n }\n return targetDir;\n}\n\n// ---- Step 1: level ----\nasync function resolveLevel(opts: RegionOptions): Promise<RegionLevel> {\n return opts.level === 'state' || opts.level === 'county'\n ? opts.level\n : unwrap(\n await p.select({\n message: 'What level is this region?',\n options: [\n { value: 'state', label: 'State', hint: 'e.g. California' },\n { value: 'county', label: 'County', hint: 'e.g. Alameda, within California' },\n ],\n }),\n );\n}\n\n// Parent state slug — only prompted for counties.\nasync function resolveParentSlug(opts: RegionOptions, level: RegionLevel): Promise<string | undefined> {\n if (level !== 'county') return undefined;\n const parentSlug =\n opts.parent ??\n unwrap(\n await p.text({\n message: 'Parent state slug?',\n placeholder: 'california',\n validate: (v) =>\n isValidSlug(v ?? '') ? undefined : 'kebab-case (lowercase letters, digits, hyphens)',\n }),\n );\n if (!isValidSlug(parentSlug)) {\n p.cancel(`Parent slug \"${parentSlug}\" must be kebab-case.`);\n process.exit(1);\n }\n return parentSlug;\n}\n\n// ---- Step 2: identity (name, slug, parent, display, description) ----\nasync function collectIdentity(opts: RegionOptions, level: RegionLevel): Promise<RegionIdentity> {\n const rawName =\n opts.name ??\n unwrap(\n await p.text({\n message: level === 'county' ? 'County name?' : 'State name?',\n placeholder: level === 'county' ? 'Alameda' : 'California',\n validate: requireNonEmpty,\n }),\n );\n\n const parentSlug = await resolveParentSlug(opts, level);\n\n const ownSlug = slugify(rawName);\n const regionId = level === 'county' ? `${parentSlug}-${ownSlug}` : ownSlug;\n if (!isValidSlug(regionId)) {\n p.cancel(`Derived regionId \"${regionId}\" is not valid kebab-case. Try a simpler name.`);\n process.exit(1);\n }\n\n const displayName = unwrap(\n await p.text({\n message: 'Display name?',\n defaultValue: rawName,\n }),\n );\n const regionName = displayName || rawName;\n\n const description = unwrap(\n await p.text({\n message: 'One-line description of the data coverage?',\n placeholder:\n level === 'county'\n ? `Civic data for ${rawName} County`\n : `Civic data for the state of ${rawName}`,\n validate: requireNonEmpty,\n }),\n );\n\n return { rawName, parentSlug, ownSlug, regionId, regionName, description };\n}\n\n// ---- Step 3: codes (state code, FIPS, timezone) ----\nasync function collectCodes(opts: RegionOptions, level: RegionLevel): Promise<RegionCodes> {\n const stateCode = (\n opts.stateCode ??\n unwrap(\n await p.text({\n message: 'Two-letter state code?',\n placeholder: 'CA',\n validate: (v) =>\n isValidStateCode((v ?? '').toUpperCase()) ? undefined : 'Two letters, e.g. CA',\n }),\n )\n ).toUpperCase();\n if (!isValidStateCode(stateCode)) {\n p.cancel(`State code \"${stateCode}\" must be two letters.`);\n process.exit(1);\n }\n\n const fipsCode =\n opts.fips ??\n unwrap(\n await p.text({\n message: level === 'county' ? 'County FIPS (5 digits)?' : 'State FIPS (2 digits)?',\n placeholder: level === 'county' ? '06001' : '06',\n validate: (v) => {\n if (isValidFips(v ?? '', level)) return undefined;\n const expectedDigits = level === 'county' ? '5' : '2';\n return `Expected ${expectedDigits} digits`;\n },\n }),\n );\n if (!isValidFips(fipsCode, level)) {\n p.cancel(`FIPS \"${fipsCode}\" is the wrong length for a ${level}.`);\n process.exit(1);\n }\n\n const timezone =\n opts.timezone ??\n unwrap(\n await p.text({\n message: 'IANA timezone?',\n defaultValue: 'America/Los_Angeles',\n placeholder: 'America/Los_Angeles',\n validate: (v) =>\n isValidTimezone(v || 'America/Los_Angeles')\n ? undefined\n : 'Not a recognized IANA zone (e.g. America/New_York)',\n }),\n );\n\n return { stateCode, fipsCode, timezone };\n}\n\n// ---- Step 4: at least one data source ----\nasync function collectOneDataSource(index: number): Promise<DataSourceInput> {\n const url = unwrap(\n await p.text({\n message: `Data source #${index} — URL?`,\n placeholder: 'https://example.gov/meetings',\n validate: (v) => (/^https?:\\/\\//.test(v ?? '') ? undefined : 'Must start with http(s)://'),\n }),\n );\n const dataType = unwrap(\n await p.select({\n message: 'Data type?',\n options: DATA_TYPES.map((t) => ({ value: t, label: t })),\n }),\n ) as DataType;\n const sourceType = unwrap(\n await p.select({\n message: 'Source type?',\n initialValue: 'html_scrape' as SourceType,\n options: SOURCE_TYPES.map((t) => ({ value: t, label: t })),\n }),\n ) as SourceType;\n const contentGoal = unwrap(\n await p.text({\n message: 'Content goal (what should the scraper extract)?',\n placeholder: 'Fetch upcoming board meeting agendas and minutes',\n validate: requireNonEmpty,\n }),\n );\n const category = unwrap(\n await p.text({\n message: 'Category label (optional)?',\n placeholder: 'Board of Supervisors',\n }),\n );\n\n const src: DataSourceInput = { url, dataType, sourceType, contentGoal };\n if (category && category.trim().length > 0) src.category = category.trim();\n return src;\n}\n\nasync function collectDataSources(): Promise<DataSourceInput[]> {\n const dataSources: DataSourceInput[] = [];\n do {\n dataSources.push(await collectOneDataSource(dataSources.length + 1));\n const again = unwrap(\n await p.confirm({ message: 'Add another data source?', initialValue: false }),\n );\n if (!again) break;\n // eslint-disable-next-line no-constant-condition\n } while (true);\n return dataSources;\n}\n\n// ---- Step 5: build the RegionInput from the collected answers ----\nexport function buildRegionInput(args: {\n level: RegionLevel;\n identity: RegionIdentity;\n codes: RegionCodes;\n dataSources: DataSourceInput[];\n}): RegionInput {\n const { level, identity, codes, dataSources } = args;\n return {\n level,\n regionId: identity.regionId,\n displayName: identity.regionName,\n regionName: identity.regionName,\n description: identity.description,\n // New region configs start at 0.1.0 — the documented convention in the\n // regions repo's CLAUDE.md. Bump manually as the config matures.\n version: '0.1.0',\n timezone: codes.timezone,\n stateCode: codes.stateCode,\n fipsCode: codes.fipsCode,\n dataSources,\n ...(identity.parentSlug ? { parentRegionId: identity.parentSlug } : {}),\n ...(level === 'county' ? { countySlug: identity.ownSlug } : {}),\n };\n}\n\n// Build + validate the config; exits if the generated file would fail CI.\nfunction buildAndValidateConfig(input: RegionInput): RegionPluginFile {\n const file = buildRegionConfig(input);\n const issues = validateRegionConfig(file);\n if (issues.length > 0) {\n p.note(issues.map((i) => `${pc.red('•')} ${i}`).join('\\n'), 'Validation failed');\n p.cancel('The generated config would not pass the regions repo CI. Re-run and adjust.');\n process.exit(1);\n }\n return file;\n}\n\n// ---- Step 6: preview + write ----\nasync function writeRegionConfig(args: {\n opts: RegionOptions;\n targetDir: string;\n level: RegionLevel;\n identity: RegionIdentity;\n file: RegionPluginFile;\n}): Promise<void> {\n const { opts, targetDir, level, identity, file } = args;\n const relPath = regionFilePath({\n level,\n regionId: identity.regionId,\n ...(identity.parentSlug ? { parentRegionId: identity.parentSlug } : {}),\n ...(level === 'county' ? { countySlug: identity.ownSlug } : {}),\n });\n const absPath = resolve(targetDir, relPath);\n const json = `${JSON.stringify(file, null, 2)}\\n`;\n\n p.note(json, `${relPath} (preview)`);\n\n if (!opts.force && (await fileExists(absPath))) {\n p.cancel(`${relPath} already exists. Re-run with --force to overwrite.`);\n process.exit(1);\n }\n\n const write = unwrap(\n await p.confirm({ message: `Write ${relPath}?`, initialValue: true }),\n );\n if (!write) {\n p.cancel('Nothing written.');\n process.exit(0);\n }\n\n await mkdir(dirname(absPath), { recursive: true });\n await writeFile(absPath, json, 'utf8');\n\n p.note(\n [\n `${pc.green('✓')} Wrote ${pc.cyan(relPath)}`,\n '',\n 'Next steps in your opuspopuli-regions checkout:',\n pc.dim(' pnpm test # schema + hierarchy validation'),\n pc.dim(' pnpm test:connectivity # URL reachability (informational)'),\n pc.dim(` git add ${relPath} && git commit && open a PR`),\n ].join('\\n'),\n 'Done',\n );\n p.outro(pc.magenta(`Region scaffolded: ${identity.regionId}`));\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Heuristic: the regions repo always has `schema/region-plugin.schema.json`\n * and a top-level `regions/` directory. If both are present we're confident\n * we're in the right checkout; if neither we warn before writing anywhere. */\nasync function looksLikeRegionsRepo(dir: string): Promise<boolean> {\n const [hasSchema, hasRegions] = await Promise.all([\n fileExists(join(dir, 'schema', 'region-plugin.schema.json')),\n fileExists(join(dir, 'regions')),\n ]);\n return hasSchema && hasRegions;\n}\n","import { Command } from 'commander';\nimport pc from 'picocolors';\n\nimport { initCommand } from './commands/init.js';\nimport { bootstrapCommand } from './commands/bootstrap.js';\nimport { resetCommand } from './commands/reset.js';\nimport { verifyCommand } from './commands/verify.js';\nimport { regionCommand } from './commands/region.js';\n\n// release-please updates the string in `const VERSION = '...'` on each\n// release. See release-please-config.json's extra-files entry that points\n// at this file with type: generic — that scanner finds the version string\n// in package.json (via the manifest file) and updates literals on lines\n// like the one below.\n// x-release-please-start-version\nconst VERSION = '0.10.13';\n// x-release-please-end\n\nconst program = new Command();\n\nprogram\n .name('create-op-node')\n .description(\n 'Interactive bootstrap for an Opus Populi federation node.\\n' +\n 'Cloudflare infrastructure → Mac Studio → live public API.',\n )\n .version(VERSION, '-v, --version', 'show version');\n\nprogram.addCommand(initCommand);\nprogram.addCommand(bootstrapCommand);\nprogram.addCommand(resetCommand);\nprogram.addCommand(verifyCommand);\nprogram.addCommand(regionCommand);\n\n// When invoked with no subcommand, default to `init` — the create-* convention\n// is that `npx create-op-node` \"just works\" without specifying a subcommand.\nif (process.argv.length === 2) {\n process.argv.push('init');\n}\n\nawait program.parseAsync(process.argv).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`\\n${pc.red('✗')} ${msg}\\n`);\n process.exit(1);\n});\n"]}
|