@zitadel/cli 0.3.0 → 0.4.0
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/README.md +39 -0
- package/dist/index.mjs +1450 -1047
- package/dist/index.mjs.map +1 -1
- package/dist/lib/oclif/help.mjs +3 -2
- package/dist/lib/oclif/help.mjs.map +1 -1
- package/dist/skills/zitadel/SKILL.md +111 -0
- package/dist/skills/zitadel-cli/SKILL.md +635 -0
- package/dist/skills/zitadel-cli/references/driving-login-ui.md +124 -0
- package/dist/skills/zitadel-components/SKILL.md +152 -0
- package/dist/skills/zitadel-sdk-angular/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-next/SKILL.md +174 -0
- package/dist/skills/zitadel-sdk-nuxt/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-qwik/SKILL.md +136 -0
- package/dist/skills/zitadel-sdk-qwik-router/SKILL.md +126 -0
- package/dist/skills/zitadel-sdk-react/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-solid/SKILL.md +144 -0
- package/dist/skills/zitadel-sdk-solid-start/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-svelte/SKILL.md +137 -0
- package/dist/skills/zitadel-sdk-sveltekit/SKILL.md +147 -0
- package/dist/skills/zitadel-sdk-tanstack-start/SKILL.md +150 -0
- package/dist/skills/zitadel-sdk-vue/SKILL.md +147 -0
- package/dist/{skills-hint-N1H5-ny1.mjs → skills-hint-C8oe8cCo.mjs} +1446 -231
- package/dist/skills-hint-C8oe8cCo.mjs.map +1 -0
- package/oclif.manifest.json +102 -3
- package/package.json +8 -5
- package/skills/zitadel-cli/SKILL.md +62 -9
- package/dist/skills-hint-N1H5-ny1.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills-hint-N1H5-ny1.mjs","names":["isObject","isErrno","createZitadelClient","createRawClient","isObject","isObject","DISABLED_VALUES","isObject","isObject","steps","isErrno","isObject","isObject","isErrno","PublishPolicyBodySchema","body"],"sources":["../src/lib/errors.ts","../src/lib/interrupt.ts","../src/lib/api-client.ts","../src/lib/json.ts","../src/lib/oclif/crud/paging.ts","../src/lib/public-cli.ts","../src/lib/suggestion.ts","../src/lib/telemetry/dimensions/env-flag.ts","../src/lib/telemetry/consent.ts","../src/lib/telemetry/identity.ts","../src/lib/telemetry/dimensions/ci-provider.ts","../src/lib/telemetry/dimensions/host-agent.ts","../src/lib/user-agent.ts","../src/lib/warnings.ts","../src/lib/variables.ts","../src/lib/flows/env-refs.ts","../src/lib/flows/sign-in.ts","../src/lib/flows/index.ts","../src/lib/idp/connections.ts","../src/lib/idp/documents.ts","../src/lib/idp/custom.ts","../src/lib/idp/endpoints.ts","../src/lib/idp/credentials.ts","../src/lib/user-schema/index.ts","../src/lib/idp/schemas.ts","../src/lib/oclif/groups.ts","../src/lib/local-files.ts","../src/lib/branding/index.ts","../src/lib/json-dir.ts","../src/lib/policies/index.ts","../src/lib/release/bundle.ts","../src/lib/release/deployment.ts","../src/lib/release/git.ts","../src/lib/release/steps/asset-probe.ts","../src/lib/release/steps/idp-checks.ts","../src/lib/release/steps/sso-consistency.ts","../src/lib/release/steps/validate.ts","../src/lib/release/steps/diff.ts","../src/lib/release/index.ts","../src/lib/box.ts","../src/lib/journey-guidance.ts","../src/lib/skills-hint.ts"],"sourcesContent":["import { ApiError, apiErrorCode, apiErrorMessage, NetworkError } from \"@zitadel/api/runtime/fetch\";\nimport type { SuggestedCommand } from \"./suggestion\";\n\n/**\n * Closed set of failure categories the CLI can surface. Every error the\n * user sees is funnelled into one of these so messaging, exit codes, and\n * machine-readable output stay consistent regardless of where the failure\n * originated.\n */\nexport type ZitadelErrorCode =\n | \"E_ALREADY_INIT\"\n | \"E_FRAMEWORK_NOT_DETECTED\"\n | \"E_UNSUPPORTED_PROJECT_SHAPE\"\n | \"E_NETWORK\"\n | \"E_AUTH\"\n | \"E_CONFLICT\"\n | \"E_LOCAL_SERVER_NOT_RUNNING\"\n | \"E_NOT_FOUND\"\n | \"E_PORT_IN_USE\"\n | \"E_VALIDATION\"\n | \"E_CREDENTIAL_MISSING\"\n | \"E_NOT_IMPLEMENTED\"\n | \"E_CANCELLED\";\n\n/**\n * Maps each {@link ZitadelErrorCode} to the process exit code the CLI\n * returns. The table is the single source of truth for exit semantics so\n * scripts and CI can branch on stable, documented numbers.\n */\nexport const EXIT_CODES: Record<ZitadelErrorCode, number> = {\n E_ALREADY_INIT: 0,\n E_FRAMEWORK_NOT_DETECTED: 3,\n E_UNSUPPORTED_PROJECT_SHAPE: 3,\n E_NETWORK: 4,\n E_AUTH: 1,\n E_CONFLICT: 5,\n E_LOCAL_SERVER_NOT_RUNNING: 4,\n E_NOT_FOUND: 4,\n E_PORT_IN_USE: 5,\n E_VALIDATION: 3,\n E_CREDENTIAL_MISSING: 3,\n E_NOT_IMPLEMENTED: 2,\n // 128 + SIGINT, what a shell reports for a command stopped by Ctrl-C.\n E_CANCELLED: 130,\n};\n\n/**\n * Optional, user-facing extras attached to a {@link ZitadelError}. Kept\n * separate from the message so the renderer can present a hint, suggested\n * follow-up commands, and structured details independently (e.g. as JSON\n * fields) rather than concatenating everything into one string.\n */\nexport type ZitadelErrorOptions = {\n hint?: string;\n /** Built by the `lib/suggestion` builders, so a project command keeps its selector. */\n nextCommands?: readonly SuggestedCommand[];\n details?: unknown;\n};\n\n/**\n * The CLI's single error type. Carries a {@link ZitadelErrorCode} so the\n * top-level handler can derive an exit code and structured output without\n * pattern-matching on messages. Throwing this anywhere guarantees the user\n * gets a categorised, hint-bearing failure instead of a raw stack trace.\n */\nexport class ZitadelError extends Error {\n readonly code: ZitadelErrorCode;\n readonly hint?: string;\n readonly nextCommands?: readonly SuggestedCommand[];\n readonly details?: unknown;\n\n constructor(code: ZitadelErrorCode, message: string, opts: ZitadelErrorOptions = {}) {\n super(message);\n this.name = \"ZitadelError\";\n this.code = code;\n this.hint = opts.hint;\n this.nextCommands = opts.nextCommands;\n this.details = opts.details;\n }\n\n get exitCode(): number {\n return EXIT_CODES[this.code] ?? 1;\n }\n}\n\n/**\n * Normalises any thrown value into a {@link ZitadelError}. Inspection is\n * ordered most-specific-first (already-normalised, HTTP status, then\n * errno/filesystem, no response, Zod-like, generic `Error`, then a\n * catch-all) so the most actionable category and hint win. A cancelled\n * request arrives already normalised, as the `E_CANCELLED` error that\n * `./interrupt` aborts it with. This is the boundary that lets the rest\n * of the CLI `throw` plain errors yet still produce consistent, categorised\n * output. The original error shape is preserved under `details` for\n * debugging without leaking it into the user-facing message.\n */\nexport function toZitadelError(error: unknown): ZitadelError {\n if (error instanceof ZitadelError) {\n return error;\n }\n\n if (error instanceof ApiError) {\n // `401`/`403` → bad or missing project secret; `404` → something is\n // missing (see below); `5xx` → transport or server fault; everything\n // else 4xx → the body the CLI sent was rejected (validation, conflict, …).\n const details = { status: error.status, url: error.url, body: error.body };\n if (error.status === 404) {\n // A 404 carrying the platform's error envelope (a `code` field) is a\n // domain-level miss from a real Zitadel API — an unknown schema or\n // project id — except `req.not_found`, which the server answers for a\n // path no operation of its version has (ADR 076). Without the envelope\n // the endpoint itself is missing: the CLI is pointed at a server that\n // isn't a Zitadel platform API.\n if (apiErrorCode(error) === \"req.not_found\") {\n return new ZitadelError(\n \"E_NOT_FOUND\",\n `${error.url} has no such endpoint on this Zitadel server`,\n {\n hint: \"The server and this CLI are different versions. Run the CLI release that matches the server, or upgrade the server.\",\n details,\n },\n );\n }\n const wrongServer = !isPlatformErrorEnvelope(error.body);\n const message = wrongServer\n ? `${apiErrorMessage(error)} — ${error.url} has no such endpoint; is this a Zitadel platform API?`\n : apiErrorMessage(error);\n return new ZitadelError(\"E_NOT_FOUND\", message, { details });\n }\n // A 409 is the platform refusing because of the state it holds — a\n // release still served, a deploy that raced in, a revoked release — not\n // because the request was malformed, so it is a conflict.\n // A 403 naming an origin the project does not hold is a refused target,\n // not a bad credential: re-authenticating would never fix it.\n const originRefused =\n error.status === 403 &&\n (error.body as { code?: unknown } | undefined)?.code === \"proj.origin_not_allowed\";\n const code: ZitadelErrorCode = originRefused\n ? \"E_VALIDATION\"\n : error.status === 401 || error.status === 403\n ? \"E_AUTH\"\n : error.status === 409\n ? \"E_CONFLICT\"\n : error.status >= 500\n ? \"E_NETWORK\"\n : \"E_VALIDATION\";\n // The platform names the fields it rejected, and the message does not\n // repeat them: `idp.field_immutable` says only \"the field is fixed for the\n // life of the connection\", which leaves the reader to guess which of a\n // connection document's fields it meant. Promoting them to the hint puts\n // the answer where the failure is read, not only in `--json`. The same\n // goes for what a refusal says is missing: `idp.endpoints_partial` names\n // the endpoints a connection left out only in `missing`.\n const fields = listedInDetails(error.body, \"fields\");\n const missing = listedInDetails(error.body, \"missing\");\n const hint = [\n ...(fields.length > 0\n ? [\n `The server rejected ${fields.length === 1 ? \"this field\" : \"these fields\"}: ${fields.join(\", \")}.`,\n ]\n : []),\n ...(missing.length > 0\n ? [\n `The server reports ${missing.length === 1 ? \"this endpoint\" : \"these endpoints\"} missing: ${missing.join(\", \")}.`,\n ]\n : []),\n ].join(\" \");\n return new ZitadelError(code, apiErrorMessage(error), {\n ...(hint !== \"\" ? { hint } : {}),\n details,\n });\n }\n\n if (isErrnoException(error)) {\n const details = { original: pickErrorShape(error) };\n if (error.code === \"EACCES\" || error.code === \"EPERM\") {\n return new ZitadelError(\"E_AUTH\", `Permission denied: ${error.message}`, {\n hint: \"Check file permissions or run with the right user.\",\n details,\n });\n }\n if (error.code === \"EEXIST\") {\n return new ZitadelError(\"E_CONFLICT\", error.message, {\n hint: \"A file already exists. Use --force to overwrite or remove it first.\",\n details,\n });\n }\n if (error.code === \"ENOENT\") {\n return new ZitadelError(\"E_VALIDATION\", error.message, {\n hint: \"A required file or directory is missing.\",\n details,\n });\n }\n }\n\n if (error instanceof NetworkError) {\n return new ZitadelError(\"E_NETWORK\", error.message, {\n hint:\n error.reason === \"timeout\"\n ? \"The server accepted the connection but did not answer in time. Check that it is healthy, then retry.\"\n : \"Check your connection and the server URL (ZITADEL_URL or --server).\",\n details: { url: error.url, reason: error.reason },\n });\n }\n\n if (isZodLikeError(error)) {\n return new ZitadelError(\"E_VALIDATION\", errorMessage(error), {\n details: { issues: (error as { issues: unknown }).issues },\n });\n }\n\n if (error instanceof Error) {\n return new ZitadelError(\"E_VALIDATION\", error.message, {\n details: { original: pickErrorShape(error) },\n });\n }\n\n return new ZitadelError(\"E_VALIDATION\", \"Unknown error\", { details: error });\n}\n\n/**\n * True when a response body looks like the platform's structured error\n * envelope (`{ code, message, … }`). Its presence proves the request reached\n * a real Zitadel platform API rather than an arbitrary HTTP server.\n */\n/**\n * The names a platform error envelope lists under `key`, if any: the dotted\n * field paths it blames (`fields`), or what it reports missing (`missing`).\n *\n * The envelope nests them under `details`, and the server wraps its own\n * `details` map in the response's `details` field, so the names arrive at\n * `body.details.details.<key>`. Both depths are read: the extra wrapper is\n * the serialiser's doing rather than part of the contract, and a reader that\n * insisted on it would go silent the day it goes away.\n */\nfunction listedInDetails(body: unknown, key: \"fields\" | \"missing\"): string[] {\n const seen = new Set<string>();\n let node: unknown = body;\n for (let depth = 0; depth < 4 && isObject(node); depth += 1) {\n const listed = (node as Record<string, unknown>)[key];\n if (Array.isArray(listed)) {\n for (const name of listed) {\n if (typeof name === \"string\" && name !== \"\") seen.add(name);\n }\n }\n node = (node as { details?: unknown }).details;\n }\n return [...seen];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Whether a request reached a server that has no such endpoint: a 404 without\n * the platform's error envelope. A Zitadel API answers a miss it knows about\n * with the envelope, so this is a route the server does not serve, such as one\n * added in a later release.\n */\nexport function isMissingEndpoint(error: unknown): boolean {\n return error instanceof ApiError && error.status === 404 && !isPlatformErrorEnvelope(error.body);\n}\n\nfunction isPlatformErrorEnvelope(body: unknown): boolean {\n return (\n typeof body === \"object\" &&\n body !== null &&\n typeof (body as { code?: unknown }).code === \"string\"\n );\n}\n\nfunction isErrnoException(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && typeof (error as NodeJS.ErrnoException).code === \"string\";\n}\n\nfunction isZodLikeError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"issues\" in error &&\n Array.isArray((error as { issues: unknown }).issues)\n );\n}\n\n/** Whether a caught error is the given `errno` code. */\nexport function isErrno(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === code;\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === \"string\") {\n return error;\n }\n return String(error);\n}\n\nfunction pickErrorShape(error: Error): Record<string, unknown> {\n return {\n name: error.name,\n message: error.message,\n code: (error as NodeJS.ErrnoException).code,\n };\n}\n","import { ZitadelError } from \"./errors\";\n\n/**\n * Ctrl-C for the running command.\n *\n * Node exits on SIGINT only while nothing listens for it, and a spinner does\n * listen — clack's stops its animation and returns — so a request stalled\n * behind one used to outlive the keypress. Instead the command listens for\n * itself: the first Ctrl-C aborts {@link interruptSignal}, which every platform\n * request is bound to, so a waiting request rejects with `E_CANCELLED` and the\n * command unwinds through its normal error path.\n *\n * Work that is not a request does not see the signal, so the first Ctrl-C also\n * arms a short grace: a command still running when it lapses exits 130. A\n * second Ctrl-C exits at once. A command with its own handler (`logs --follow`\n * stops following) finishes inside the grace and exits as it always did.\n */\nconst GRACE_MS = 1_000;\n\nlet controller = new AbortController();\nlet grace: NodeJS.Timeout | undefined;\n\n/**\n * Aborted once Ctrl-C has been pressed in the current command, and stays\n * aborted, so a caller that swallows the first rejection cannot start another\n * request.\n */\nexport function interruptSignal(): AbortSignal {\n return controller.signal;\n}\n\nfunction onInterrupt(): void {\n if (controller.signal.aborted) {\n process.exit(130);\n }\n controller.abort(\n new ZitadelError(\"E_CANCELLED\", \"Cancelled\", {\n hint: \"The command was cancelled with Ctrl-C.\",\n }),\n );\n grace = setTimeout(() => process.exit(130), GRACE_MS);\n grace.unref();\n}\n\n/** Starts listening as a command begins, with a signal of its own. */\nexport function listenForInterrupt(): void {\n stopListeningForInterrupt();\n controller = new AbortController();\n process.on(\"SIGINT\", onInterrupt);\n}\n\n/**\n * Stops listening as the command ends. Only matters when commands share a\n * process, as specs do: the grace must not outlive the command that armed it.\n */\nexport function stopListeningForInterrupt(): void {\n process.off(\"SIGINT\", onInterrupt);\n clearTimeout(grace);\n grace = undefined;\n}\n","import {\n createZitadelClient as createRawClient,\n type ZitadelClient,\n type ZitadelClientOptions,\n} from \"@zitadel/api/client\";\nimport { ApiError } from \"@zitadel/api/runtime/fetch\";\n\nimport { interruptSignal } from \"./interrupt\";\n\n/**\n * How long one platform request may take, response body included, before it\n * fails as `E_NETWORK`. Without it a server that accepts the connection and\n * never answers holds the command for the runtime's own limit — minutes.\n */\nexport const REQUEST_TIMEOUT_MS = 30_000;\n\n/**\n * Characters that can drive a terminal rather than print on it: the C0\n * controls (ESC among them), DEL and the C1 controls (`\\p{Cc}`), the format\n * and bidi controls (`\\p{Cf}`), and the line and paragraph separators. Newline\n * and tab are left alone unless the caller asks otherwise, because they are\n * how a description or a multi-line value is written.\n */\nconst CONTROL = /[\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}]/gu;\n\n/** Options for {@link escapeControlCharacters}. */\nexport type EscapeOptions = {\n /**\n * Keep `\\n` and `\\t` as they are. On by default; a renderer that must keep\n * a value on one line turns it off.\n */\n keepLayout?: boolean;\n};\n\n/**\n * Escape every character that could drive the reader's terminal to its\n * visible `\\xNN`/`\\uNNNN` spelling, or `\\u{NNNNN}` above the BMP so the\n * spelling cannot run into the character that follows it.\n *\n * Anything the server returns was written by someone — a user's name, a\n * branding value, a variable — and an ESC or OSC sequence in it would\n * otherwise clear the screen, set the window title, write the clipboard\n * through OSC 52, or disguise a link through OSC 8 when printed. Ordinary text\n * is unchanged, so readable values stay readable.\n */\nexport function escapeControlCharacters(text: string, opts: EscapeOptions = {}): string {\n const keepLayout = opts.keepLayout ?? true;\n return text.replace(CONTROL, (char) => {\n if (keepLayout && (char === \"\\n\" || char === \"\\t\")) {\n return char;\n }\n const code = char.codePointAt(0) ?? 0;\n if (code <= 0xff) {\n return `\\\\x${code.toString(16).padStart(2, \"0\")}`;\n }\n return code <= 0xffff\n ? `\\\\u${code.toString(16).padStart(4, \"0\")}`\n : `\\\\u{${code.toString(16)}}`;\n });\n}\n\n/**\n * Escape an object key. Unlike a value, a key must stay distinct from its\n * siblings: a key holding a raw ESC and one holding the literal text `\\x1b`\n * would otherwise both come out as `\\x1b`, and one of the two fields would be\n * lost. Doubling the backslash first makes the spelling unambiguous.\n */\nfunction escapeKey(key: string): string {\n return escapeControlCharacters(key.replaceAll(\"\\\\\", \"\\\\\\\\\"));\n}\n\n/** An array or object still to be copied, paired with the copy to fill. */\ntype Pending = { source: object; target: Record<string, unknown> | unknown[] };\n\n/**\n * Escape every string in a decoded JSON value, keys included, at any depth.\n * Numbers, booleans and `null` pass through untouched; the result has the\n * same shape as the input, with the same number of fields.\n *\n * The walk keeps its own work list rather than recursing. A user attribute\n * holds arbitrary JSON, and a few thousand levels of nesting — which\n * `JSON.parse` and `JSON.stringify` both accept — would otherwise exhaust the\n * call stack, letting one writer make `list` and `get` fail for every reader.\n */\nexport function sanitizeResponse<T>(value: T): T {\n const pending: Pending[] = [];\n const copy = (item: unknown): unknown => {\n if (typeof item === \"string\") {\n return escapeControlCharacters(item);\n }\n if (typeof item !== \"object\" || item === null) {\n return item;\n }\n const target = Array.isArray(item) ? [] : {};\n pending.push({ source: item, target });\n return target;\n };\n\n const root = copy(value);\n for (let next = pending.pop(); next; next = pending.pop()) {\n const { source, target } = next;\n if (Array.isArray(source)) {\n for (const item of source) {\n (target as unknown[]).push(copy(item));\n }\n continue;\n }\n for (const [key, item] of Object.entries(source)) {\n // Defined rather than assigned, so a `__proto__` key stays a field.\n Object.defineProperty(target, escapeKey(key), {\n value: copy(item),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n return root as T;\n}\n\n/**\n * Rebuild a rejected call's {@link ApiError} with the server's text escaped.\n * The error envelope's `message` and `details` are printed as the failure, so\n * they are as attacker-influenceable as any response body. It stays an\n * `ApiError`, with the same status and URL, so `toZitadelError` classifies it\n * as before. Exported for `zitadel api`, which sends its requests itself.\n */\nexport function sanitizeRejection(error: unknown): never {\n if (!(error instanceof ApiError)) {\n throw error;\n }\n const sanitized = new ApiError(\n error.status,\n error.url,\n sanitizeResponse(error.body),\n escapeControlCharacters(error.message),\n );\n sanitized.stack = error.stack === undefined ? undefined : escapeControlCharacters(error.stack);\n throw sanitized;\n}\n\n/** Options for {@link createZitadelClient}. */\nexport type SanitizeOptions = {\n /**\n * Return response bodies exactly as the server sent them. Only for a\n * caller that stores or compares what it reads rather than printing it:\n * `setup` writes the server's canonical body back to the project's\n * files, and `deploy` diffs against them, so an escaped\n * `\\r` or zero-width joiner would be written to disk as literal text and\n * published as a change. Such a caller escapes at the point it prints.\n * Errors are escaped either way.\n */\n verbatim?: boolean;\n};\n\n/**\n * Build the typed Zitadel client the CLI talks to the server through.\n *\n * It is `@zitadel/api`'s client with every resolved response, and every\n * server-supplied error, passed through {@link sanitizeResponse} — the approach\n * the GitHub CLI takes with go-gh's `asciisanitizer`, widened to the format\n * and bidi controls that can disguise text. Doing it once here, rather than\n * in each renderer, covers every command, table, detail view and `--json`\n * envelope, including ones not yet written; only a caller that asks for\n * {@link SanitizeOptions.verbatim} bodies escapes for itself. The shared\n * package is left raw: the console renders into a DOM, which does not\n * interpret escape codes.\n *\n * Every request is also bounded by {@link REQUEST_TIMEOUT_MS} and cancelled by\n * Ctrl-C (see `./interrupt`), unless the caller sets its own `signal` or\n * `timeoutMs`.\n */\nexport function createZitadelClient(\n opts: ZitadelClientOptions,\n sanitize: SanitizeOptions = {},\n): ZitadelClient {\n const onResolve = sanitize.verbatim ? <T>(value: T): T => value : sanitizeResponse;\n const client = createRawClient({\n signal: interruptSignal(),\n timeoutMs: REQUEST_TIMEOUT_MS,\n ...opts,\n });\n return new Proxy(client, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value !== \"function\") {\n return value;\n }\n return (...args: unknown[]) => {\n const result = (value as (...a: unknown[]) => unknown)(...args);\n return result instanceof Promise ? result.then(onResolve, sanitizeRejection) : result;\n };\n },\n });\n}\n\nexport type { ZitadelClient, ZitadelClientOptions };\n","import { stringify } from \"safe-stable-stringify\";\n\n/**\n * Serialise a value to pretty-printed JSON with object keys sorted at every\n * depth. Determinism is the point: managed files written by the CLI must be\n * byte-stable across runs so diffs stay clean and content hashes don't churn\n * when only key ordering would otherwise differ. Delegates the deterministic\n * sort to `safe-stable-stringify`, matching `JSON.stringify(value, null, 2)`\n * formatting. The `?? \"null\"` only applies to `undefined`/function inputs,\n * which the CLI never serialises.\n */\nexport function stableStringify(value: unknown): string {\n return stringify(value, null, 2) ?? \"null\";\n}\n\n/**\n * Replace (or insert) one top-level key's value in a JSON document by\n * splicing text, leaving every other byte of the source untouched. The\n * counterpart of {@link stableStringify} for files the CLI does *not* own\n * (the user's `package.json`): blank lines, inline nested objects, key\n * order, indentation style, line endings, and the trailing newline all\n * survive, because nothing outside the spliced value is reserialized. The\n * replaced value itself is rendered at the document's detected indent (a\n * compact document stays compact).\n *\n * Defensive by construction: the result is re-parsed and compared against\n * the expected mutation, so a splice that would corrupt the document throws\n * instead of writing it.\n */\nexport function setTopLevelJsonKey(\n source: string,\n path: string,\n key: string,\n value: unknown,\n): string {\n const parsed = parseJsonObject(source, path);\n const eol = source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const indent = detectIndent(source);\n const rendered = renderValueAtDepthOne(value, indent, eol);\n const layout = scanTopLevel(source);\n const member = layout.members.find((candidate) => candidate.key === key);\n\n let next: string;\n if (member) {\n next = `${source.slice(0, member.valueStart)}${rendered}${source.slice(member.valueEnd)}`;\n } else if (layout.members.length === 0) {\n const inner =\n indent === 0\n ? `${JSON.stringify(key)}:${rendered}`\n : `${eol}${indentString(indent)}${JSON.stringify(key)}: ${rendered}${eol}`;\n next = `${source.slice(0, layout.open + 1)}${inner}${source.slice(layout.close)}`;\n } else {\n const last = layout.members.at(-1);\n if (!last) throw new Error(`refusing to write ${path}: the JSON layout scan found no members`);\n const inner =\n indent === 0\n ? `,${JSON.stringify(key)}:${rendered}`\n : `,${eol}${indentString(indent)}${JSON.stringify(key)}: ${rendered}`;\n next = `${source.slice(0, last.valueEnd)}${inner}${source.slice(last.valueEnd)}`;\n }\n\n const verification = parseJsonObject(next, path);\n const expected = { ...parsed, [key]: value };\n if (JSON.stringify(verification) !== JSON.stringify(expected)) {\n throw new Error(`refusing to write ${path}: the targeted JSON edit did not verify`);\n }\n return next;\n}\n\n/**\n * Infers the indentation unit of a JSON document: the whitespace prefix of\n * its first indented line, a compact document stays compact (`0`), and\n * anything unrecognizable falls back to two spaces.\n */\nfunction detectIndent(source: string): string | number {\n const match = source.match(/\\n([ \\t]+)\\S/);\n if (match?.[1]) {\n return match[1];\n }\n return source.trimEnd().includes(\"\\n\") ? 2 : 0;\n}\n\nfunction indentString(indent: string | number): string {\n return typeof indent === \"number\" ? \" \".repeat(indent) : indent;\n}\n\n/** Serializes a value as it should appear as a top-level member's value. */\nfunction renderValueAtDepthOne(value: unknown, indent: string | number, eol: string): string {\n if (indent === 0) {\n return JSON.stringify(value);\n }\n const unit = indentString(indent);\n // Re-indent every continuation line one level deeper and re-join with the\n // document's own line endings.\n return JSON.stringify(value, null, unit).split(\"\\n\").join(`${eol}${unit}`);\n}\n\ntype TopLevelMember = { key: string; valueStart: number; valueEnd: number };\ntype TopLevelLayout = { open: number; close: number; members: TopLevelMember[] };\n\n/**\n * Single-pass, string-aware scan of a JSON object document, collecting the\n * exact text span of every top-level member's value plus the root braces.\n * Only structural understanding needed for the splice — the document has\n * already been validated by `JSON.parse`, so this can assume well-formed\n * input and does not re-validate.\n */\nfunction scanTopLevel(source: string): TopLevelLayout {\n const members: TopLevelMember[] = [];\n let open = -1;\n let close = -1;\n let depth = 0;\n let index = 0;\n\n while (index < source.length) {\n const char = source.charAt(index);\n if (char === '\"') {\n const start = index;\n index = skipString(source, index);\n if (depth === 1 && isKeyPosition(source, start)) {\n const key = JSON.parse(source.slice(start, index)) as string;\n // Skip to the value after the colon.\n while (source[index] !== \":\") index += 1;\n index += 1;\n while (index < source.length && isWhitespace(source.charAt(index))) index += 1;\n const valueStart = index;\n index = skipValue(source, index);\n members.push({ key, valueStart, valueEnd: index });\n }\n continue;\n }\n if (char === \"{\" || char === \"[\") {\n depth += 1;\n if (depth === 1 && open === -1) {\n open = index;\n }\n } else if (char === \"}\" || char === \"]\") {\n depth -= 1;\n if (depth === 0) {\n close = index;\n }\n }\n index += 1;\n }\n return { open, close, members };\n}\n\n/** True when the string starting at `start` is a top-level key, not a value. */\nfunction isKeyPosition(source: string, start: number): boolean {\n for (let index = start - 1; index >= 0; index -= 1) {\n const char = source.charAt(index);\n if (isWhitespace(char)) continue;\n return char === \"{\" || char === \",\";\n }\n return false;\n}\n\n/** Returns the index just past the value starting at `index`. */\nfunction skipValue(source: string, index: number): number {\n const char = source.charAt(index);\n if (char === '\"') {\n return skipString(source, index);\n }\n if (char === \"{\" || char === \"[\") {\n let depth = 0;\n let cursor = index;\n while (cursor < source.length) {\n const current = source.charAt(cursor);\n if (current === '\"') {\n cursor = skipString(source, cursor);\n continue;\n }\n if (current === \"{\" || current === \"[\") depth += 1;\n if (current === \"}\" || current === \"]\") {\n depth -= 1;\n if (depth === 0) return cursor + 1;\n }\n cursor += 1;\n }\n return cursor;\n }\n // Primitive: number, boolean, null — runs until a structural delimiter.\n let cursor = index;\n while (\n cursor < source.length &&\n !\",}]\".includes(source.charAt(cursor)) &&\n !isWhitespace(source.charAt(cursor))\n ) {\n cursor += 1;\n }\n return cursor;\n}\n\n/** Returns the index just past the closing quote of the string at `index`. */\nfunction skipString(source: string, index: number): number {\n let cursor = index + 1;\n while (cursor < source.length) {\n const char = source.charAt(cursor);\n if (char === \"\\\\\") {\n cursor += 2;\n continue;\n }\n if (char === '\"') {\n return cursor + 1;\n }\n cursor += 1;\n }\n return cursor;\n}\n\nfunction isWhitespace(char: string): boolean {\n return char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\";\n}\n\n/**\n * Parse `contents` as JSON and assert the root is a plain object (not an\n * array or scalar). The CLI's config and secret files are always objects, so\n * this guards callers from the `JSON.parse` return type of `any` and produces\n * a `path`-qualified error message pointing at the offending file.\n */\nexport function parseJsonObject(contents: string, path: string): Record<string, unknown> {\n const value = JSON.parse(contents) as unknown;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${path} must contain a JSON object`);\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Narrows an unknown value to a plain (non-array, non-null) object. Shared by\n * the commands and the file-writer that walk parsed JSON, so the predicate\n * isn't reimplemented per call site.\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { ZitadelError } from \"../../errors\";\nimport { isObject } from \"../../json\";\nimport type { Page } from \"./types\";\n\n/** How a command spells draining every page, and fetching one at a time, for its errors. */\nexport type PagingFlags = Readonly<{ all: string; onePage: string }>;\n\n/** The list commands' own: `--all`, and `--limit` with `--page-token`. */\nconst LIST_FLAGS: PagingFlags = { all: \"--all\", onePage: \"--limit and --page-token\" };\n\n/**\n * Walk a cursor-paginated endpoint. `request` performs one page; the\n * response must carry the items under `items` and, while more remain, a\n * the cursor property `nextPageToken` names. With `all` the pages are drained\n * in order and `next`\n * is `null`; otherwise one page is fetched and `next` is its token. `flags`\n * names the caller's own flags in the errors.\n */\nexport const collectPages = async (\n request: (token?: string) => Promise<unknown>,\n {\n items,\n all,\n token,\n nextPageToken,\n flags = LIST_FLAGS,\n }: Readonly<{\n items?: string;\n all: boolean;\n token?: string;\n nextPageToken: string;\n flags?: PagingFlags;\n }>,\n): Promise<Page> => {\n // Accumulated in one array rather than by concatenating each page onto the\n // last: these resources are unbounded, and a wide `--all` would otherwise\n // copy every record once per remaining page.\n const collected: unknown[] = [];\n // A server that returns a cursor it already issued — a bug, a cache — would\n // otherwise have the drain fetch the same page forever behind a spinner that\n // looks like progress.\n const seen = new Set<string>();\n let cursor = token;\n for (;;) {\n const response = await request(cursor);\n // A wrapped page names the array; an endpoint that answers with the\n // collection itself has nothing to name, and the body is the array.\n const page = items === undefined ? response : isObject(response) ? response[items] : undefined;\n if (!Array.isArray(page)) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n items === undefined\n ? \"Unexpected list response: expected an array\"\n : `Unexpected list response: missing \"${items}\" array`,\n { details: { response } },\n );\n }\n collected.push(...(page as readonly unknown[]));\n const cursor_ = isObject(response) ? response[nextPageToken] : undefined;\n const next = typeof cursor_ === \"string\" ? cursor_ || null : null;\n if (!all) {\n return { items: collected, next };\n }\n if (!next) {\n return { items: collected, next: null };\n }\n if (seen.has(next)) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `The server repeated a page cursor, so ${flags.all} would never finish`,\n {\n hint: `Fetch one page at a time with ${flags.onePage}, and report the repeated cursor.`,\n // Named for what it is rather than for the platform's spelling of\n // it, so the error shape does not vary with the wire vocabulary.\n details: { cursor: next, pages_fetched: seen.size + 1 },\n },\n );\n }\n seen.add(next);\n cursor = next;\n }\n};\n","const CLI_PACKAGE_NAME = \"@zitadel/cli\";\n\nexport function npmDistTagForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n const match = normalized.match(/^\\d+\\.\\d+\\.\\d+-([0-9A-Za-z][0-9A-Za-z-]*)/);\n return match?.[1] ?? \"latest\";\n}\n\n/**\n * Whether a version is one the release train publishes: a release (`0.1.0`) or\n * an alpha prerelease (`1.0.0-alpha.25`). Any other prerelease (`1.0.0-beta.2`,\n * `0.0.0-test`) has only its dist-tag to point at.\n */\nexport function isTrainVersion(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(-alpha\\.\\d+)?$/.test(version.trim().replace(/^v/, \"\"));\n}\n\nexport function npmSelectorForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n if (isTrainVersion(normalized)) {\n return normalized;\n }\n return npmDistTagForCliVersion(normalized);\n}\n\n/**\n * The version a scaffold writes for the `@zitadel/*` packages it adds: the\n * CLI's own exact version on the train, else its dist-tag (`beta` for\n * `1.0.0-beta.2`). The packages publish as one lockstep train, so the exact pin\n * keeps the app on the SDK that matches the files this CLI wrote, and lets\n * doctor's `dependency-version` check compare it against the CLI.\n */\nexport function sdkVersionForCli(cliVersion: string): string {\n return npmSelectorForCliVersion(cliVersion);\n}\n\n/**\n * Whether a value can sit in a suggested command unquoted on every shell the\n * CLI runs under (POSIX shells, PowerShell and cmd.exe). Quoting differs\n * between them, so a value that needs quoting is not put in a suggested\n * command at all; callers hand it over as an argument list instead.\n */\nexport function isPortableShellWord(value: string): boolean {\n // `/` is included so a POSIX-style --cwd path can be suggested as written.\n return /^[A-Za-z0-9_./-]+$/.test(value);\n}\n\n/**\n * Suggested commands as strings, built from argument lists. Every argument\n * must be a portable shell word, or none of the commands is returned: a\n * caller then hands over the argument lists alone, which no shell interprets.\n */\nexport function portableCommands(argLists: readonly string[][], cliVersion: string): string[] {\n if (!argLists.every((args) => args.every(isPortableShellWord))) {\n return [];\n }\n return argLists.map((args) => publicCliCommand(args.join(\" \"), cliVersion));\n}\n\n/**\n * An option and its value as arguments for a suggested command. A value that\n * starts with `-` would be read as the next flag, so it is joined with `=`\n * instead. That token is not a portable shell word, so it also keeps the\n * string form out of {@link portableCommands}.\n *\n * @param option - The option, with its dashes, e.g. `--schema`.\n * @param value - The value it takes, as the user or a file name gave it.\n */\nexport function optionArgs(option: string, value: string): string[] {\n return value.startsWith(\"-\") ? [`${option}=${value}`] : [option, value];\n}\n\nexport function publicCliCommand(args: string, cliVersion: string): string {\n const prefix = `npx ${CLI_PACKAGE_NAME}@${npmSelectorForCliVersion(cliVersion)}`;\n return args.length > 0 ? `${prefix} ${args}` : prefix;\n}\n\nexport function normalizePublicCliCommand(command: string, cliVersion: string): string {\n if (command === \"zitadel\") {\n return publicCliCommand(\"\", cliVersion);\n }\n if (command.startsWith(\"zitadel \")) {\n return publicCliCommand(command.slice(\"zitadel \".length), cliVersion);\n }\n return command;\n}\n\nexport function normalizePublicCliCommands<T extends string>(\n commands: ReadonlyArray<T> | undefined,\n cliVersion: string,\n): T[] | undefined {\n // Only the `zitadel` prefix changes, so a suggestion stays a suggestion.\n return commands?.map((command) => normalizePublicCliCommand(command, cliVersion) as T);\n}\n\n/**\n * Rewrites `zitadel …` command mentions in scaffolded prose (the\n * `.zitadel/**` READMEs) to the public `npx @zitadel/cli@<version> …` form.\n *\n * The checked-in README sources stay written with the bare `zitadel`\n * command — that is the canonical, readable spelling — but the CLI is not a\n * dependency of the scaffolded app, so the bare command does not exist on\n * the user's PATH (and `npx zitadel` would fetch an unrelated npm package).\n * Covers inline code spans (`` `zitadel deploy` ``) and fenced-block lines\n * that start with `zitadel `; prose file names like `zitadel.json` and\n * `zitadel.db` don't match because the word must end the span or be\n * followed by a space.\n */\nexport function normalizePublicCliProse(content: string, cliVersion: string): string {\n const prefix = publicCliCommand(\"\", cliVersion);\n return rewriteCliCodeSpans(content, cliVersion).replace(\n /^(\\s*)zitadel (.*)$/gm,\n (_match, indent: string, rest: string) => `${indent}${prefix} ${rest}`,\n );\n}\n\n/** The inline-code-span half of {@link normalizePublicCliProse}. */\nfunction rewriteCliCodeSpans(content: string, cliVersion: string): string {\n const prefix = publicCliCommand(\"\", cliVersion);\n return content.replace(\n /`zitadel( [^`\\n]*)?`/g,\n (_match, args: string | undefined) => `\\`${prefix}${args ?? \"\"}\\``,\n );\n}\n\n/**\n * Rewrites `zitadel …` command mentions inside every string of a scaffolded\n * JSON document — today the `.zitadel/meta/*.json` dialect files — returning\n * a rewritten copy. The input is never mutated: the meta-schema bodies are\n * imported JSON modules shared across calls.\n *\n * Those files are generated copies of the meta-schemas the server embeds\n * (`api/openapi/endpoints/schemas/*.json`), where the bare `zitadel` spelling\n * is the correct one — the server documents the product command, not one\n * project's install. Their `description` strings surface as editor tooltips\n * on the scaffolded `.zitadel/**` files, where the bare command does not\n * exist on the user's PATH, so the copy is normalized on the way out instead\n * of the shared source being edited (same fix PR #872 made for the READMEs).\n *\n * Unlike {@link normalizePublicCliProse} this rewrites inline code spans\n * only: a JSON `description` is prose, so a value that merely begins with\n * the word `zitadel` is a sentence, not a command line.\n */\nexport function normalizePublicCliJson<T>(value: T, cliVersion: string): T {\n if (typeof value === \"string\") {\n return rewriteCliCodeSpans(value, cliVersion) as T;\n }\n if (Array.isArray(value)) {\n return value.map((item) => normalizePublicCliJson(item, cliVersion)) as T;\n }\n if (typeof value === \"object\" && value !== null) {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, normalizePublicCliJson(item, cliVersion)]),\n ) as T;\n }\n return value;\n}\n\n/** The version selector of a public `npx @zitadel/cli@<selector>` mention. */\nconst PUBLIC_CLI_VERSION = new RegExp(`${CLI_PACKAGE_NAME.replaceAll(\"/\", \"\\\\/\")}@[^\\\\s\\`]+`, \"g\");\n\n/**\n * Replaces the version in every public CLI mention inside a JSON document\n * with `*`, so two documents {@link normalizePublicCliJson} wrote for\n * different CLI versions compare equal when nothing else differs. Returns a\n * rewritten copy.\n */\nexport function maskPublicCliVersion<T>(value: T): T {\n if (typeof value === \"string\") {\n return value.replace(PUBLIC_CLI_VERSION, `${CLI_PACKAGE_NAME}@*`) as T;\n }\n if (Array.isArray(value)) {\n return value.map((item) => maskPublicCliVersion(item)) as T;\n }\n if (typeof value === \"object\" && value !== null) {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, maskPublicCliVersion(item)]),\n ) as T;\n }\n return value;\n}\n","import { isPortableShellWord, publicCliCommand } from \"./public-cli\";\n\ndeclare const suggestedCommand: unique symbol;\n\n/**\n * A command the CLI suggests running next: a `nextCommands` entry on a result\n * or an error, a `next_commands` row in a command's data, or the `retry` of an\n * input question. Only the builders below make one, so a suggestion cannot be\n * written without deciding whether it targets this run's project.\n *\n * That decision is the point. A suggestion for a command that talks to a\n * project must carry the run's `--env` / `--env-file` / `--server`, or\n * following it quietly targets the default project instead (#1689). A raw\n * string does not typecheck where a suggestion is expected, so forgetting the\n * selector means choosing {@link unscopedCommand} by name, not by accident.\n */\nexport type SuggestedCommand = string & { readonly [suggestedCommand]: true };\n\ndeclare const environmentSelector: unique symbol;\n\n/**\n * The flags that reproduce a run's environment selection, as a suffix\n * (` --env production`), or `\"\"` when the run named none. Only\n * `environmentSelectorSuffix` makes one, so a project command can only be\n * built from a selector the run actually resolved.\n */\nexport type EnvironmentSelector = string & { readonly [environmentSelector]: true };\n\n/** Brands a suffix built by `environmentSelectorSuffix`; nothing else calls it. */\nexport function asEnvironmentSelector(suffix: string): EnvironmentSelector {\n return suffix as EnvironmentSelector;\n}\n\n/**\n * A `zitadel` command aimed at the same project as the run that suggests it.\n * The selector is appended to `args`, so `args` must not end with a shell\n * redirection; put that after the result instead.\n */\nexport function projectCommand(\n args: string,\n selector: EnvironmentSelector,\n cliVersion: string,\n): SuggestedCommand {\n return publicCliCommand(`${args}${selector}`, cliVersion) as SuggestedCommand;\n}\n\n/**\n * A `zitadel` command that does not target a project: `setup`, `start`,\n * `doctor`, the local runtime. Without `cliVersion` it is the bare `zitadel …`\n * spelling, which the envelope rewrites to the public `npx` form on the way\n * out; pass it when the command is also quoted in a hint.\n */\nexport function unscopedCommand(args: string, cliVersion?: string): SuggestedCommand {\n return (\n cliVersion === undefined ? `zitadel ${args}` : publicCliCommand(args, cliVersion)\n ) as SuggestedCommand;\n}\n\n/**\n * Commands built from argument lists, for a caller that also reports the lists\n * (`next_args`). Every argument must be a portable shell word, or none is\n * returned and the lists stand alone, which no shell interprets. The lists\n * carry whatever selector the command needs: they are the arguments as run.\n */\nexport function portableSuggestions(\n argLists: readonly string[][],\n cliVersion: string,\n /** Arguments the caller fills in (`<what changed>`): quoted in the command, not portable words. */\n placeholders: readonly string[] = [],\n): SuggestedCommand[] {\n const allowed = (word: string) => placeholders.includes(word) || isPortableShellWord(word);\n if (!argLists.every((args) => args.every(allowed))) {\n return [];\n }\n return argLists.map(\n (args) =>\n publicCliCommand(\n args.map((word) => (placeholders.includes(word) ? `'${word}'` : word)).join(\" \"),\n cliVersion,\n ) as SuggestedCommand,\n );\n}\n\n/** A command that is not the CLI (`npm install …`, `rm …`), suggested as written. */\nexport function shellCommand(command: string): SuggestedCommand {\n return command as SuggestedCommand;\n}\n\n/**\n * A suggestion wrapped in shell around it: a pipe that feeds it a secret\n * (`printf '%s' \"$SECRET\" | `) or the `< value.txt` redirection that must\n * follow the selector. The command itself stays the one a builder made.\n */\nexport function inShell(\n command: SuggestedCommand,\n shell: { before?: string; after?: string },\n): SuggestedCommand {\n return `${shell.before ?? \"\"}${command}${shell.after ?? \"\"}` as SuggestedCommand;\n}\n","const DISABLED_VALUES = new Set([\"\", \"0\", \"false\", \"off\", \"no\"]);\n\n/**\n * Whether an environment variable is set to an enabled value. A present-but-\n * falsey string (`CI=false`, `CI=0`) counts as disabled — unlike a bare\n * `Boolean(env.CI)` check, which is true for any non-empty string.\n */\nexport function envEnabled(value: string | undefined): boolean {\n return value !== undefined && !DISABLED_VALUES.has(value.trim().toLowerCase());\n}\n","import type { FlagVariable } from \"../oclif/types\";\n\n/**\n * Outcome of resolving whether telemetry may run for this invocation. `reason`\n * is a stable token (handy in tests and `--debug` logs) explaining the\n * decision; it is never sent anywhere.\n */\nexport type Consent = {\n readonly enabled: boolean;\n readonly reason: \"enabled\" | \"do-not-track\" | \"env-opt-out\" | \"flag-opt-out\" | \"test-runner\";\n};\n\n/** Inputs that can disable telemetry, kept explicit so the matrix is testable. */\nexport type ConsentInput = {\n readonly env: NodeJS.ProcessEnv;\n /** The resolved `--telemetry/--no-telemetry` flag value (default true). */\n readonly flag?: boolean;\n};\n\n/** The cross-tool opt-out. */\nexport const DO_NOT_TRACK: FlagVariable = {\n name: \"DO_NOT_TRACK\",\n flag: \"telemetry\",\n description:\n \"Any value but `0` or an empty one turns telemetry off (https://consoledonottrack.com).\",\n precedence: \"Turns telemetry off even with `--telemetry`.\",\n};\n\n/** The values of {@link ZITADEL_TELEMETRY}, trimmed and lowercased, that turn telemetry off. */\nconst DISABLED_VALUES = new Set([\"\", \"0\", \"false\", \"off\", \"no\"]);\n\n/** The CLI's own opt-out. */\nexport const ZITADEL_TELEMETRY: FlagVariable = {\n name: \"ZITADEL_TELEMETRY\",\n flag: \"telemetry\",\n description: `An empty value or one of ${[...DISABLED_VALUES]\n .filter((value) => value !== \"\")\n .map((value) => `\\`${value}\\``)\n .join(\", \")} turns telemetry off.`,\n precedence: \"Turns telemetry off even with `--telemetry`.\",\n};\n\n/**\n * Resolve telemetry consent under an opt-out model: on by default, but any of\n * several explicit signals turns it off, in precedence order.\n *\n * 1. `--no-telemetry` on the command line — the most explicit, per-invocation.\n * 2. `DO_NOT_TRACK` — the cross-tool standard (https://consoledonottrack.com);\n * any value other than `0`/empty disables.\n * 3. `ZITADEL_TELEMETRY` set to a falsey token (`0`/`false`/`off`/`no`).\n * 4. An automated test run (`VITEST`/`NODE_ENV=test`) — never emit synthetic\n * traffic or pay the shutdown flush; spawned CLI subprocesses inherit it.\n *\n * The user's own choices (1–3) come first so `reason` reports them even in a\n * test shell: the user agent reads it to decide whether to describe the\n * user's environment.\n *\n * Consent being enabled does not by itself send anything; the caller still\n * needs somewhere to send (a Mixpanel token or the Vercel copy) and fails open\n * on any transport error.\n */\nexport function resolveConsent(input: ConsentInput): Consent {\n if (input.flag === false) {\n return { enabled: false, reason: \"flag-opt-out\" };\n }\n\n const doNotTrack = input.env[DO_NOT_TRACK.name]?.trim();\n if (doNotTrack && doNotTrack !== \"0\") {\n return { enabled: false, reason: \"do-not-track\" };\n }\n\n const explicit = input.env[ZITADEL_TELEMETRY.name]?.trim().toLowerCase();\n if (explicit !== undefined && DISABLED_VALUES.has(explicit)) {\n return { enabled: false, reason: \"env-opt-out\" };\n }\n\n if (input.env.VITEST || input.env.NODE_ENV === \"test\") {\n return { enabled: false, reason: \"test-runner\" };\n }\n\n return { enabled: true, reason: \"enabled\" };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * A stable, anonymous identifier for this install. It is a random UUID tied to\n * no account, email, or machine fingerprint — its only job is to let Mixpanel\n * group events from the same install into a funnel. `isFirstRun` is true the\n * one time we mint and persist the id, which drives the one-time consent notice.\n */\nexport type Identity = {\n readonly distinctId: string;\n readonly isFirstRun: boolean;\n};\n\ntype StoredIdentity = { distinctId: string };\n\n/**\n * Resolve the directory the CLI persists cross-invocation state in, honoring\n * the platform conventions: `XDG_CONFIG_HOME` then `~/.config` on Unix, and\n * `%APPDATA%` on Windows. The anonymous id lives here so it survives between\n * runs without touching the user's project tree.\n */\nexport function telemetryConfigDir(env: NodeJS.ProcessEnv): string {\n if (process.platform === \"win32\" && env.APPDATA) {\n return join(env.APPDATA, \"zitadel\", \"cli\");\n }\n const base = env.XDG_CONFIG_HOME?.trim() || join(homedir(), \".config\");\n return join(base, \"zitadel\", \"cli\");\n}\n\n/**\n * Load the persisted anonymous id, minting and storing a new one on first run.\n *\n * Fail-open: if the config dir cannot be resolved, read, or written — including\n * an `os.homedir()` throw in a restricted/containerized environment, a\n * read-only home, a CI sandbox, or a permissions error — fall back to an\n * ephemeral per-process id and report `isFirstRun: false` so we neither crash\n * nor nag the user with the notice on every run. Telemetry is best-effort,\n * never load-bearing.\n */\nexport function loadOrCreateIdentity(env: NodeJS.ProcessEnv): Identity {\n let dir: string;\n try {\n dir = telemetryConfigDir(env);\n } catch {\n return { distinctId: randomUUID(), isFirstRun: false };\n }\n const file = join(dir, \"telemetry.json\");\n\n try {\n const parsed = JSON.parse(readFileSync(file, \"utf8\")) as StoredIdentity;\n if (typeof parsed.distinctId === \"string\" && parsed.distinctId.length > 0) {\n return { distinctId: parsed.distinctId, isFirstRun: false };\n }\n } catch {\n /* fall through to mint a fresh id */\n }\n\n const distinctId = randomUUID();\n try {\n mkdirSync(dir, { recursive: true });\n writeFileSync(file, `${JSON.stringify({ distinctId } satisfies StoredIdentity)}\\n`, {\n mode: 0o600,\n });\n return { distinctId, isFirstRun: true };\n } catch {\n return { distinctId, isFirstRun: false };\n }\n}\n","import type { Property } from \"../property\";\nimport { envEnabled } from \"./env-flag\";\n\n/** Coarse CI provider name, or `undefined` when not running in CI. */\nclass CiProvider implements Property<NodeJS.ProcessEnv, string | undefined> {\n /** Provider-marker env var → reported name, in match order. */\n private static readonly providers = [\n [\"GITHUB_ACTIONS\", \"github_actions\"],\n [\"GITLAB_CI\", \"gitlab_ci\"],\n [\"CIRCLECI\", \"circleci\"],\n [\"BUILDKITE\", \"buildkite\"],\n [\"JENKINS_URL\", \"jenkins\"],\n ] as const satisfies ReadonlyArray<readonly [string, string]>;\n\n public value(env: NodeJS.ProcessEnv): string | undefined {\n const named = CiProvider.providers.find(([marker]) => envEnabled(env[marker]));\n if (named) {\n return named[1];\n }\n return envEnabled(env.CI) ? \"unknown\" : undefined;\n }\n}\n\nexport const ciProvider = new CiProvider();\n","import type { Property } from \"../property\";\n\n/** Fixed-enum identity of the agent or host driving the process. */\nclass HostAgent implements Property<NodeJS.ProcessEnv, string> {\n /** Predicate → reported name, in match order. */\n private static readonly agents: ReadonlyArray<\n readonly [(env: NodeJS.ProcessEnv) => boolean, string]\n > = [\n [(env) => Boolean(env.CLAUDECODE || env.CLAUDE_CODE_ENTRYPOINT), \"claude_code\"],\n [(env) => Boolean(env.CURSOR_TRACE_ID || env.CURSOR_AGENT), \"cursor\"],\n [(env) => env.TERM_PROGRAM === \"vscode\", \"vscode\"],\n ];\n\n public value(env: NodeJS.ProcessEnv): string {\n return HostAgent.agents.find(([matches]) => matches(env))?.[1] ?? \"unknown\";\n }\n}\n\nexport const hostAgent = new HostAgent();\n","/**\n * The `User-Agent` the CLI sends on every HTTP request it makes through\n * undici — the Zitadel API, local-server health checks, branding asset probes\n * — so a server (and its logs and session records) can tell CLI traffic apart\n * from any other Node client, and tell CLI versions apart. Node's `fetch`\n * otherwise sends the bare `node`.\n *\n * Space-separated `product/version` tokens (RFC 9110 §10.1.5), in the style of\n * npm and the AWS CLI, most significant first:\n *\n * zitadel-cli/1.0.0 node/v24.12.0 darwin/24.6.0 arch/arm64 ci/github_actions host/claude_code\n *\n * `ci/` and `host/` use the vocabulary of the telemetry `ci_provider` and\n * `host_agent` dimensions. They appear only when detected, and never once the\n * user has opted out of telemetry: they describe the user's environment, so\n * the same opt-out covers them.\n */\n\nimport { release } from \"node:os\";\n\nimport { type Dispatcher, getGlobalDispatcher, setGlobalDispatcher } from \"undici\";\n\nimport { type Consent, resolveConsent } from \"./telemetry/consent\";\nimport { ciProvider } from \"./telemetry/dimensions/ci-provider\";\nimport { hostAgent } from \"./telemetry/dimensions/host-agent\";\n\nconst USER_AGENT_HEADER = \"user-agent\";\n\n/**\n * Consent outcomes that are the user's own choice. A test run also disables\n * telemetry, but says nothing about what the user wants reported.\n */\nconst OPT_OUT_REASONS: ReadonlySet<Consent[\"reason\"]> = new Set([\n \"flag-opt-out\",\n \"do-not-track\",\n \"env-opt-out\",\n]);\n\n/** Process facts the user agent is built from, surfaced as data so it is testable. */\nexport type UserAgentFacts = {\n readonly cliVersion: string;\n readonly nodeVersion: string;\n readonly platform: NodeJS.Platform;\n readonly osRelease: string;\n readonly arch: string;\n readonly env: NodeJS.ProcessEnv;\n /** The `--telemetry/--no-telemetry` flag, when given. */\n readonly telemetryFlag?: boolean;\n};\n\n/** The {@link UserAgentFacts} of the running process. */\nexport function processUserAgentFacts(\n cliVersion: string,\n telemetryFlag: boolean | undefined,\n): UserAgentFacts {\n return {\n cliVersion,\n nodeVersion: process.version,\n platform: process.platform,\n osRelease: release(),\n arch: process.arch,\n env: process.env,\n telemetryFlag,\n };\n}\n\nexport function buildUserAgent(facts: UserAgentFacts): string {\n const tokens = [\n product(\"zitadel-cli\", facts.cliVersion),\n product(\"node\", facts.nodeVersion),\n product(facts.platform, facts.osRelease),\n product(\"arch\", facts.arch),\n ];\n const consent = resolveConsent({ env: facts.env, flag: facts.telemetryFlag });\n if (!OPT_OUT_REASONS.has(consent.reason)) {\n const ci = ciProvider.value(facts.env);\n if (ci !== undefined) {\n tokens.push(product(\"ci\", ci));\n }\n const host = hostAgent.value(facts.env);\n if (host !== \"unknown\") {\n tokens.push(product(\"host\", host));\n }\n }\n return tokens.join(\" \");\n}\n\n/**\n * One `name/version` product token. Characters outside the RFC 9110 `token`\n * set (an OS release string is free-form) become `_`, so a stray space or\n * slash can never split one token into two.\n */\nfunction product(name: string, version: string): string {\n return `${sanitizeToken(name)}/${sanitizeToken(version)}`;\n}\n\nfunction sanitizeToken(value: string): string {\n return value.replace(/[^!#$%&'*+\\-.^_`|~0-9A-Za-z]/g, \"_\") || \"unknown\";\n}\n\n/** The installed user agent and the global dispatcher that carries it. */\ntype UserAgentSlot = {\n userAgent?: string;\n dispatcher?: Dispatcher;\n};\n\n/**\n * Stored on `globalThis`, like the dispatcher it wraps, so every copy of this\n * module in the process shares one value: with module-local state, a second\n * copy would compose a second interceptor whose stale value overwrote the\n * first's on every request.\n */\nconst SLOT = Symbol.for(\"@zitadel/cli/user-agent\");\n\nfunction slot(): UserAgentSlot {\n const scope = globalThis as Record<symbol, UserAgentSlot | undefined>;\n scope[SLOT] ??= {};\n return scope[SLOT];\n}\n\n/**\n * undici interceptor that sets the installed user agent on every request,\n * replacing whatever the caller or `fetch` put there. Exported so a module\n * that builds its own dispatcher (and so bypasses the global one) can\n * compose it; a no-op until {@link installUserAgent} runs.\n */\nexport const userAgentInterceptor: Dispatcher.DispatcherComposeInterceptor =\n (dispatch) => (options, handler) => {\n const userAgent = slot().userAgent;\n return dispatch(\n userAgent === undefined\n ? options\n : { ...options, headers: withUserAgent(options.headers, userAgent) },\n handler,\n );\n };\n\n/**\n * Make every request through the global dispatcher — which is what `fetch`\n * uses, including the `@zitadel/api` client — carry `userAgent`. Composes\n * onto the existing global dispatcher, so a proxy agent installed before\n * (`NODE_USE_ENV_PROXY`) keeps working. Calling it again only replaces the\n * value, unless something has since swapped the global dispatcher out, in\n * which case the interceptor is composed onto the new one.\n *\n * Importing the `undici` package installs its own `Agent` as the global\n * dispatcher when none is set yet, so Node's bundled `fetch` dispatches\n * through the package's undici. Keep its major version on the one the\n * supported Node release bundles.\n */\nexport function installUserAgent(userAgent: string): void {\n const state = slot();\n state.userAgent = userAgent;\n const current = getGlobalDispatcher();\n if (current !== state.dispatcher) {\n state.dispatcher = current.compose(userAgentInterceptor);\n setGlobalDispatcher(state.dispatcher);\n }\n}\n\n/**\n * Forget the installed user agent. **Test-only**: it does not restore the\n * global dispatcher, which the caller saved and puts back itself.\n */\nexport function _resetUserAgentForTesting(): void {\n delete (globalThis as Record<symbol, unknown>)[SLOT];\n}\n\n/**\n * Rewrite `headers` — in any of the shapes undici accepts — as a flat\n * name/value list with every existing `user-agent` dropped and `userAgent`\n * appended. The flat list keeps repeated headers intact. A malformed\n * odd-length list is returned untouched, for undici to reject.\n */\nexport function withUserAgent(\n headers: Dispatcher.DispatchOptions[\"headers\"],\n userAgent: string,\n): Dispatcher.DispatchOptions[\"headers\"] {\n if (Array.isArray(headers) && headers.length % 2 !== 0) {\n return headers;\n }\n const flat: string[] = [];\n for (const [name, value] of headerEntries(headers)) {\n if (name.toLowerCase() === USER_AGENT_HEADER) {\n continue;\n }\n const values = value === undefined ? [] : Array.isArray(value) ? value : [value];\n for (const item of values) {\n flat.push(name, item);\n }\n }\n flat.push(USER_AGENT_HEADER, userAgent);\n return flat;\n}\n\ntype HeaderEntry = readonly [string, string | string[] | undefined];\n\nfunction headerEntries(headers: Dispatcher.DispatchOptions[\"headers\"]): Iterable<HeaderEntry> {\n if (headers == null) {\n return [];\n }\n if (Array.isArray(headers)) {\n const pairs: HeaderEntry[] = [];\n for (let index = 0; index < headers.length; index += 2) {\n // Even length is checked by the caller, so both indexes are in range.\n pairs.push([headers[index] as string, headers[index + 1]]);\n }\n return pairs;\n }\n if (Symbol.iterator in headers) {\n return headers as Iterable<HeaderEntry>;\n }\n return Object.entries(headers);\n}\n","import { consola } from \"consola\";\n\n/**\n * Warnings reported during this invocation. The CLI runs one command per\n * process, so a module-level list is the invocation's list; `BaseCommand`\n * clears it when a command starts and drains it into the envelope when the\n * command emits.\n */\nconst reported: string[] = [];\n\n/**\n * Report a warning. This is the only way the CLI warns: never call\n * `consola.warn` directly (see `apps/cli/AGENTS.md`).\n *\n * A terminal shows the warning at once, which matters when it comes before a\n * long wait. `--json` silences that output, so the warning is also kept for\n * the envelope's `warnings`, and both kinds of reader see it.\n */\nexport function reportWarning(message: string): void {\n consola.warn(message);\n reported.push(message);\n}\n\n/** Take every warning reported so far, leaving none behind. */\nexport function takeReportedWarnings(): string[] {\n return reported.splice(0);\n}\n","import type { GetVariable200, GetVariables200 } from \"@zitadel/api/generated/model\";\n\nimport type { Parsed } from \"@zitadel/config/idp\";\n\nimport { escapeControlCharacters } from \"./api-client\";\nimport { ZitadelError } from \"./errors\";\n\n/** The kinds of value a name can hold: what primary deploys freeze, and what preview deploys freeze. */\nexport type VariableKind = \"primary\" | \"preview\";\n\n/**\n * The query a variable write or delete takes: the project and, for `--preview`,\n * the kind. Without a kind the platform's default applies: a plain value is\n * stored for both kinds and a secret for the primary kind only, and a delete\n * removes both.\n */\nexport type VariableScope = { project_id: string; kind?: \"preview\" };\n\n/** The scope a variable write or delete addresses, from the project and `--preview`. */\nexport function variableScope(projectId: string, preview: boolean): VariableScope {\n return preview ? { project_id: projectId, kind: \"preview\" } : { project_id: projectId };\n}\n\n/**\n * The scope of a read. A read names one kind, because the platform answers a\n * name with a value per kind and the two are never merged: `--preview` reads the\n * preview values, and without it the primary ones.\n */\nexport function variableReadScope(\n projectId: string,\n preview: boolean,\n): { project_id: string; kind: VariableKind } {\n return { project_id: projectId, kind: preview ? \"preview\" : \"primary\" };\n}\n\n/**\n * A variable as the platform reports it. A non-secret carries its value; a\n * secret carries none, because a read answers `{\"secret\": true}` and never\n * discloses what is stored (ADR 062 §7).\n */\nexport type VariableRow = {\n name: string;\n secret: boolean;\n value?: string | number | boolean;\n /**\n * What the name's preview kind holds, on the inventory the default `list`\n * prints. Absent means the name holds no preview value — which is not the\n * same as holding an empty one, so the two render differently (#1617).\n */\n preview?: { secret: boolean; value?: string | number | boolean };\n};\n\n/** One value on the wire: a bare scalar, or `{\"secret\": true}` for a secret. */\nexport type VariableValue = NonNullable<GetVariable200[\"primary\"]>;\n\n/** The values of one kind in a read, keyed by name. */\nexport function valuesOfKind(\n body: GetVariables200,\n kind: VariableKind,\n): Record<string, VariableValue> {\n return Object.fromEntries(\n Object.entries(body).flatMap(([name, byKind]) =>\n byKind[kind] === undefined ? [] : [[name, byKind[kind]]],\n ),\n );\n}\n\n/** The primary values of a read, keyed by name. */\nexport function primaryValues(body: GetVariables200): Record<string, VariableValue> {\n return valuesOfKind(body, \"primary\");\n}\n\n/**\n * Project one wire value into a row. Both endpoints answer in the same two\n * forms — a bare scalar for a non-secret, `{\"secret\": true}` for a secret — so\n * the collection and the single-name read share this.\n */\nexport function toVariableRow(name: string, value: VariableValue): VariableRow {\n return typeof value === \"object\" && value !== null\n ? { name, secret: true }\n : { name, secret: false, value };\n}\n\n/**\n * Project the values into rows, sorted by name so output is stable between\n * runs.\n */\nexport function toVariableRows(values: Record<string, VariableValue>): VariableRow[] {\n return Object.entries(values)\n .map(([name, value]) => toVariableRow(name, value))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/** Stands in for a secret's value, which the platform never discloses. */\nconst SECRET_MARKER = \"(secret)\";\n\n/** Stands in for a kind the name holds no value for at all. */\nconst NO_VALUE = \"-\";\n\n/**\n * Every name on the project with the primary value it holds and the preview\n * value beside it, sorted by name. A read without a kind answers both, so one\n * request covers the inventory; a name is listed when either kind holds a\n * value, so a preview-only name does not disappear (#1617).\n */\nexport function toInventoryRows(body: GetVariables200): VariableRow[] {\n return Object.entries(body)\n .map(([name, byKind]) => {\n const primary =\n byKind.primary === undefined ? undefined : toVariableRow(name, byKind.primary);\n const preview =\n byKind.preview === undefined ? undefined : toVariableRow(name, byKind.preview);\n return {\n name,\n secret: primary?.secret ?? false,\n ...(primary?.value === undefined ? {} : { value: primary.value }),\n ...(preview === undefined\n ? {}\n : {\n preview: {\n secret: preview.secret,\n ...(preview.value === undefined ? {} : { value: preview.value }),\n },\n }),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * {@link variableCells} plus the preview column, for the inventory. A kind the\n * name holds nothing for prints `-`: an empty cell would read as an empty\n * value, and a secret prints its marker in either column.\n */\nexport function variableInventoryCells(\n rows: ReadonlyArray<VariableRow>,\n): Array<{ name: string; value: string; preview: string }> {\n const cell = (\n held: { secret: boolean; value?: string | number | boolean } | undefined,\n ): string =>\n held === undefined\n ? NO_VALUE\n : held.secret\n ? SECRET_MARKER\n : held.value === undefined\n ? NO_VALUE\n : renderScalar(held.value);\n return rows.map((row) => ({\n name: row.name,\n value: cell(row.value === undefined && !row.secret ? undefined : row),\n preview: cell(row.preview),\n }));\n}\n\n/**\n * Render a stored scalar for a terminal.\n *\n * A value is attacker-influenceable — anyone holding `variable.write` chooses\n * it — so it is never interpolated raw. The client already escapes what could\n * drive the terminal; this also escapes a newline and a tab, which would\n * break the table out of its own row or split a tab-separated line.\n */\nexport function renderScalar(value: string | number | boolean | undefined): string {\n if (typeof value !== \"string\") {\n return String(value);\n }\n return escapeControlCharacters(value, { keepLayout: false });\n}\n\n/**\n * The rows as the cells the resource commands' renderers print, one per\n * column. Those renderers print a string verbatim, so every value is escaped\n * here first: a stored value is chosen by whoever holds `variable.write`, and a\n * newline or an ESC byte must not reach the reader's terminal. A secret prints\n * a marker rather than a value — there is none to print, and an empty cell would\n * read as an empty value rather than a withheld one.\n */\nexport function variableCells(\n rows: ReadonlyArray<VariableRow>,\n): Array<{ name: string; value: string }> {\n return rows.map((row) => ({\n name: row.name,\n value: row.secret ? SECRET_MARKER : renderScalar(row.value),\n }));\n}\n\n/**\n * Names the platform accepts, from `variable-name.yaml`: word characters only,\n * which is exactly what the `${{ NAME }}` reference syntax can address\n * (ADR 062 §2). Checked before the patch so one bad line in a `.env` file is\n * named locally rather than failing the whole transaction at the edge.\n */\nconst VARIABLE_NAME = /^\\w+$/;\n\n/** Longest name the same schema accepts. */\nconst VARIABLE_NAME_MAX = 255;\n\n/** Reject a name the platform would refuse, naming it. */\nexport function assertVariableName(name: string): void {\n if (!VARIABLE_NAME.test(name)) {\n throw new ZitadelError(\"E_VALIDATION\", `Invalid variable name ${JSON.stringify(name)}.`, {\n hint: \"A variable name contains only letters, digits and underscores.\",\n });\n }\n if (name.length > VARIABLE_NAME_MAX) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `Variable name is ${name.length} characters; the limit is ${VARIABLE_NAME_MAX}.`,\n { hint: \"Shorten the name.\" },\n );\n }\n}\n\n/**\n * The scalar types a variable can hold — the API's JSON scalars (ADR 062 §1).\n * The server resolves `${{ NAME }}` only in an OIDC connection's `client_id`\n * and `client_secret` (`flow_sso_redirect_issuer.go`, `flow_sso_callback.go`),\n * and both must hold a string, so no reference resolves to a number or boolean\n * yet.\n */\nexport const VARIABLE_TYPES = [\"string\", \"number\", \"boolean\"] as const;\n\nexport type VariableType = (typeof VARIABLE_TYPES)[number];\n\n/**\n * A JSON number, spelled strictly. `Number()` alone would accept `0x10`, a\n * blank string, or surrounding whitespace, none of which is a number anyone\n * means when they type one.\n */\nconst JSON_NUMBER = /^-?(0|[1-9]\\d*)(\\.\\d+)?([eE][+-]?\\d+)?$/;\n\n/**\n * Turn what was typed or piped into the scalar to store, as the type asks, or\n * say what is wrong with it. The problem carries its hint, so a caller that\n * only has the problem to show loses nothing.\n *\n * The type is stated, never guessed: an integer past 2^53 has no exact JSON\n * number, so an ID or a numeric credential would be stored with different\n * digits than were entered. It is refused rather than silently rounded.\n */\nexport function parseVariableValue(\n raw: string,\n type: VariableType,\n): Parsed<string | number | boolean> {\n const refuse = (problem: string, hint: string): Parsed<never> => ({\n ok: false,\n problem: `${problem} ${hint}`,\n });\n switch (type) {\n case \"string\":\n return { ok: true, value: raw };\n case \"boolean\":\n if (raw === \"true\" || raw === \"false\") {\n return { ok: true, value: raw === \"true\" };\n }\n return refuse(\n `Expected true or false, got ${JSON.stringify(raw)}.`,\n \"A boolean variable is exactly `true` or `false`.\",\n );\n case \"number\": {\n const value = Number(raw);\n if (!JSON_NUMBER.test(raw) || !Number.isFinite(value)) {\n return refuse(\n `Expected a number, got ${JSON.stringify(raw)}.`,\n \"Write it as a JSON number, such as 5, -1.5 or 1e3.\",\n );\n }\n if (Number.isInteger(value) && !Number.isSafeInteger(value)) {\n return refuse(\n `${raw} is too large to store exactly as a number.`,\n \"Store it as a string, which keeps every digit.\",\n );\n }\n return { ok: true, value };\n }\n }\n}\n\n/**\n * Read a value from stdin, for the non-interactive path\n * (`variable set NAME --secret < secret.txt`).\n *\n * A single trailing newline is stripped — a here-doc or `echo` adds one and it\n * is not part of the credential — but nothing else is trimmed, because\n * whitespace inside a value is the caller's to decide.\n */\nexport async function readStdin(stream: NodeJS.ReadableStream): Promise<string> {\n // A local accumulator: `Array.fromAsync` would read better but is not on\n // every Node the package supports.\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n return Buffer.concat(chunks)\n .toString(\"utf8\")\n .replace(/\\r?\\n$/, \"\");\n}\n","import { isObject } from \"../json\";\n\n/**\n * Collects the environment variables a flows document depends on, sorted and\n * de-duplicated. Recognises two reference styles: inline `${VAR}` interpolations\n * inside string values, and keys ending in `_env` whose value names a single\n * variable. `deploy` uses this to fail before contacting the platform when\n * a required variable is absent.\n */\nexport function flowEnvRefs(value: unknown): string[] {\n const refs = new Set<string>();\n const visit = (node: unknown): void => {\n if (typeof node === \"string\") {\n for (const match of node.matchAll(/\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g)) {\n const ref = match[1];\n if (ref) {\n refs.add(ref);\n }\n }\n } else if (Array.isArray(node)) {\n node.forEach(visit);\n } else if (isObject(node)) {\n for (const [key, child] of Object.entries(node)) {\n if (\n key.endsWith(\"_env\") &&\n typeof child === \"string\" &&\n /^[A-Za-z_][A-Za-z0-9_]*$/.test(child)\n ) {\n refs.add(child);\n } else {\n visit(child);\n }\n }\n }\n };\n visit(value);\n return [...refs].sort();\n}\n","import { flowConfigSchema } from \"@zitadel/config/schemas\";\nimport {\n PURPOSE_FLIP_TARGETS,\n validateFlowDefinition,\n type FlowValidationIssue,\n} from \"@zitadel/config/validate\";\n\nimport { isObject } from \"../json\";\n\n/** What validating a flow against a schema change found. */\ntype FlowCheck =\n /**\n * The flow has a structural error, so the validator never reached the rules\n * that depend on the schema and cannot say whether the change breaks it.\n */\n | { readonly kind: \"unchecked\"; readonly issues: FlowValidationIssue[] }\n /** The errors the change introduces; empty when the flow is unaffected. */\n | { readonly kind: \"checked\"; readonly introduced: FlowValidationIssue[] };\n\n/**\n * Check what a schema change from `before` to `after` does to a flow.\n *\n * Only new errors count. A schema-rule error the flow already had is `deploy`'s\n * to report, and refusing an unrelated change because of it would block the\n * developer from an edit that might be part of the fix.\n *\n * @param flow - The flow as it is on disk.\n * @param before - The schema as it is on disk.\n * @param after - The schema as the change leaves it.\n * @param flowAfter - The flow as the change leaves it. Password and passkey\n * never edit a flow, so it defaults to the flow itself; `auth-method sso\n * disable` removes the provider from it.\n */\nexport function checkFlow(\n flow: object,\n before: Record<string, unknown>,\n after: Record<string, unknown>,\n flowAfter: object = flow,\n): FlowCheck {\n // The semantic validator reads a malformed shape leniently (a string where\n // `fields` should be a list reads as no fields), so the raw file is checked\n // against the canonical flow schema first, as `deploy` does.\n const shape = flowConfigSchema.safeParse(flowAfter);\n if (!shape.success) {\n return {\n kind: \"unchecked\",\n issues: shape.error.issues.map((issue) => ({\n severity: \"error\",\n rule: \"definition\",\n message: `${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`,\n })),\n };\n }\n // The validator runs the schema rules only over a structurally sound flow,\n // so without this the change would always look harmless on a broken one.\n const structural = validateFlowDefinition(flowAfter);\n if (structural.length > 0) {\n return { kind: \"unchecked\", issues: structural };\n }\n const key = (issue: FlowValidationIssue) => `${issue.rule}\\u0000${issue.message}`;\n const existing = new Set(\n validateFlowDefinition(flow, before)\n .filter((issue) => issue.severity === \"error\")\n .map(key),\n );\n return {\n kind: \"checked\",\n introduced: validateFlowDefinition(flowAfter, after).filter(\n (issue) => issue.severity === \"error\" && !existing.has(key(issue)),\n ),\n };\n}\n\n/**\n * The sign-in methods (`password`, `passkey`, `sso`) that some active flow\n * lets an existing user sign in with.\n *\n * Only an active flow is served, so a draft offers nothing. Passkey counts\n * only through a `passkey` action: `passkey_register` enrols a new credential\n * and signs nobody in. SSO counts only through a step offering one of\n * `providers`.\n *\n * @param flows - The flows that run against the schema, whatever their status.\n * @param providers - The SSO providers the schema enables.\n */\nexport function offeredSignInMethods(\n flows: readonly Record<string, unknown>[],\n providers: readonly string[],\n): string[] {\n // Only the login journey signs anyone in: a register-only flow, or the\n // register steps of a combined one, can collect a password or offer a\n // passkey without letting an existing user back in.\n const journeys = flows.filter((flow) => flow.status === \"active\").map(loginJourney);\n const offered = (signsIn: (flow: Record<string, unknown>) => boolean) => journeys.some(signsIn);\n return [\n ...(offered(collectsPassword) ? [\"password\"] : []),\n ...(offered(signsInWithPasskey) ? [\"passkey\"] : []),\n ...(offered((flow) => offersSso(flow, providers)) ? [\"sso\"] : []),\n ];\n}\n\n/**\n * Outcomes the engine answers by switching from login to register without a\n * `purpose` on the transition: the validator's flip table, plus\n * `sso_user_not_found`, which it leaves out of that table on purpose but\n * which routes to registration the same way.\n */\nconst LOGIN_LEAVING_OUTCOMES = new Set([\n ...Object.keys(PURPOSE_FLIP_TARGETS.login ?? {}),\n \"sso_user_not_found\",\n]);\n\n/**\n * The flow cut down to the steps reachable from its `login` entry, following\n * transitions that stay in the login purpose. No `login` purpose means no\n * steps: such a flow signs nobody in.\n */\nfunction loginJourney(flow: Record<string, unknown>): Record<string, unknown> {\n const purposes = isObject(flow.purposes) ? flow.purposes : {};\n const entry = purposes.login;\n const byName = new Map(steps(flow).map((step) => [step.name, step]));\n const reached = new Set<string>();\n const queue = typeof entry === \"string\" ? [entry] : [];\n while (queue.length > 0) {\n const name = queue.shift() as string;\n const step = byName.get(name);\n if (reached.has(name) || step === undefined) {\n continue;\n }\n reached.add(name);\n const transitions = isObject(step.transitions) ? Object.entries(step.transitions) : [];\n for (const [outcome, transition] of transitions) {\n // Some outcomes switch the journey to registration on their own, with\n // no `purpose` on the transition: the steps after them register a new\n // user rather than sign one in.\n if (LOGIN_LEAVING_OUTCOMES.has(outcome)) {\n continue;\n }\n // Mirrors the validator's local adjacency: a transition with an\n // `action` goes to another flow, whose step names are not this flow's,\n // and one into another purpose (register, say) leaves the login\n // journey. A null `action` or `purpose` is the same as an absent one.\n if (\n isObject(transition) &&\n typeof transition.target === \"string\" &&\n (transition.action === undefined || transition.action === null) &&\n (transition.purpose === undefined ||\n transition.purpose === null ||\n transition.purpose === \"login\")\n ) {\n queue.push(transition.target);\n }\n }\n }\n return { ...flow, steps: steps(flow).filter((step) => reached.has(step.name as string)) };\n}\n\nfunction steps(flow: Record<string, unknown>): Record<string, unknown>[] {\n return Array.isArray(flow.steps) ? flow.steps.filter(isObject) : [];\n}\n\n/** Password is field-shaped: a step collects `x-auth-methods#password`. */\nfunction collectsPassword(flow: Record<string, unknown>): boolean {\n return steps(flow).some(\n (step) => Array.isArray(step.fields) && step.fields.includes(\"x-auth-methods#password\"),\n );\n}\n\nfunction signsInWithPasskey(flow: Record<string, unknown>): boolean {\n return steps(flow).some(\n (step) =>\n Array.isArray(step.actions) &&\n step.actions.some((action) => isObject(action) && action.kind === \"passkey\"),\n );\n}\n\nfunction offersSso(flow: Record<string, unknown>, providers: readonly string[]): boolean {\n return steps(flow).some(\n (step) =>\n Array.isArray(step.sso_providers) &&\n step.sso_providers.some((p) => typeof p === \"string\" && providers.includes(p)),\n );\n}\n","/**\n * Public surface for the flow domain. Every caller outside this module\n * imports from here (not from individual files) so the package\n * boundary stays observable.\n *\n * **Source of truth.** The wire shape lives in\n * `@zitadel/api/generated/model` (orval-generated from the\n * OpenAPI spec). Callers that need the type import\n * `CreateFlowDefinitionBodyFlowDefinition` from there directly;\n * callers that need the runtime validator import\n * `CreateFlowDefinitionBody` from\n * `@zitadel/api/generated/endpoints/zitadelNextGen.zod`. This\n * module owns only the CLI-specific concerns: the password-flow\n * builder, env-var reference scanning, the file-level\n * `validateFlows` helper that surfaces `E_VALIDATION` errors against\n * the generated Zod, and the sign-in analysis the `auth-method`\n * commands run over a flow (what a schema change breaks, and which\n * methods a flow lets a user sign in with).\n *\n * **Dependency rule.** No upward imports (`commands/`, `sync/`, etc.)\n * and no filesystem I/O. It depends sideways only on shared utilities\n * under `apps/cli/src/lib/` — today `lib/errors` (`ZitadelError`) and\n * `lib/json` (`isObject`).\n */\nexport { buildFlow } from \"./build\";\nexport { validateFlows } from \"./validate\";\nexport { flowEnvRefs } from \"./env-refs\";\nexport { checkFlow, offeredSignInMethods } from \"./sign-in\";\n\n/**\n * Relative directory (from the project root) where local flow files\n * live. Owned here so callers (`commands/*`, `sync/syncers.ts`) and\n * tests share a single source of truth for the path; the runtime\n * never depends on it directly because `lib/flows` does not touch\n * the filesystem.\n */\nexport const FLOWS_DIR = \".zitadel/flows\";\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport {\n type ClientId,\n type ClientIdVariable,\n type ClientSecretVariable,\n type ConnectionSlug,\n credentialVariables,\n type CustomOidcInput,\n idpProvider,\n isVariableReference,\n parseConnectionSlug,\n type ProviderSelection,\n referencedVariable,\n type IdpProvider,\n} from \"@zitadel/config/idp\";\n\nimport { isErrno, ZitadelError } from \"../errors\";\nimport { isObject } from \"../json\";\n\n/**\n * Relative directory (from the project root) where local connection files\n * live, one per provider. Owned here alongside the only reader of it, and\n * re-exported from `lib/idp` so callers and tests share one source of truth\n * for the path, as `FLOWS_DIR` and `SCHEMAS_DIR` do for their domains.\n */\nexport const IDPS_DIR = \".zitadel/idps\";\n\n/**\n * `$schema` pointer a scaffolded connection carries, relative to\n * {@link IDPS_DIR}: the meta-schema `zitadel setup` writes under\n * `.zitadel/meta/`, so an editor validates the file as it is typed.\n */\nexport const CONNECTION_SCHEMA_REF = \"../meta/idp-connection.json\";\n\n/** A connection file as it sits on disk, with the name needed to report it. */\nexport type ConnectionFile = {\n /** File name within {@link IDPS_DIR}, e.g. `google.json`. */\n readonly name: string;\n /** Project-relative path, for messages the developer has to act on. */\n readonly path: string;\n readonly body: Record<string, unknown>;\n};\n\n/**\n * Read every connection file under `.zitadel/idps/`, in lexical order so a\n * duplicate report is stable. A missing directory reads as no connections:\n * the first provider a Project enables creates it.\n *\n * Unlike `readJsonDir`, this keeps each file's name. Every decision below is\n * reported to the developer in terms of the file they have to look at.\n */\nexport async function readConnectionFiles(cwd: string): Promise<ConnectionFile[]> {\n const dir = join(cwd, IDPS_DIR);\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch (error) {\n if (isErrno(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n const files: ConnectionFile[] = [];\n for (const name of entries.filter((e) => e.endsWith(\".json\")).sort()) {\n const path = `${IDPS_DIR}/${name}`;\n let body: unknown;\n try {\n body = JSON.parse(await readFile(join(dir, name), \"utf8\"));\n } catch (error) {\n throw new ZitadelError(\"E_VALIDATION\", `${path} is not valid JSON`, {\n hint: \"Fix or remove the file, then run the command again.\",\n details: { file: path, parse_error: describeParseError(error) },\n });\n }\n if (!isObject(body)) {\n throw new ZitadelError(\"E_VALIDATION\", `${path} does not contain a JSON object`, {\n details: { file: path },\n });\n }\n files.push({ name, path, body });\n }\n return files;\n}\n\n/**\n * What went wrong parsing a file, without the text of the file. V8 quotes the\n * source it choked on, and this file is where a pasted secret would be.\n */\nfunction describeParseError(error: unknown): string {\n const position = error instanceof Error ? /position (\\d+)/.exec(error.message)?.[1] : undefined;\n return position === undefined ? \"invalid JSON\" : `invalid JSON at position ${position}`;\n}\n\n/**\n * Whether a connection file describes the catalog entry's provider.\n *\n * `template` names the catalog entry the file was scaffolded from. When it was\n * edited away, the file still counts if it carries the catalog's own slug and\n * issuer. A different slug on the same issuer is a custom connection that\n * happens to point at the provider, which a Project may hold alongside the\n * catalog one, so the catalog provider does not claim it.\n */\nfunction describesProvider(file: ConnectionFile, entry: IdpProvider): boolean {\n if (file.body.template === entry.template) {\n return true;\n }\n const oidc = file.body.oidc;\n return (\n String(file.body.slug ?? \"\").trim() === entry.slug &&\n isObject(oidc) &&\n oidc.issuer === entry.issuer\n );\n}\n\n/** The client id a connection file carries. */\nfunction clientIdOf(file: ConnectionFile): string | undefined {\n return credentialOf(file, \"client_id\");\n}\n\n/** One credential field, from the file's `oidc` block. */\nfunction credentialOf(\n file: ConnectionFile,\n field: \"client_id\" | \"client_secret\",\n): string | undefined {\n const block = file.body.oidc;\n return isObject(block) && typeof block[field] === \"string\" ? block[field] : undefined;\n}\n\n/**\n * The variables a connection's credentials reference, falling back to the\n * names this CLI would have written.\n *\n * A connection is editable and may name its own variables, so publishing to a\n * slug-derived name would store the credential where the connection never\n * looks and report it as stored.\n */\nexport function credentialVariablesOf(\n file: ConnectionFile,\n slug: ConnectionSlug | undefined,\n): StoredVariables {\n const scaffolded = slug === undefined ? undefined : credentialVariables(slug);\n return {\n clientId: named(file, \"client_id\", scaffolded?.clientId),\n clientSecret: named(file, \"client_secret\", scaffolded?.clientSecret),\n };\n}\n\n/**\n * The variable a credential field names, as the type of its fallback.\n *\n * A field absent from the file is where this command would have pointed it and\n * will point it now, so it reads as `fallback`, which is `undefined` when the\n * caller has no slug to derive one from. A field holding a literal is the value\n * itself: there is no variable behind it, and naming one would publish where\n * the connection never looks. Whatever a `client_id` field references is a\n * client id's variable, whatever it is called, which is what the brand records;\n * the type parameter keeps the two credentials from being swapped.\n */\nfunction named<V extends string>(\n file: ConnectionFile,\n field: \"client_id\" | \"client_secret\",\n fallback: V | undefined,\n): V | undefined {\n const value = credentialOf(file, field);\n return value === undefined ? fallback : (referencedVariable(value) as V | undefined);\n}\n\n/**\n * The variables a connection on disk actually uses.\n *\n * `undefined` for a credential the file holds as a literal: an editable\n * connection may carry a real client id rather than a reference, and that value\n * is not read from anywhere, so there is nothing to publish to and nothing for\n * another connection to collide with.\n */\nexport type StoredVariables = {\n readonly clientId: ClientIdVariable | undefined;\n readonly clientSecret: ClientSecretVariable | undefined;\n};\n\n/**\n * Stop when a connection document hands back a credential value.\n *\n * `client_secret` is always a `${{ NAME }}` reference — the syncer refuses to\n * upload anything else — so a value here is the server having resolved the\n * reference. Every path that reaches this has somewhere worse to put it than a\n * log: a plan preview prints it, and a file written from it would commit it to\n * `.zitadel/idps/`, which is the one place the secret must never reach.\n */\nexport function refuseResolvedSecret(definition: object, id: string): void {\n const block = (definition as Record<string, unknown>).oidc;\n const stored = isObject(block) ? block.client_secret : undefined;\n if (typeof stored === \"string\" && !isVariableReference(stored)) {\n throw new ZitadelError(\"E_VALIDATION\", `${id} came back holding a client_secret value`, {\n hint:\n \"A stored connection must keep the ${{ NAME }} reference. Report this: the endpoint \" +\n \"is resolving secrets, and the value would be written to disk.\",\n details: { id, block: \"oidc\" },\n });\n }\n}\n\n/**\n * Stop when two connections' credentials would land in the same variable.\n *\n * Two ways that happens. A slug may hold `-` and `_`\n * (`^[a-z0-9][a-z0-9_-]*$`) and the variable name replaces every\n * non-alphanumeric with `_`, so `google-work` and `google_work` both read\n * `GOOGLE_WORK_CLIENT_SECRET`. And a connection is editable, so one may simply\n * point at a name another already uses, or point both of its own credentials\n * at one name. Either way a publish overwrites what the other credential put\n * there, and the loser signs in with the wrong application — a failure that\n * surfaces at the provider, not here.\n *\n * What an existing file *references* is what counts, not what its slug would\n * derive: an `okta` connection referencing `GOOGLE_CLIENT_SECRET` collides\n * with Google however its slug reads.\n *\n * The derivation stays legible on purpose — these names get typed into\n * `variable set` by hand — so the ambiguity is refused rather than encoded\n * around.\n *\n * @param ours - The variables this run will publish to.\n * @param except - The connection being reused, which is not its own collision.\n */\nfunction refuseCollidingVariables(\n ours: StoredVariables,\n slug: ConnectionSlug,\n files: readonly ConnectionFile[],\n except?: ConnectionFile,\n): void {\n // The one place the two kinds of name are compared on purpose: both credentials\n // pointing at the same variable.\n if (ours.clientId !== undefined && (ours.clientId as string) === ours.clientSecret) {\n throw new ZitadelError(\n \"E_CONFLICT\",\n `This connection points both credentials at ${ours.clientId}`,\n {\n hint: \"Give client_id and client_secret separate ${{ NAME }} references, then run the command again.\",\n details: { slug, variable: ours.clientId },\n },\n );\n }\n for (const file of files) {\n if (file === except) {\n continue;\n }\n // A file with no usable slug has no derived names, but what it references\n // explicitly is still read, however its slug reads.\n const theirSlug = parseConnectionSlug(String(file.body.slug ?? \"\"));\n const theirs = credentialVariablesOf(file, theirSlug.ok ? theirSlug.value : undefined);\n // A literal on either side names no variable, so it cannot collide.\n const shared = [ours.clientId, ours.clientSecret].find(\n (name) => name !== undefined && (name === theirs.clientId || name === theirs.clientSecret),\n );\n if (shared === undefined) {\n continue;\n }\n throw new ZitadelError(\"E_CONFLICT\", `${file.path} and ${slug} both use ${shared}`, {\n hint: \"Point one of them at a variable of its own, then run the command again.\",\n details: {\n file: file.path,\n slug,\n other_slug: theirSlug.ok ? theirSlug.value : String(file.body.slug ?? \"\"),\n variable: shared,\n },\n });\n }\n}\n\n/** What the caller should do with the provider's connection. */\nexport type ConnectionPlan =\n | {\n readonly action: \"reuse\";\n readonly file: ConnectionFile;\n readonly slug: ConnectionSlug;\n /** Settings the developer gave that the existing file does not have, and so were not applied. */\n readonly notApplied?: readonly (\"display name\" | \"scopes\")[];\n }\n | {\n readonly action: \"create\";\n readonly name: string;\n readonly path: string;\n readonly slug: ConnectionSlug;\n /** Files that already connect to this provider's issuer under another slug. */\n readonly alsoUsesIssuer?: readonly string[];\n };\n\n/**\n * Decide whether a catalog provider already has a connection in this Project.\n *\n * Reuse is the default: a Project has one connection per provider, and a\n * second one for the same provider is nearly always an accident. Anything\n * ambiguous stops instead of guessing, because both alternatives — editing\n * the wrong connection, or silently adding a duplicate — are worse than\n * asking the developer which they meant.\n *\n * @param clientId - When given, a single match whose client id differs is a\n * conflict rather than a reuse: the developer is pointing at a different\n * OAuth application than the one already configured.\n */\nfunction planCatalogConnection(options: {\n readonly provider: IdpProvider;\n readonly files: readonly ConnectionFile[];\n readonly clientId?: ClientId;\n /** How the calling command spells the slug flag, for the hints. */\n readonly slugFlag: string;\n}): ConnectionPlan {\n const entry = options.provider;\n const slug = entry.slug;\n const matches = options.files.filter((file) => describesProvider(file, entry));\n\n if (matches.length > 1) {\n const names = matches.map((m) => m.path).join(\", \");\n throw new ZitadelError(\n \"E_CONFLICT\",\n `More than one ${entry.displayName} connection exists: ${names}`,\n {\n hint: \"Keep the one this Project should use and remove the others, then run the command again.\",\n details: { provider: slug, files: matches.map((m) => m.path) },\n },\n );\n }\n\n const [match] = matches;\n if (match !== undefined) {\n refuseDifferentClientId(match, options.clientId);\n // A file can match on template or issuer while carrying no slug of its\n // own. Inventing the provider's would point the schema and every flow at\n // an identity the connection does not declare, and the server rejects the\n // connection on the next apply for want of it.\n const matchSlug = parseConnectionSlug(String(match.body.slug ?? \"\"));\n if (!matchSlug.ok) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `${match.path} is a ${entry.displayName} connection with no usable slug`,\n {\n hint: \"Give the connection file a slug -- the schemas and flows reference it by that name.\",\n details: { file: match.path, problem: matchSlug.problem },\n },\n );\n }\n refuseCollidingVariables(\n credentialVariablesOf(match, matchSlug.value),\n matchSlug.value,\n options.files,\n match,\n );\n return { action: \"reuse\", file: match, slug: matchSlug.value };\n }\n\n // No match. The scaffolded name is the slug, so an unrelated file already\n // sitting there would be overwritten — refuse rather than replace it.\n const name = `${slug}.json`;\n const path = `${IDPS_DIR}/${name}`;\n const occupied = options.files.find((file) => file.name === name);\n if (occupied !== undefined) {\n const theirSlug = String(occupied.body.slug ?? \"\").trim();\n // The same name on a connection to somewhere else is not the provider's.\n throw new ZitadelError(\n \"E_CONFLICT\",\n theirSlug === slug\n ? `${path} is a connection called ${slug}, but not to ${entry.displayName}: its issuer is not ${entry.issuer}`\n : `${path} already exists and its slug is ${theirSlug === \"\" ? \"missing\" : theirSlug}, not ${slug}`,\n {\n hint:\n theirSlug === slug\n ? `Point it at ${entry.displayName} if it is that connection. Otherwise change its slug, in the file and in the schemas and flows that name it, then run the command again.`\n : `Rename or remove that file, or give it the slug ${slug} if it is the ${entry.displayName} connection, then run the command again.`,\n details: { file: path, slug: occupied.body.slug ?? null },\n },\n );\n }\n refuseCollidingVariables(credentialVariables(slug), slug, options.files);\n // A hand-written connection to the same issuer under another slug is not\n // claimed, so this adds a second button for the provider. Say so.\n const alsoUsesIssuer = options.files\n .filter((file) => isObject(file.body.oidc) && file.body.oidc.issuer === entry.issuer)\n .map((file) => file.path);\n return {\n action: \"create\",\n name,\n path,\n slug,\n ...(alsoUsesIssuer.length > 0 ? { alsoUsesIssuer } : {}),\n };\n}\n\n/**\n * Stop when the developer names a client id other than the one a connection\n * already holds.\n *\n * A scaffolded connection stores `${{ NAME }}`, not an id, so there is no\n * identity in the file to disagree with and the command stays idempotent.\n * A hand-written connection may still hold a literal, and that one is\n * worth refusing: rerunning with a different id would otherwise reuse a\n * file configured for another client.\n */\nfunction refuseDifferentClientId(match: ConnectionFile, clientId: ClientId | undefined): void {\n const existing = clientIdOf(match);\n const literal = existing !== undefined && !isVariableReference(existing);\n if (clientId !== undefined && literal && existing !== clientId) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `${match.path} already uses client id ${existing}, not ${clientId}`,\n {\n hint: \"Edit the connection file to change its client id, or run the command without one to reuse it.\",\n details: {\n file: match.path,\n stored_client_id: existing,\n supplied_client_id: clientId,\n },\n },\n );\n }\n}\n\n/**\n * Decide what to do with a custom connection, identified by the slug the\n * developer supplied.\n *\n * Unlike {@link planConnection} this never looks at the template or the\n * issuer to find a connection: a Project may hold several connections to one\n * issuer, with different credentials or mappings, and what tells them apart\n * is the name. The slug is also what schemas and flows reference, so it is\n * the only thing that can say \"the same connection\".\n *\n * A slug already in use is reused only when it is the same provider — the\n * same issuer — so that repeating a command changes nothing. The same name on\n * a connection to somewhere else is somebody else's, and replacing it would\n * repoint every schema and flow that names it.\n */\nfunction planCustomConnection(options: {\n readonly input: CustomOidcInput;\n readonly files: readonly ConnectionFile[];\n readonly clientId?: ClientId;\n /** Whether `--scopes` was passed: a default nobody asked for has not been contradicted. */\n readonly scopesGiven?: boolean;\n /** How the calling command spells the slug flag, for the hints. */\n readonly slugFlag: string;\n}): ConnectionPlan {\n const { slug, issuer } = options.input;\n const name = `${slug}.json`;\n const path = `${IDPS_DIR}/${name}`;\n const match = checkCustomSlug(options.files, slug, options.slugFlag);\n if (match === undefined) {\n return { action: \"create\", name, path, slug };\n }\n\n refuseChangedIssuer(match, slug, issuer, options.slugFlag);\n const oidc = match.body.oidc;\n refuseDifferentClientId(match, options.clientId);\n refuseCollidingVariables(credentialVariablesOf(match, slug), slug, options.files, match);\n const storedScopes = isObject(oidc) && Array.isArray(oidc.scopes) ? oidc.scopes.join(\" \") : \"\";\n const notApplied = [\n ...(match.body.display_name === options.input.displayName ? [] : ([\"display name\"] as const)),\n ...(options.scopesGiven !== true || storedScopes === options.input.scopes.join(\" \")\n ? []\n : ([\"scopes\"] as const)),\n ];\n return { action: \"reuse\", file: match, slug, ...(notApplied.length > 0 ? { notApplied } : {}) };\n}\n\n/**\n * What a custom connection's slug alone decides: the file it already names, or\n * a refusal. More than one file with the slug, or a file name the slug would\n * take that holds another connection, or variable names a new connection would\n * collide on, are all knowable before anything else about the connection is, so\n * a command can raise them as soon as it has the slug.\n *\n * @returns The single file that declares the slug, or `undefined` when the\n * slug is free and a new connection can be created.\n */\nexport function checkCustomSlug(\n files: readonly ConnectionFile[],\n slug: ConnectionSlug,\n slugFlag: string,\n): ConnectionFile | undefined {\n const name = `${slug}.json`;\n const path = `${IDPS_DIR}/${name}`;\n const holders = files.filter((file) => String(file.body.slug ?? \"\").trim() === slug);\n\n if (holders.length > 1) {\n throw new ZitadelError(\n \"E_CONFLICT\",\n `More than one connection is named ${slug}: ${holders.map((h) => h.path).join(\", \")}`,\n {\n hint: \"A slug names one connection. Remove or rename all but one, then run the command again.\",\n details: { slug, files: holders.map((h) => h.path) },\n },\n );\n }\n\n const [match] = holders;\n if (match !== undefined) {\n return match;\n }\n // Nothing declares the slug, but the file name is where this one would go.\n if (files.some((file) => file.name === name)) {\n throw new ZitadelError(\n \"E_CONFLICT\",\n `${path} already exists and is not the ${slug} connection`,\n {\n hint: `Rename or remove that file, or choose another ${slugFlag}, then run the command again.`,\n details: { file: path, slug },\n },\n );\n }\n refuseCollidingVariables(credentialVariables(slug), slug, files);\n return undefined;\n}\n\n/**\n * Refuse an issuer other than the one an existing connection was written with.\n * An applied connection keeps its issuer, so naming another one for the same\n * slug is a conflict, raised as soon as both are known.\n */\nexport function refuseChangedIssuer(\n file: ConnectionFile,\n slug: ConnectionSlug,\n issuer: string,\n slugFlag: string,\n): void {\n const oidc = file.body.oidc;\n const existingIssuer =\n isObject(oidc) && typeof oidc.issuer === \"string\" ? oidc.issuer : undefined;\n if (existingIssuer === issuer) {\n return;\n }\n throw new ZitadelError(\n \"E_CONFLICT\",\n existingIssuer === undefined\n ? `${file.path} is already named ${slug} and is not an OIDC connection to ${issuer}`\n : `${file.path} is already named ${slug} and connects to ${existingIssuer}, not ${issuer}`,\n {\n hint: `An applied connection keeps its issuer, and the server compares it exactly, so even a trailing slash names another provider. Choose another ${slugFlag} for this connection, then move the schemas and flows that name the old one to it.`,\n details: { file: file.path, slug, issuer, existing_issuer: existingIssuer ?? null },\n },\n );\n}\n\n/**\n * The display name and issuer a custom connection's file holds, as written, for\n * the ones it has. Nothing is checked here: a hand-edited file may hold\n * anything. Scopes are left out because reusing a connection never applies them.\n */\nexport function storedCustomSettings(file: ConnectionFile): {\n displayName?: string;\n issuer?: string;\n} {\n const oidc = file.body.oidc;\n return {\n ...(typeof file.body.display_name === \"string\" ? { displayName: file.body.display_name } : {}),\n ...(isObject(oidc) && typeof oidc.issuer === \"string\" ? { issuer: oidc.issuer } : {}),\n };\n}\n\n/**\n * Decide what to do with the connection for a provider in this Project.\n *\n * A catalog provider has one connection, found by what it is. Reuse is the\n * default: a second one for the same provider is nearly always an accident.\n * A custom connection is found by the slug the developer gave it, because a\n * Project may hold several connections to one issuer and the name is the only\n * thing that tells them apart.\n *\n * Anything ambiguous stops instead of guessing, because both alternatives —\n * editing the wrong connection, or silently adding a duplicate — are worse\n * than asking the developer which they meant.\n *\n * @param clientId - When given, a single match whose client id differs is a\n * conflict rather than a reuse: the developer is pointing at a different\n * OAuth application than the one already configured.\n */\nexport function planConnection(options: {\n readonly selection: ProviderSelection;\n readonly files: readonly ConnectionFile[];\n readonly clientId?: ClientId;\n readonly scopesGiven?: boolean;\n /** How the calling command spells the slug flag, for the hints. */\n readonly slugFlag: string;\n}): ConnectionPlan {\n const { selection, files, clientId, scopesGiven, slugFlag } = options;\n return selection.kind === \"custom\"\n ? planCustomConnection({ input: selection.connection, files, clientId, scopesGiven, slugFlag })\n : planCatalogConnection({ provider: idpProvider(selection.id), files, clientId, slugFlag });\n}\n","/**\n * Enabling a provider on an existing Project edits two files: the user schema\n * gains an `sso` authentication method, and the login flow gains the steps and\n * routes a provider round trip needs.\n *\n * Both functions are pure — they take parsed documents and return new ones, so\n * the caller owns reading, writing and reporting. Both are idempotent: running\n * them again on their own output changes nothing.\n *\n * Only the regions below are ever written. Anything a developer has edited by\n * hand is left exactly as it stands and reported back, because silently\n * rewriting it would discard deliberate work.\n */\n\nimport { getDefaultLoginFlow, SETUP_PRESETS } from \"@zitadel/config/defaults\";\nimport type { ConnectionSlug } from \"@zitadel/config/idp\";\n\nimport { ZitadelError } from \"../errors\";\n\n/**\n * Steps a flow starts at, by purpose, plus the steps that collect an\n * identifier. The provider button belongs on all of them: a developer landing\n * on the first screen expects it there, and someone who has already gone to\n * the email screen should not have to go back for it.\n *\n * On the shipped password-first flow the login entry *is* `identifier`, so\n * this is exactly `identifier` and `register` — which is what the design's\n * reference flow shows. On passkey-first it also picks up the passkey entry\n * screen, which the reference never considered.\n */\nfunction providerSteps(flow: Json): string[] {\n const purposes = isObject(flow.purposes) ? flow.purposes : {};\n const names = [purposes.login, purposes.register, \"identifier\", \"register\"];\n const wanted: string[] = [];\n for (const name of names) {\n if (typeof name === \"string\" && !wanted.includes(name) && stepNamed(flow, name) !== undefined) {\n wanted.push(name);\n }\n }\n return wanted;\n}\n\n/**\n * The step a flow starts its login purpose at, which a transition that\n * re-purposes to `login` must target.\n *\n * The engine rejects a `purpose: \"login\"` transition pointing anywhere else,\n * so this cannot be hardcoded: `identifier` is only the password-first flow's\n * entry, and a passkey-first flow starts at its passkey screen.\n */\nfunction loginEntry(flow: Json): string | undefined {\n const purposes = isObject(flow.purposes) ? flow.purposes : {};\n const named = purposes.login;\n if (typeof named === \"string\" && stepNamed(flow, named) !== undefined) {\n return named;\n }\n // A flow that does not serve the login purpose has nowhere to send someone\n // who wants to sign in instead, and the validator rejects a transition that\n // re-purposes to a purpose the definition does not serve. Falling back to\n // `identifier` would write exactly that.\n return stepNamed(flow, \"identifier\") !== undefined && purposes.login !== undefined\n ? \"identifier\"\n : undefined;\n}\n\n/** Step the engine sends a new external identity to. */\nconst REGISTER_SSO = \"register-sso\";\n/** Step shown when the provider's email already has an account. */\nconst SSO_CONFLICT = \"sso-conflict\";\n/** The step that asks the identified user for a password. */\nconst PASSWORD_STEP = \"password\";\n\n/** Outcomes the engine fires after a provider returns, and where they go. */\nfunction providerOutcomes(terminal: string): Record<string, string> {\n return {\n sso_authenticated: terminal,\n sso_user_not_found: REGISTER_SSO,\n user_already_exists: SSO_CONFLICT,\n };\n}\n\n/**\n * The step a completed sign-in ends at.\n *\n * Derived, not assumed to be called `done`. Step names are not fixed by the\n * contract — `purposes` names entry points, not terminals — and what marks a\n * terminal is the `complete` property, which both shipped flows carry. A flow\n * whose terminal is called something else was valid before this edit, and\n * writing `done` into the generated routes would point them at a step that\n * does not exist: `validateFlowDefinition` rejects that on the next `deploy`\n * (\"transition ... targets unknown step\"), so enabling a provider would break\n * a flow that worked.\n *\n * `undefined` when the flow has no single terminal to route to, which the\n * caller refuses rather than guesses at.\n */\nfunction terminalStep(flow: Json): string | undefined {\n const complete = steps(flow).filter(\n (step) => step.complete !== undefined && typeof step.name === \"string\",\n );\n if (complete.length === 1) {\n return complete[0]?.name as string;\n }\n // A flow that marks no terminal, or several: fall back to the scaffolded\n // name if it is there, so an older hand-written flow still works.\n return stepNamed(flow, \"done\") === undefined ? undefined : \"done\";\n}\n\ntype Json = Record<string, unknown>;\ntype Step = Json & { name?: unknown };\n\n/** What a generator left alone, so the caller can say so. */\nexport type SsoSkipped = {\n /** The step that was left alone, e.g. `sso-conflict`. */\n readonly step: string;\n /** File-relative description, e.g. `steps.sso-conflict`. */\n readonly region: string;\n readonly reason: \"hand-edited\";\n};\n\nexport type SsoResult<T> = {\n readonly document: T;\n /** True when the document changed; false makes a rerun a no-op. */\n readonly changed: boolean;\n readonly skipped: SsoSkipped[];\n};\n\nfunction clone<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction isObject(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction steps(flow: Json): Step[] {\n return Array.isArray(flow.steps) ? (flow.steps as Step[]) : [];\n}\n\n/** Which document a refusal is about, for the region names it reports. */\nexport type SsoEditTarget = \"flow\" | \"schema\";\n\n/**\n * Why this document cannot be edited for SSO, or `undefined` when it can.\n *\n * The editors below read a missing region as empty and write the generated one\n * in its place. That is right for a document that has simply not got there yet,\n * and wrong for one whose region holds something else: that value was put there\n * by hand, and replacing it is the one thing these functions promise not to do.\n * A flow whose `steps` is a string, for instance, would otherwise be read as\n * having no steps and written back with two — the hand-written value gone, and\n * nothing said about it.\n *\n * Reported rather than skipped: unlike a hand-edited step, which the caller can\n * leave alone and still produce a working flow, none of the edits can proceed\n * here, so a partial success would be a misleading thing to report.\n */\nexport function ssoEditRefusal(document: object, target: SsoEditTarget): string | undefined {\n const body = document as Json;\n return target === \"flow\" ? flowRefusal(body) : schemaRefusal(body);\n}\n\nfunction flowRefusal(flow: Json): string | undefined {\n const providers = ssoProvidersRefusal(flow);\n if (providers !== undefined) {\n return providers;\n }\n // Last, because it is about where the generated routes point rather than\n // whether the document can be read at all.\n if (terminalStep(flow) === undefined) {\n return \"no step marks where a completed sign-in ends\";\n }\n return undefined;\n}\n\n/**\n * Why a flow's steps cannot be read for their provider lists, or `undefined`\n * when they can. This is all removing a provider needs\n * (`auth-method sso disable`): unlike enabling, it writes no route, so it does\n * not care where a completed sign-in ends.\n */\nexport function ssoProvidersRefusal(document: object): string | undefined {\n const flow = document as Json;\n if (flow.steps !== undefined && !Array.isArray(flow.steps)) {\n return \"steps is not a list\";\n }\n for (const [index, step] of steps(flow).entries()) {\n if (!isObject(step)) {\n return `steps[${index}] is not a step`;\n }\n const name = typeof step.name === \"string\" ? step.name : String(index);\n if (step.transitions !== undefined && !isObject(step.transitions)) {\n return `steps.${name}.transitions is not an object`;\n }\n // Owned like transitions are: `addProvider` reads a non-list as empty and\n // writes the generated list over it, so `sso_providers: \"github\"` would\n // become `[\"google\"]` with nothing said about the provider it replaced.\n if (step.sso_providers !== undefined && !Array.isArray(step.sso_providers)) {\n return `steps.${name}.sso_providers is not a list`;\n }\n }\n return undefined;\n}\n\nfunction schemaRefusal(schema: Json): string | undefined {\n const methods = schema[\"x-auth-methods\"];\n if (methods === undefined) {\n return undefined;\n }\n if (!isObject(methods)) {\n return \"x-auth-methods is not an object\";\n }\n if (methods.sso === undefined) {\n return undefined;\n }\n if (!isObject(methods.sso)) {\n return \"x-auth-methods.sso is not an object\";\n }\n // The meta-schema requires a boolean. A missing one or a string \"true\" is\n // neither on nor off, so it is refused rather than overwritten.\n if (typeof methods.sso.enabled !== \"boolean\") {\n return \"x-auth-methods.sso.enabled is not a boolean\";\n }\n const providers = methods.sso.providers;\n if (providers !== undefined && !Array.isArray(providers)) {\n return \"x-auth-methods.sso.providers is not a list\";\n }\n return undefined;\n}\n\nfunction stepNamed(flow: Json, name: string): Step | undefined {\n return steps(flow).find((step) => step.name === name);\n}\n\n/**\n * Enable the provider on a user schema.\n *\n * Only `x-auth-methods.sso` is touched: password and passkey configuration\n * belongs to whoever set it, and a provider is added to the list rather than\n * replacing it, so enabling a second one later keeps the first.\n */\nexport function applySsoToSchema(schema: object, slug: ConnectionSlug): SsoResult<object> {\n const document = clone(schema) as Json;\n const methods = isObject(document[\"x-auth-methods\"]) ? { ...document[\"x-auth-methods\"] } : {};\n const existing = isObject(methods.sso) ? methods.sso : undefined;\n const providers = Array.isArray(existing?.providers)\n ? [...(existing.providers as unknown[])]\n : [];\n\n if (existing?.enabled === true && providers.includes(slug)) {\n return { document: schema, changed: false, skipped: [] };\n }\n if (!providers.includes(slug)) {\n providers.push(slug);\n }\n methods.sso = { ...existing, enabled: true, providers };\n document[\"x-auth-methods\"] = methods;\n return { document, changed: true, skipped: [] };\n}\n\n/**\n * The properties this project collects when someone registers.\n *\n * Read from the register purpose's own entry step rather than from the schema:\n * that step is where the project decided what to ask for, and the use case\n * chosen at setup already shaped it (`minimal` asks for an email, `business`\n * also for names and a company). Taking the schema instead would collect every\n * property it defines, including ones the project deliberately does not ask\n * about.\n *\n * Credential fields are dropped. The provider is the proof for an account\n * `create_user_with_sso` creates, so the scaffold asks for no password. An\n * author who adds a password field gets it stored with the user.\n *\n * Falls back to the identifier-collecting step, and then to nothing, so a flow\n * shaped unlike the shipped one still produces a step that can collect the one\n * property the mutation cannot do without.\n */\nfunction registrationFields(flow: Json): string[] {\n const purposes = isObject(flow.purposes) ? flow.purposes : {};\n const named = typeof purposes.register === \"string\" ? purposes.register : \"register\";\n for (const name of [named, \"register\", \"identifier\"]) {\n const step = stepNamed(flow, name);\n const fields = isObject(step) && Array.isArray(step.fields) ? step.fields : [];\n const collected = fields.filter(\n (field): field is string => typeof field === \"string\" && !field.startsWith(\"x-auth-methods#\"),\n );\n if (collected.length > 0) {\n return collected;\n }\n }\n return [];\n}\n\n/**\n * The step that collects what the provider did not supply.\n *\n * It asks for everything registration asks for, because a provider is not\n * obliged to supply any of it: the engine creates the account outright when\n * the claims satisfy the schema and shows this step when they do not, and a\n * step that can only collect the identifier is a dead end for every property\n * beyond it.\n */\nfunction registerSsoStep(fields: string[], terminal: string): Step {\n return {\n name: REGISTER_SSO,\n fields,\n actions: [\n { name: \"submit\", kind: \"submit\", primary: true, text_key: `${REGISTER_SSO}.action.submit` },\n ],\n on_success: \"create_user_with_sso\",\n transitions: {\n submit: { target: terminal },\n user_already_exists: { target: SSO_CONFLICT },\n },\n };\n}\n\n/**\n * The step shown when the provider's email already has an account. It offers\n * only the methods the schema actually enables — a password box on a schema\n * without passwords is a dead end.\n */\nfunction ssoConflictStep(\n slug: ConnectionSlug,\n methods: { password: boolean; passkey: boolean },\n loginStep: string | undefined,\n terminal: string,\n): Step {\n const actions: Json[] = [];\n const fields: string[] = [];\n if (methods.password) {\n fields.push(\"x-auth-methods#password\");\n actions.push({\n name: \"submit\",\n kind: \"submit\",\n primary: true,\n text_key: `${SSO_CONFLICT}.action.submit`,\n });\n }\n if (methods.passkey) {\n actions.push({\n name: \"passkey\",\n kind: \"passkey\",\n primary: false,\n text_key: `${SSO_CONFLICT}.action.passkey`,\n });\n }\n if (loginStep !== undefined) {\n actions.push({\n name: \"sign_in\",\n kind: \"navigate\",\n primary: false,\n text_key: `${SSO_CONFLICT}.action.sign_in`,\n });\n }\n\n const transitions: Json = {};\n if (methods.password) {\n transitions.submit = { target: terminal };\n }\n if (methods.passkey) {\n transitions.passkey = { target: terminal };\n }\n transitions.sso_authenticated = { target: terminal };\n transitions.user_already_exists = { target: SSO_CONFLICT };\n if (loginStep !== undefined) {\n transitions.sign_in = { target: loginStep, purpose: \"login\" };\n }\n transitions.sso_user_not_found = { target: REGISTER_SSO };\n\n return { name: SSO_CONFLICT, fields, actions, sso_providers: [slug], transitions };\n}\n\n/**\n * Whether a step is still what this generator would write for it.\n *\n * Compared key-sorted at every depth: the CLI writes its managed files with a\n * stable serialiser, so a step that has been through `setup`\n * has its keys in a different order from the object built here while being\n * the same step. Comparing the raw JSON would report the generator's own\n * output as hand-edited.\n */\nfunction matches(step: Step, expected: Step): boolean {\n return canonical(withoutServerDefaults(step)) === canonical(withoutServerDefaults(expected));\n}\n\n/**\n * A step without what the platform leaves out when it answers.\n *\n * `setup` writes the canonical definition into the file, and the server\n * omits an action's `primary: false` (a default), an empty `fields` list, and\n * an empty `gates` map, so the step in the file is not byte for byte what this\n * generator wrote though it is the same step. Reading it as hand-edited would\n * skip the step on the next provider.\n */\nfunction withoutServerDefaults(step: Step): Step {\n const copy: Step = { ...step };\n for (const key of [\"fields\", \"gates\"]) {\n const value = copy[key];\n const empty = Array.isArray(value)\n ? value.length === 0\n : isObject(value) && Object.keys(value).length === 0;\n if (empty) {\n delete copy[key];\n }\n }\n if (Array.isArray(copy.actions)) {\n copy.actions = copy.actions.map((action) => {\n if (!isObject(action) || action.primary !== false) {\n return action;\n }\n const { primary: _default, ...rest } = action;\n return rest;\n });\n }\n return copy;\n}\n\nlet shippedPasswordForms: string[] | undefined;\n\n/**\n * The password steps the shipped flows carry, one per preset, in the form\n * {@link withoutSsoRoutes} reduces any password step to. A step that reduces to\n * one of these is the one `setup` wrote, however many providers it offers.\n * The shipped steps carry no provider routes, so the terminal does not matter.\n */\nfunction shippedPasswordSteps(): string[] {\n shippedPasswordForms ??= SETUP_PRESETS.flatMap((preset) => {\n const flow = getDefaultLoginFlow({ preset }) as unknown as Json;\n const step = stepNamed(flow, PASSWORD_STEP);\n return step === undefined ? [] : [canonical(withoutSsoRoutes(step, \"done\"))];\n });\n return shippedPasswordForms;\n}\n\n/**\n * A password step without what offering providers adds to it: the provider\n * list, and the routes this generator writes for what comes back from one.\n *\n * A route that goes somewhere else is the developer's and stays, which is what\n * makes the step read as edited. The platform's own rewrite is not an edit\n * ({@link withoutServerDefaults}).\n */\nfunction withoutSsoRoutes(step: Step, terminal: string): Step {\n const copy: Step = { ...withoutServerDefaults(step) };\n delete copy.sso_providers;\n if (isObject(copy.transitions)) {\n const written = providerOutcomes(terminal);\n copy.transitions = Object.fromEntries(\n Object.entries(copy.transitions).filter(\n ([outcome, route]) =>\n !(\n outcome in written &&\n isObject(route) &&\n route.target === written[outcome] &&\n Object.keys(route).length === 1\n ),\n ),\n );\n }\n return copy;\n}\n\n/**\n * Whether a password step already lists the provider and carries the routes the\n * generator writes, whatever else it has been edited to say.\n */\nfunction offersAlready(step: Step, slug: string, terminal: string): boolean {\n if (!Array.isArray(step.sso_providers) || !step.sso_providers.includes(slug)) {\n return false;\n }\n const transitions = isObject(step.transitions) ? step.transitions : {};\n return Object.entries(providerOutcomes(terminal)).every(([outcome, target]) => {\n const route = transitions[outcome];\n return isObject(route) && route.target === target;\n });\n}\n\n/** The provider list a step should end up with: what it has, plus this slug. */\nfunction mergedProviders(step: Step, slug: ConnectionSlug): unknown[] {\n const providers = Array.isArray(step.sso_providers) ? [...(step.sso_providers as unknown[])] : [];\n return providers.includes(slug) ? providers : [...providers, slug];\n}\n\n/**\n * Offer a provider on a step, keeping any already there. Returns whether the\n * step changed, so a rerun is a no-op.\n */\nfunction addProvider(step: Step, slug: string): boolean {\n const providers = Array.isArray(step.sso_providers) ? [...(step.sso_providers as unknown[])] : [];\n if (providers.includes(slug)) {\n return false;\n }\n providers.push(slug);\n step.sso_providers = providers;\n return true;\n}\n\n/** Stable JSON: object keys sorted at every depth, arrays left in order. */\nfunction canonical(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortKeys);\n }\n if (isObject(value)) {\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, sortKeys(value[key])]),\n );\n }\n return value;\n}\n\n/** Outcome keys the previous CLI wrote, and the names the engine now raises. */\nconst LEGACY_OUTCOMES: ReadonlyArray<readonly [string, string]> = [\n [\"callback\", \"sso_authenticated\"],\n [\"identity_unknown\", \"sso_user_not_found\"],\n];\n\n/**\n * Rename the previous outcome keys on every step, in place. The validator\n * rejects the old keys, so leaving them would make `auth-method sso enable`\n * write an invalid flow. Where a step already has the new key, that one wins. A\n * key that is also one of the step's action names is the action's transition\n * and stays. A new key that is an action name is refused: the old route would\n * be dropped for the action's. A legacy key with `purpose` or `action` is\n * refused: the new keys may declare neither, and dropping them would change the\n * author's routing.\n */\nfunction migrateLegacyOutcomes(document: Json): boolean {\n let changed = false;\n for (const step of steps(document)) {\n if (!isObject(step.transitions)) {\n continue;\n }\n const transitions = step.transitions;\n const actions = Array.isArray(step.actions) ? step.actions : [];\n const actionNames = new Set(\n actions.map((action) => (isObject(action) ? action.name : undefined)),\n );\n for (const [old, next] of LEGACY_OUTCOMES) {\n if (!(old in transitions) || actionNames.has(old)) {\n continue;\n }\n if (actionNames.has(next)) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `steps.${String(step.name)}: transition \"${old}\" is renamed to \"${next}\", which is an action on this step`,\n {\n hint: `Rename the action \"${next}\" on step \"${String(step.name)}\" (and its transition), then run auth-method sso enable again.`,\n details: { step: step.name, action: next },\n },\n );\n }\n if (!(next in transitions)) {\n const transition = transitions[old];\n if (\n isObject(transition) &&\n ((transition.purpose ?? null) !== null || (transition.action ?? null) !== null)\n ) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `steps.${String(step.name)}: transition \"${old}\" declares purpose or action, which \"${next}\" cannot`,\n {\n hint: `Remove purpose and action from the transition \"${old}\" on step \"${String(step.name)}\", then run auth-method sso enable again.`,\n details: { step: step.name, transition: old },\n },\n );\n }\n transitions[next] = transition;\n }\n delete transitions[old];\n changed = true;\n }\n }\n return changed;\n}\n\n/**\n * Refuse a flow where a step this command writes declares an action named like\n * an outcome key the generator writes on that step. Those names were free\n * before the rename; the generated route would silently replace the action's.\n */\nfunction refuseOutcomeActionCollision(document: Json): void {\n const outcomes = [\"sso_authenticated\", \"sso_user_not_found\", \"user_already_exists\"];\n const entries: Array<[string, string[]]> = [\n ...providerSteps(document).map((name) => [name, outcomes] as [string, string[]]),\n [SSO_CONFLICT, outcomes],\n [REGISTER_SSO, [\"user_already_exists\"]],\n [\"register-password\", [\"user_already_exists\"]],\n ];\n // A step can be listed twice (a provider step named `register-password`), so\n // its keys are the union of every entry, never just the last one.\n const written = new Map<string, Set<string>>();\n for (const [name, keys] of entries) {\n written.set(name, new Set([...(written.get(name) ?? []), ...keys]));\n }\n for (const [name, keys] of written) {\n const step = stepNamed(document, name);\n const actions = step !== undefined && Array.isArray(step.actions) ? step.actions : [];\n for (const action of actions) {\n if (isObject(action) && typeof action.name === \"string\" && keys.has(action.name)) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `steps.${name}: action \"${action.name}\" uses a name auth-method sso enable writes as an outcome on this step`,\n {\n hint: `Rename the action \"${action.name}\" on step \"${name}\" (and its transition), then run auth-method sso enable again.`,\n details: { step: name, action: action.name },\n },\n );\n }\n }\n }\n}\n\n/**\n * Add the provider to a login flow.\n *\n * @param enabled - The authentication methods the target schema enables,\n * which decide what the conflict step may offer.\n */\nexport function applySsoToFlow(\n flow: object,\n slug: ConnectionSlug,\n enabled: { password: boolean; passkey: boolean },\n): SsoResult<object> {\n const document = clone(flow) as Json;\n // Before any rewrite, so a refused flow is never half edited.\n refuseOutcomeActionCollision(document);\n const skipped: SsoSkipped[] = [];\n let changed = false;\n // `ssoEditRefusal` has already refused a flow with no terminal to route to,\n // so the caller never reaches here without one.\n const terminal = terminalStep(document) ?? \"done\";\n // First, so a step the previous CLI wrote matches today's template below.\n if (migrateLegacyOutcomes(document)) {\n changed = true;\n }\n\n for (const name of providerSteps(document)) {\n const step = stepNamed(document, name);\n if (step === undefined) {\n continue;\n }\n if (addProvider(step, slug)) {\n changed = true;\n }\n const transitions = isObject(step.transitions) ? { ...step.transitions } : {};\n for (const [outcome, target] of Object.entries(providerOutcomes(terminal))) {\n const current = transitions[outcome];\n // `user_already_exists` already points at the password step on a\n // register flow. Retargeting it is the point: the same outcome now also\n // fires for a provider return, and the conflict step offers everything\n // the password step did.\n if (isObject(current) && current.target === target) {\n continue;\n }\n transitions[outcome] = { target };\n changed = true;\n }\n step.transitions = transitions;\n }\n\n // The password step is where someone lands who typed their email rather than\n // clicking a provider. A user who signed up with a provider has no password,\n // so a step with only a password field is a dead end for them. It offers the\n // providers too, unless it has been edited by hand: it is a step the\n // developer is likely to have changed, and the editors only write into what\n // they recognise.\n const password = stepNamed(document, PASSWORD_STEP);\n if (password !== undefined && !providerSteps(document).includes(PASSWORD_STEP)) {\n if (offersAlready(password, slug, terminal)) {\n // Edited by hand and already carrying the provider and its routes, which\n // is what the warning asks for: there is nothing left to say.\n } else if (!shippedPasswordSteps().includes(canonical(withoutSsoRoutes(password, terminal)))) {\n skipped.push({\n step: PASSWORD_STEP,\n region: `steps.${PASSWORD_STEP}`,\n reason: \"hand-edited\",\n });\n } else {\n // Every provider the entry steps carry, not only the one named: a project\n // enabled before the password step offered providers has several to catch up.\n const offered = providerSteps(document).flatMap((name) => {\n const entry = stepNamed(document, name);\n return entry !== undefined && Array.isArray(entry.sso_providers)\n ? (entry.sso_providers as unknown[])\n : [];\n });\n for (const provider of new Set([...offered, slug])) {\n if (typeof provider === \"string\" && addProvider(password, provider)) {\n changed = true;\n }\n }\n const transitions = isObject(password.transitions) ? { ...password.transitions } : {};\n // The same routes as the entry steps. A collision here binds to the\n // identified user either way, and the conflict step says why they are\n // back and offers the other ways in; sending them to this step again\n // would show an unchanged form and a Back that shows it twice.\n for (const [outcome, target] of Object.entries(providerOutcomes(terminal))) {\n const current = transitions[outcome];\n if (!isObject(current) || current.target !== target) {\n transitions[outcome] = { target };\n changed = true;\n }\n }\n password.transitions = transitions;\n }\n }\n\n // The password registration step shares the outcome, so it has to route to\n // the same place or a taken email dead-ends there.\n const registerPassword = stepNamed(document, \"register-password\");\n if (registerPassword !== undefined) {\n const transitions = isObject(registerPassword.transitions)\n ? { ...registerPassword.transitions }\n : {};\n const current = transitions.user_already_exists;\n if (!isObject(current) || current.target !== SSO_CONFLICT) {\n transitions.user_already_exists = { target: SSO_CONFLICT };\n registerPassword.transitions = transitions;\n changed = true;\n }\n }\n\n const list = steps(document);\n const terminalIndex = list.findIndex((step) => step.name === terminal);\n const insertAt = terminalIndex === -1 ? list.length : terminalIndex;\n // Each step with every form the generator may have written it in before. The\n // conflict step follows the methods enabled, so one written when passkey was\n // off is still the generator's own output once passkey is on. `register-sso`\n // and the password step do not depend on the methods, so they have one form.\n const wanted: Array<{ step: Step; earlier: Step[] }> = [\n { step: registerSsoStep(registrationFields(document), terminal), earlier: [] },\n {\n step: ssoConflictStep(slug, enabled, loginEntry(document), terminal),\n earlier: [true, false].flatMap((password) =>\n [true, false].map((passkey) =>\n ssoConflictStep(slug, { password, passkey }, loginEntry(document), terminal),\n ),\n ),\n },\n ];\n let offset = 0;\n for (const { step, earlier } of wanted) {\n const name = step.name as string;\n const existing = stepNamed(document, name);\n if (existing === undefined) {\n list.splice(insertAt + offset, 0, step);\n offset += 1;\n changed = true;\n continue;\n }\n // The conflict step carries a provider list of its own, so a second\n // provider is added to it rather than replacing the first — otherwise the\n // generator would report its own output as hand-edited and leave the\n // screen offering only the provider that was enabled first. `register-sso`\n // declares none, so it is compared as written.\n const merged = step.sso_providers === undefined ? undefined : mergedProviders(existing, slug);\n const expected = merged === undefined ? step : { ...step, sso_providers: merged };\n // Compared as if the list were already merged, but without merging it. The\n // list is the generator's to extend; the rest of the step is not. Adding\n // the provider first and comparing afterwards reported a hand-edited step\n // as left alone while having already changed it -- the one thing the\n // report promises it did not do.\n const candidate = merged === undefined ? existing : { ...existing, sso_providers: merged };\n if (matches(candidate, expected)) {\n if (merged !== undefined && addProvider(existing, slug)) {\n changed = true;\n }\n } else if (\n merged !== undefined &&\n earlier.some((form) => matches(candidate, { ...form, sso_providers: merged }))\n ) {\n // What the generator wrote for other methods: bring it up to today's, in\n // the place it already has, keeping the providers it lists.\n list[list.indexOf(existing)] = expected;\n changed = true;\n } else {\n skipped.push({ step: name, region: `steps.${name}`, reason: \"hand-edited\" });\n }\n }\n document.steps = list;\n\n return changed || skipped.length > 0\n ? { document, changed, skipped }\n : { document: flow, changed: false, skipped };\n}\n\n/**\n * Remove a provider from a user schema (`auth-method sso disable`, ADR 070).\n *\n * Only `x-auth-methods.sso` is touched. The provider leaves the list, and when\n * none is left `sso` becomes `{ \"enabled\": false }`: the meta-schema requires\n * at least one provider whenever the list is present. A provider the schema\n * does not offer is a no-op.\n */\nexport function removeSsoFromSchema(schema: object, slug: string): SsoResult<object> {\n const document = clone(schema) as Json;\n const methods = isObject(document[\"x-auth-methods\"]) ? { ...document[\"x-auth-methods\"] } : {};\n const sso = methods.sso;\n if (!isObject(sso) || !Array.isArray(sso.providers) || !sso.providers.includes(slug)) {\n return { document: schema, changed: false, skipped: [] };\n }\n const providers = sso.providers.filter((provider) => provider !== slug);\n methods.sso = providers.length === 0 ? { enabled: false } : { ...sso, providers };\n document[\"x-auth-methods\"] = methods;\n return { document, changed: true, skipped: [] };\n}\n\n/**\n * Remove a provider from every step of a login flow that offers it.\n *\n * Only the `sso_providers` lists change; a list left empty is dropped. The\n * routes and steps `auth-method sso enable` added stay: without a provider they\n * are never reached, they validate as they are, and enabling a provider again\n * uses them as they stand rather than rebuilding them.\n */\nexport function removeSsoFromFlow(flow: object, slug: string): SsoResult<object> {\n const document = clone(flow) as Json;\n let changed = false;\n for (const step of steps(document)) {\n if (!Array.isArray(step.sso_providers) || !step.sso_providers.includes(slug)) {\n continue;\n }\n const providers = (step.sso_providers as unknown[]).filter((provider) => provider !== slug);\n if (providers.length === 0) {\n delete step.sso_providers;\n } else {\n step.sso_providers = providers;\n }\n changed = true;\n }\n return changed\n ? { document, changed, skipped: [] }\n : { document: flow, changed: false, skipped: [] };\n}\n","import {\n CUSTOM_PROVIDER,\n type CustomOidcInput,\n IDP_PROVIDERS,\n isLoopbackIssuer,\n RESERVED_SLUGS,\n parseConnectionSlug,\n parseDisplayName,\n parseIssuer,\n parseProviderSelection,\n parseScopes,\n type Parsed,\n type ProviderSelection,\n selectionName,\n} from \"@zitadel/config/idp\";\n\nimport { ZitadelError } from \"../errors\";\n\n/** What the developer typed for a custom connection, before it is checked. */\nexport type CustomFlagValues = {\n readonly slug?: string;\n readonly displayName?: string;\n readonly issuer?: string;\n readonly scopes?: string;\n};\n\n/** How a setting is spelled on the command line, so a message names the flag to fix. */\nexport type CustomFlagNames = {\n readonly provider: string;\n readonly slug: string;\n readonly displayName: string;\n readonly issuer: string;\n readonly scopes: string;\n};\n\n/**\n * The flag keys the two commands define for a custom connection, once. Each\n * command builds its flag definitions from these, reads its parsed flags\n * through them, and the names a message suggests come from them, so renaming\n * one renames the flag, what is read from it, and what is suggested.\n */\nexport const ENABLE_FLAG_KEYS = {\n provider: \"provider\",\n slug: \"slug\",\n displayName: \"display-name\",\n issuer: \"issuer\",\n scopes: \"scopes\",\n} as const;\n\n/** The `--sso-*` flags on `setup` that describe the same settings. */\nexport const SETUP_FLAG_KEYS = {\n provider: \"sso\",\n slug: \"sso-slug\",\n displayName: \"sso-display-name\",\n issuer: \"sso-issuer\",\n scopes: \"sso-scopes\",\n} as const;\n\ntype FlagKeys = {\n readonly provider: string;\n readonly slug: string;\n readonly displayName: string;\n readonly issuer: string;\n readonly scopes: string;\n};\n\nconst flagNamesOf = (keys: FlagKeys): CustomFlagNames => ({\n provider: `--${keys.provider}`,\n slug: `--${keys.slug}`,\n displayName: `--${keys.displayName}`,\n issuer: `--${keys.issuer}`,\n scopes: `--${keys.scopes}`,\n});\n\n/** The flags on `auth-method sso enable`, which a failed setup suggests running instead. */\nexport const ENABLE_FLAG_NAMES: CustomFlagNames = flagNamesOf(ENABLE_FLAG_KEYS);\n\n/** The `--sso-*` flags on `setup` that describe the same settings. */\nexport const SETUP_FLAG_NAMES: CustomFlagNames = flagNamesOf(SETUP_FLAG_KEYS);\n\n/**\n * What a command's parsed flags say about a custom connection. Typed by the\n * keys, so the flags a command parsed must carry them.\n */\nexport function customFlagValues<K extends FlagKeys>(\n flags: { readonly [P in K[\"slug\" | \"displayName\" | \"issuer\" | \"scopes\"]]?: string },\n keys: K,\n): CustomFlagValues {\n const read = (key: string) => (flags as Readonly<Record<string, string | undefined>>)[key];\n return {\n slug: read(keys.slug),\n displayName: read(keys.displayName),\n issuer: read(keys.issuer),\n scopes: read(keys.scopes),\n };\n}\n\n/**\n * How the target server reaches this machine's loopback: `allowed` for a\n * server `zitadel start` runs as a process with the loopback allow list,\n * `container` for one it runs in Docker, `unknown` for any other.\n */\nexport type LoopbackReach = \"allowed\" | \"container\" | \"unknown\";\n\n/** The warning a loopback issuer earns on a server that cannot reach it, or `undefined`. */\nexport function loopbackIssuerWarning(\n selection: ProviderSelection,\n reach: LoopbackReach = \"unknown\",\n): string | undefined {\n if (\n selection.kind !== \"custom\" ||\n !isLoopbackIssuer(selection.connection.issuer) ||\n reach === \"allowed\"\n ) {\n return undefined;\n }\n const { issuer } = selection.connection;\n return reach === \"container\"\n ? `${issuer} is on this machine, but the local server runs in Docker, where localhost is the container itself, so sign-in will fail. Start the server with \\`zitadel start --runtime binary\\` instead.`\n : `${issuer} is on this machine, and a server blocks requests to localhost unless NEXTGEN_HTTPCLIENT_ALLOW_LIST allows it, so sign-in will fail until it does. A server \\`zitadel start\\` runs allows it by default.`;\n}\n\n/**\n * What a command line describing a custom connection looks like, spelled with\n * the flags the command defines, for an error or a help example to show.\n */\nexport function customExample(flag: CustomFlagNames, withScopes = false): string {\n return [\n `${flag.provider} ${CUSTOM_PROVIDER}`,\n `${flag.slug} acme-sso`,\n `${flag.displayName} 'Acme SSO'`,\n `${flag.issuer} https://sso.acme.example`,\n ...(withScopes ? [`${flag.scopes} 'openid profile email groups'`] : []),\n ].join(\" \");\n}\n\n/** The names of the custom settings that were given, as the command spells them. */\nexport function givenCustomFlags(values: CustomFlagValues, flag: CustomFlagNames): string[] {\n return [\n [flag.slug, values.slug],\n [flag.displayName, values.displayName],\n [flag.issuer, values.issuer],\n [flag.scopes, values.scopes],\n ]\n .filter(([, value]) => value !== undefined)\n .map(([name]) => name as string);\n}\n\n/** One setting's complaint, under the flag that carried it. */\nfunction checkedUnder<T>(name: string, parsed: Parsed<T>): T {\n if (!parsed.ok) {\n throw new ZitadelError(\"E_VALIDATION\", `${name}: ${parsed.problem}`, {\n hint: `Fix ${name} and run the command again.`,\n details: { flag: name },\n });\n }\n return parsed.value;\n}\n\n/**\n * Check the settings that were given, and only those, naming the flag that\n * carried a bad one. For a run that will ask for the rest: a slug the server\n * would refuse is refused before the first question, as a missing client id is.\n */\nexport function checkGivenCustomFlags(values: CustomFlagValues, flag: CustomFlagNames): void {\n if (values.slug !== undefined) {\n checkedUnder(flag.slug, parseConnectionSlug(values.slug, RESERVED_SLUGS));\n }\n if (values.displayName !== undefined) {\n checkedUnder(flag.displayName, parseDisplayName(values.displayName));\n }\n if (values.issuer !== undefined) {\n checkedUnder(flag.issuer, parseIssuer(values.issuer));\n }\n if (values.scopes !== undefined) {\n checkedUnder(flag.scopes, parseScopes(values.scopes));\n }\n}\n\n/**\n * The provider a command line names, with its settings checked as a whole.\n *\n * A catalog provider is just its name. A custom one is described by the\n * settings that follow it, each checked against the contract the server\n * enforces on apply. Every complaint is raised here, so a caller that wants a\n * mistake named before a secret is asked for calls it before asking: being\n * turned away after typing a credential would mean typing it again. The\n * settings are flags on purpose — a name, issuer and scopes are what a script\n * or an agent supplies, and what a person can read back from their shell\n * history.\n */\nexport function selectionFromFlags(\n provider: string,\n values: CustomFlagValues,\n flag: CustomFlagNames,\n example: string,\n): ProviderSelection {\n const given = givenCustomFlags(values, flag);\n\n if (provider !== CUSTOM_PROVIDER) {\n // A catalog provider knows its own name, issuer and scopes, so a setting\n // given alongside it would be ignored, and an ignored flag reads as honoured.\n if (given.length > 0) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `${given.join(\", \")} only applies to a custom connection`,\n {\n hint: `Add ${flag.provider} ${CUSTOM_PROVIDER}, or remove ${given.length === 1 ? \"it\" : \"them\"}.`,\n details: { flags: given },\n },\n );\n }\n const selection = parseProviderSelection(provider);\n if (selection === undefined) {\n throw new ZitadelError(\"E_VALIDATION\", `Unknown provider ${provider}`, {\n hint: `Use one of ${[...IDP_PROVIDERS, CUSTOM_PROVIDER].join(\", \")}.`,\n });\n }\n return selection;\n }\n\n const { slug, displayName, issuer } = values;\n if (slug === undefined || displayName === undefined || issuer === undefined) {\n const missing = [flag.slug, flag.displayName, flag.issuer].filter(\n (name) => !given.includes(name),\n );\n throw new ZitadelError(\"E_VALIDATION\", `A custom connection needs ${missing.join(\", \")}`, {\n hint: `Describe the connection, e.g. ${example}`,\n details: { missing },\n });\n }\n const checked = checkedUnder;\n return {\n kind: \"custom\",\n connection: {\n slug: checked(flag.slug, parseConnectionSlug(slug, RESERVED_SLUGS)),\n displayName: checked(flag.displayName, parseDisplayName(displayName)),\n issuer: checked(flag.issuer, parseIssuer(issuer)),\n scopes: checked(flag.scopes, parseScopes(values.scopes)),\n },\n };\n}\n\n/**\n * The flags that restate a custom connection, for a command offered as text.\n *\n * Suggested commands are run verbatim, so a display name with a space or a\n * metacharacter in it must arrive as one argument. Nothing here is a\n * credential: the name, issuer and scopes are the developer's own settings.\n */\nexport function customFlagText(custom: CustomOidcInput, flag: CustomFlagNames): string {\n return flagText(\n {\n slug: custom.slug,\n displayName: custom.displayName,\n issuer: custom.issuer,\n scopes: custom.scopes.join(\" \"),\n },\n flag,\n );\n}\n\n/**\n * The `auth-method sso enable` arguments that add `selection` to a project:\n * the provider, and for a custom connection the settings that describe it. A\n * suggestion builder wraps them with the selector its command needs.\n */\nexport function ssoEnableArgs(selection: ProviderSelection): string {\n return `auth-method sso enable --provider ${selectionName(selection)}${\n selection.kind === \"custom\" ? ` ${customFlagText(selection.connection, ENABLE_FLAG_NAMES)}` : \"\"\n }`;\n}\n\n/** The same for whichever settings were given, each as one shell word. */\nexport function flagText(values: CustomFlagValues, flag: CustomFlagNames): string {\n const word = (value: string) =>\n /^[A-Za-z0-9_@%+=:,./-]+$/.test(value) ? value : `'${value.replaceAll(\"'\", \"'\\\\''\")}'`;\n return [\n [flag.slug, values.slug],\n [flag.displayName, values.displayName],\n [flag.issuer, values.issuer],\n [flag.scopes, values.scopes],\n ]\n .flatMap(([name, value]) => (value === undefined ? [] : [`${name} ${word(value)}`]))\n .join(\" \");\n}\n","import {\n type CatalogProviderId,\n type ConnectionEndpoints,\n idpProvider,\n parseIssuer,\n} from \"@zitadel/config/idp\";\n\nimport type { Asker } from \"../input\";\n\n/**\n * Ask where a provider lives, on a development run only.\n *\n * Someone working on the CLI runs it against a local stand-in constantly, and\n * before this the connection document had to be hand-edited afterwards and\n * re-applied. Someone who installed the CLI is configuring the real vendor and\n * must never meet the question — so it is gated on `developmentBuild`\n * (`isDevelopmentBuild()`, the explicit `ZITADEL_CLI_DEV` opt-in). A published\n * CLI never sets it, so the question stays out of its `--help` and prompts.\n *\n * Returns `undefined` for a normal run and for a scripted run, and the\n * catalog's own issuer is dropped when written, so an ordinary run produces\n * the document it would if none of this existed.\n */\nexport async function askConnectionEndpoints(options: {\n readonly provider: CatalogProviderId;\n readonly developmentBuild: boolean;\n /** How the question is asked: the running command's `input`. */\n readonly ask: Asker;\n}): Promise<ConnectionEndpoints | undefined> {\n const { provider, developmentBuild, ask } = options;\n if (!developmentBuild) {\n return undefined;\n }\n // Only the issuer is asked for, and only the issuer is written. The engine\n // accepts a connection that names every endpoint or none at all\n // (`requireAllOrNoEndpoints`): naming two of the four it needs -- it also\n // wants `jwks_uri`, and `userinfo_endpoint` unless id_token mapping is on --\n // is rejected as `idp.endpoints_partial`. Asking for four URLs to satisfy\n // that would be a worse question than asking for none, and a stand-in\n // serves its own discovery document just as the vendor does.\n // Validated against the connection contract rather than merely parsed: `new\n // URL` accepts `http://idp.internal:9100` and `file:///tmp/idp`, which would\n // be written to a connection that then fails on apply. Refusing at the prompt\n // puts the complaint where the value was typed.\n return {\n issuer: await ask({\n kind: \"text\",\n name: \"issuer\",\n message: \"What is the issuer URL of the provider?\",\n parse: parseIssuer,\n initialValue: idpProvider(provider).issuer,\n }),\n };\n}\n","import type {\n ClientId,\n ClientIdVariable,\n ClientSecret,\n ClientSecretVariable,\n} from \"@zitadel/config/idp\";\nimport { consola } from \"consola\";\n\nimport { reportWarning } from \"../warnings\";\nimport { type EnvironmentSelector, projectCommand, type SuggestedCommand } from \"../suggestion\";\n\n/**\n * Publishes one variable to the project.\n *\n * Injected rather than built here: this module decides what becomes of a\n * captured credential, and giving it an API client as well would tie that\n * decision to the whole platform surface. Both callers already hold a\n * connection to the project they just addressed.\n */\nexport type SecretPublisher = (\n name: ClientIdVariable | ClientSecretVariable,\n value: ClientId | ClientSecret,\n options: { readonly secret: boolean },\n) => Promise<void>;\n\n/** Whether a value reached the project's variables. */\nexport type PublishState = \"stored\" | \"deferred\" | \"failed\";\n\n/** Where a captured client secret ended up, for the command's summary. */\nexport type SecretOutcome = {\n readonly name: ClientSecretVariable;\n\n /**\n * The project's variables — the only place a credential is written. The\n * connection document references it as `${{ NAME }}` and the engine resolves\n * that from the project's variables and from nowhere else, so a local server\n * and Zitadel Cloud both need the value here.\n *\n * `deferred` when there was no value to publish or no project to publish to;\n * `failed` when the platform refused the call. Neither is fatal — the\n * connection is written either way and `variable set` publishes it later.\n */\n readonly published: PublishState;\n};\n\n/**\n * Publish a client secret to the project.\n *\n * Nothing is written to disk. The value is a credential, the project stores it\n * encrypted under the project's own key (ADR 029), and no runtime reads it\n * from the environment — the token exchange happens on the server. A copy in\n * `.env.local` would be a credential sitting in the working tree for the\n * convenience of nobody, and one `git add -A` away from being published.\n *\n * Passing no value publishes nothing and is not an error: the developer may\n * intend to publish it themselves.\n */\nexport async function storeClientSecret(options: {\n readonly name: ClientSecretVariable;\n readonly value?: ClientSecret;\n readonly publish?: SecretPublisher;\n}): Promise<SecretOutcome> {\n const { name, value, publish } = options;\n if (value === undefined) {\n return { name, published: \"deferred\" };\n }\n return { name, published: await publishSecret(publish, name, value) };\n}\n\n/**\n * Publish the connection's client id.\n *\n * An ordinary variable, not a secret: the id travels in the browser's\n * authorize URL, so it is public by construction and hiding it would only cost\n * the developer the ability to read back what was configured.\n */\nexport async function publishClientId(options: {\n readonly name: ClientIdVariable;\n readonly value: ClientId;\n readonly publish?: SecretPublisher;\n}): Promise<PublishState> {\n return publishSecret(options.publish, options.name, options.value, false);\n}\n\n/**\n * Send the value to the project, reporting a refusal instead of raising it.\n *\n * By the time this runs the connection document is already on disk and, in\n * `setup`, the whole project is provisioned. Failing the command there would\n * leave the developer with a half-written Project to clean up over something\n * one later command fixes, so the caller warns and points at `variable set`.\n */\nasync function publishSecret(\n publish: SecretPublisher | undefined,\n name: ClientIdVariable | ClientSecretVariable,\n value: ClientId | ClientSecret,\n secret = true,\n): Promise<PublishState> {\n if (publish === undefined) {\n return \"deferred\";\n }\n try {\n await publish(name, value, { secret });\n return \"stored\";\n } catch (error) {\n consola.debug(`Publishing ${name} to the project failed`, error);\n return \"failed\";\n }\n}\n\n/**\n * The `variable set` arguments that publish one credential to the project.\n *\n * Without `--preview` the write takes the platform's default: a client id,\n * which is not secret, is stored for both kinds, and a client secret for the\n * primary kind only. The engine resolves a connection's `${{ NAME }}` from the\n * project's own variables.\n */\nfunction republishArgsFor(\n name: ClientIdVariable | ClientSecretVariable,\n secret: boolean,\n): string[] {\n return [\"variable\", \"set\", name, ...(secret ? [\"--secret\"] : [])];\n}\n\n/**\n * The command that puts a credential the project never received where the\n * connection looks for it.\n *\n * Shared so the warning printed to a terminal and the `next_commands` a JSON\n * run reports cannot drift apart — a JSON run prints no warnings at all, so\n * that list is the only place the recovery step appears.\n */\nexport function republishCommand(\n name: ClientIdVariable | ClientSecretVariable,\n secret: boolean,\n cliVersion: string,\n selector: EnvironmentSelector,\n): SuggestedCommand {\n // `selector` carries the invocation's --env/--env-file/--server so the retry\n // targets the same project.\n return projectCommand(republishArgsFor(name, secret).join(\" \"), selector, cliVersion);\n}\n\n/** A credential, and whether the project ended up holding it. */\nexport type CredentialRecovery = {\n /** `undefined` when there is no such credential in this run at all. */\n readonly name: ClientIdVariable | ClientSecretVariable | undefined;\n readonly secret: boolean;\n readonly published: PublishState | undefined;\n};\n\n/**\n * The arguments that finish the job for every credential the project did not\n * receive — empty in the ordinary case, where both were stored.\n *\n * Argument lists rather than command strings, for a caller that also reports\n * them as `next_args`; {@link republishCommands} is built from this, so the\n * two forms list the same commands.\n *\n * @param credentials - Each credential of the run and what became of it.\n * @param extraArgs - Appended to every command, such as the `--cwd` the run\n * was given, so the recovery reaches the same Project.\n */\nexport function republishArgs(\n credentials: readonly CredentialRecovery[],\n extraArgs: readonly string[] = [],\n): string[][] {\n return credentials.flatMap(({ name, secret, published }) =>\n name !== undefined && published !== undefined && published !== \"stored\"\n ? [[...republishArgsFor(name, secret), ...extraArgs]]\n : [],\n );\n}\n\n/**\n * {@link republishArgs} as commands to run.\n *\n * Built for a run that prints nothing: with `--json` consola is disabled, so\n * the warnings above never appear and this list is the only place the recovery\n * step is stated.\n */\nexport function republishCommands(\n credentials: readonly CredentialRecovery[],\n cliVersion: string,\n selector: EnvironmentSelector,\n): SuggestedCommand[] {\n return republishArgs(credentials).map((args) =>\n projectCommand(args.join(\" \"), selector, cliVersion),\n );\n}\n\n/**\n * Say whether the project received a credential, and how to retry when it did\n * not. Shared by both credentials, because the project is the destination that\n * decides whether sign-in works and the wording should not drift between them.\n *\n * `noValue` separates the two ways a publish can be deferred: nothing was\n * supplied, or there was no project to publish to. They read the same to the\n * code and call for different things from the developer.\n */\nfunction reportPublished(\n name: ClientIdVariable | ClientSecretVariable,\n state: PublishState,\n republish: string,\n noValue: boolean,\n): void {\n switch (state) {\n case \"stored\":\n consola.success(`Published ${name} to the project`);\n break;\n case \"deferred\":\n reportWarning(\n noValue\n ? `${name} has no value yet. Publish it with: ${republish}`\n : `${name} was not published to the project. Publish it with: ${republish}`,\n );\n break;\n case \"failed\":\n reportWarning(`${name} could not be published. Sign-in fails until it is: ${republish}`);\n break;\n }\n}\n\n/** Tell the developer what became of the secret. */\nexport function reportSecretOutcome(\n outcome: SecretOutcome,\n cliVersion: string,\n noValue: boolean,\n selector: EnvironmentSelector,\n): void {\n reportPublished(\n outcome.name,\n outcome.published,\n republishCommand(outcome.name, true, cliVersion, selector),\n noValue,\n );\n}\n\n/**\n * Tell the developer what became of the client id.\n *\n * A missing one is never \"no value yet\": the command refuses without a client\n * id, so the only way here is a project it could not reach.\n */\nexport function reportClientIdOutcome(\n name: ClientIdVariable,\n state: PublishState,\n cliVersion: string,\n selector: EnvironmentSelector,\n): void {\n reportPublished(name, state, republishCommand(name, false, cliVersion, selector), false);\n}\n","/**\n * Public surface for the user-schema domain. Every caller outside this\n * module imports from here (not from individual files), the same\n * discipline as `lib/flows/`.\n *\n * **Source of truth.** The wire shape lives in\n * `@zitadel/api/generated/model` (orval-generated from the\n * OpenAPI spec). Callers that need the type import `CreateSchemaBody`\n * from there directly; callers that need the runtime validator import\n * the matching Zod schema from\n * `@zitadel/api/generated/endpoints/zitadelNextGen.zod`. The default\n * schema/flow bodies the CLI scaffolds are composed in\n * `@zitadel/config/defaults` (`getDefaultHumanUserSchema`) — the single\n * source of field defaults.\n *\n * **Dependency rule.** No upward imports (`commands/`, `sync/`, etc.)\n * and no filesystem I/O. Reading and writing local files is the\n * caller's responsibility, served by `apps/cli/src/lib/json-dir.ts`\n * plus this module's {@link SCHEMAS_DIR} constant.\n */\n\n/**\n * Relative directory (from the project root) where local user-schema\n * files live. Owned here so callers (`commands/*`, `sync/syncers.ts`)\n * and tests share a single source of truth for the path; the runtime\n * never depends on it directly because `lib/user-schema` does not touch\n * the filesystem. The counterpart of `lib/flows`' `FLOWS_DIR`.\n */\nexport const SCHEMAS_DIR = \".zitadel/schemas\";\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\n\nimport { FLOWS_DIR } from \"../flows\";\nimport { SCHEMAS_DIR } from \"../user-schema\";\nimport { isErrno, ZitadelError } from \"../errors\";\nimport { isObject } from \"../json\";\n\n/** A user-schema file, with what the command has to show about it. */\nexport type SchemaFile = {\n /** File name without `.json`, which is what `--schema` takes. */\n readonly name: string;\n /** Project-relative path, for the summary. */\n readonly path: string;\n /** Property names the schema defines, used to build the claim mapping. */\n readonly properties: string[];\n /** Authentication methods the schema enables today, for the summary. */\n readonly methods: string[];\n readonly body: Record<string, unknown>;\n};\n\n/**\n * The authentication methods a schema document enables, sorted: every entry\n * under `x-auth-methods` whose `enabled` is `true`. What the login engine can\n * actually serve is narrower, and is the caller's to decide.\n */\nexport function methodsOf(body: Record<string, unknown>): string[] {\n const methods = body[\"x-auth-methods\"];\n if (!isObject(methods)) {\n return [];\n }\n return Object.entries(methods)\n .filter(([, value]) => isObject(value) && value.enabled === true)\n .map(([name]) => name)\n .sort();\n}\n\n/**\n * Read the Project's user schemas.\n *\n * READMEs sit in the same directory, so only `.json` files count. A schema\n * that cannot be parsed stops the command: enabling a provider edits these\n * files, and editing one we could not read is how a working setup gets\n * corrupted.\n */\nexport async function readSchemaFiles(cwd: string): Promise<SchemaFile[]> {\n const dir = join(cwd, SCHEMAS_DIR);\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch (error) {\n // Only an absent directory means the Project has none. A permission or\n // I/O failure reported as \"no user schema\" would send the developer\n // looking for a missing file that is sitting right there.\n if (isErrno(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n const files: SchemaFile[] = [];\n for (const entry of entries.filter((e) => e.endsWith(\".json\")).sort()) {\n const path = `${SCHEMAS_DIR}/${entry}`;\n let body: unknown;\n try {\n body = JSON.parse(await readFile(join(dir, entry), \"utf8\"));\n } catch (error) {\n throw new ZitadelError(\"E_VALIDATION\", `${path} is not valid JSON`, {\n hint: \"Fix the file, then run the command again.\",\n details: { file: path, parse_error: String(error) },\n });\n }\n if (!isObject(body)) {\n throw new ZitadelError(\"E_VALIDATION\", `${path} does not contain a JSON object`, {\n details: { file: path },\n });\n }\n files.push({\n name: basename(entry, \".json\"),\n path,\n properties: isObject(body.properties) ? Object.keys(body.properties) : [],\n methods: methodsOf(body),\n body,\n });\n }\n return files;\n}\n\n/**\n * Pick the schema to change.\n *\n * One schema is the common case and is chosen without asking. Several is\n * ambiguous, and picking silently would edit the wrong user type, so the name\n * has to be given — the interactive picker is the caller's, because this\n * module does not prompt.\n */\nexport function selectSchema(files: readonly SchemaFile[], requested?: string): SchemaFile {\n if (files.length === 0) {\n throw new ZitadelError(\"E_NOT_FOUND\", `This Project has no user schema under ${SCHEMAS_DIR}`, {\n hint: \"Run `zitadel setup` first.\",\n });\n }\n if (requested !== undefined) {\n const wanted = requested.endsWith(\".json\") ? basename(requested, \".json\") : requested;\n const match = files.find((file) => file.name === wanted);\n if (match === undefined) {\n throw new ZitadelError(\"E_NOT_FOUND\", `This Project has no user schema named ${wanted}`, {\n hint: `Known schemas: ${files.map((f) => f.name).join(\", \")}`,\n details: { requested: wanted, known: files.map((f) => f.name) },\n });\n }\n return match;\n }\n const [only, ...rest] = files;\n if (rest.length > 0 || only === undefined) {\n throw new ZitadelError(\"E_VALIDATION\", \"This Project has more than one user schema\", {\n hint: `Name the one to change with --schema. Known schemas: ${files.map((f) => f.name).join(\", \")}`,\n details: { known: files.map((f) => f.name) },\n });\n }\n return only;\n}\n\n/** The login flow files a Project holds, with the names to report them by. */\nexport type FlowFile = {\n readonly name: string;\n readonly path: string;\n readonly body: Record<string, unknown>;\n};\n\n/**\n * Read the Project's flow files.\n *\n * A flow names the schema it runs against, so the caller can pick the ones\n * belonging to the schema being changed rather than editing every flow.\n */\nexport async function readFlowFiles(cwd: string): Promise<FlowFile[]> {\n const dir = join(cwd, FLOWS_DIR);\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch (error) {\n // Only an absent directory means the Project has none. A permission or\n // I/O failure reported as \"no user schema\" would send the developer\n // looking for a missing file that is sitting right there.\n if (isErrno(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n const files: FlowFile[] = [];\n for (const entry of entries.filter((e) => e.endsWith(\".json\")).sort()) {\n const path = `${FLOWS_DIR}/${entry}`;\n let body: unknown;\n try {\n body = JSON.parse(await readFile(join(dir, entry), \"utf8\"));\n } catch (error) {\n throw new ZitadelError(\"E_VALIDATION\", `${path} is not valid JSON`, {\n hint: \"Fix the file, then run the command again.\",\n details: { file: path, parse_error: String(error) },\n });\n }\n if (!isObject(body)) {\n throw new ZitadelError(\"E_VALIDATION\", `${path} does not contain a JSON object`, {\n details: { file: path },\n });\n }\n files.push({ name: basename(entry, \".json\"), path, body });\n }\n return files;\n}\n\n/** The authentication methods a schema document enables. */\nexport type AuthMethods = { password: boolean; passkey: boolean };\n\n/**\n * Read the enabled methods straight off a schema document.\n *\n * Setup composes its schema in memory and never reads it back from disk, so\n * it needs this before a {@link SchemaFile} exists.\n */\nexport function authMethods(body: Record<string, unknown>): AuthMethods {\n const enabled = methodsOf(body);\n return { password: enabled.includes(\"password\"), passkey: enabled.includes(\"passkey\") };\n}\n\n/** Whether a schema file enables a given authentication method. */\nexport function enabledMethods(schema: SchemaFile): AuthMethods {\n return {\n password: schema.methods.includes(\"password\"),\n passkey: schema.methods.includes(\"passkey\"),\n };\n}\n","/**\n * The groups the root help lists commands under, declared in print order and\n * named for what a developer is trying to do: get going, work against a local\n * server, manage who can sign in and how, change the project's configuration,\n * or check on it. Every command declares its own group (`static group` on the\n * class) so nothing has to be registered centrally; oclif's own utilities\n * (`autocomplete`, `search`, …) declare none and are listed with the last group.\n */\nexport const CommandGroups = {\n gettingStarted: \"Getting started\",\n localDevelopment: \"Local development\",\n usersAndTeams: \"Users and teams\",\n authentication: \"Authentication\",\n configuration: \"Configuration and releases\",\n diagnostics: \"Diagnostics and utilities\",\n} as const;\n\nexport type CommandGroup = (typeof CommandGroups)[keyof typeof CommandGroups];\n\nexport const COMMAND_GROUPS: readonly CommandGroup[] = Object.values(CommandGroups);\n\n/**\n * The order within a group, which the root help and the docs' CLI reference\n * (`./reference`) share: `groupOrder` first, lowest first, then the command id.\n */\nexport function compareInGroup(\n a: { id: string; groupOrder?: number },\n b: { id: string; groupOrder?: number },\n): number {\n return (\n (a.groupOrder ?? Number.MAX_SAFE_INTEGER) - (b.groupOrder ?? Number.MAX_SAFE_INTEGER) ||\n a.id.localeCompare(b.id)\n );\n}\n","/**\n * Local file references in `.zitadel/` resource files.\n *\n * Wherever the OpenAPI YAML marks a string field `x-local: file`, the\n * generated editor meta-schema accepts `{ \"$file\": \"<path>\" }` in its place,\n * so a long value such as a login template lives in its own file instead of a\n * JSON-escaped string. The API never sees a reference: before upload every\n * one is replaced by the referenced file's content.\n *\n * Resolution is generic. Nothing here knows which fields may carry a\n * reference; the Zod gate and the editor schema decide that.\n *\n * Paths are relative to the directory of the resource file that holds them\n * and must stay inside the project, because upload reads them. The check\n * applies to the real target: a symlink, or a symlinked directory on the way,\n * that leads outside the project is refused.\n */\nimport { lstatSync, readFileSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\n\nexport const FILE_REFERENCE_KEY = \"$file\";\n\nexport type FileReference = { readonly [FILE_REFERENCE_KEY]: string };\n\n/**\n * Where references resolve: the project root, and the directory (relative to\n * it) of the resource file holding them.\n */\nexport type FileReferenceContext = { readonly cwd: string; readonly baseDir: string };\n\n/** The keys and indexes that lead from a document's root to one value. */\ntype Path = ReadonlyArray<string | number>;\n\nconst omittedReference = Symbol(\"omittedReference\");\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction isErrno(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === code;\n}\n\n/** A file's content, or undefined when it is absent. */\nfunction readIfPresent(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf8\");\n } catch (error) {\n if (isErrno(error, \"ENOENT\") || isErrno(error, \"ENOTDIR\")) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction readFileReference(\n path: string,\n ref: string,\n options: { readonly onMissing: \"throw\" | \"omit\" },\n): string | typeof omittedReference {\n let content: string | undefined;\n try {\n content = readIfPresent(path);\n } catch {\n throw new ZitadelError(\"E_VALIDATION\", `$file ${JSON.stringify(ref)} cannot be read`, {\n hint: \"Create the referenced file or fix the path.\",\n });\n }\n if (content !== undefined) {\n return content;\n }\n if (options.onMissing === \"omit\") {\n return omittedReference;\n }\n throw new ZitadelError(\"E_VALIDATION\", `$file ${JSON.stringify(ref)} cannot be read`, {\n hint: \"Create the referenced file or fix the path.\",\n });\n}\n\n/** Whether `path` is `root` itself or lies beneath it. */\nfunction isWithin(root: string, path: string): boolean {\n const rel = relative(root, path);\n return !(rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel));\n}\n\n/** Whether `path` itself is a symlink, without following it. */\nfunction isSymlink(path: string): boolean {\n try {\n return lstatSync(path).isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * `path` with every symlink resolved, symlinked parent directories included,\n * even when its last segments do not exist yet. Undefined when a segment is a\n * symlink that resolves nowhere, since what it names could be anywhere.\n */\nfunction realTarget(path: string): string | undefined {\n const missing: string[] = [];\n let current = path;\n for (;;) {\n try {\n return join(realpathSync(current), ...missing);\n } catch (error) {\n if (!isErrno(error, \"ENOENT\") && !isErrno(error, \"ENOTDIR\")) {\n throw error;\n }\n if (isSymlink(current)) {\n return undefined;\n }\n const parent = dirname(current);\n if (parent === current) {\n return path;\n }\n missing.unshift(basename(current));\n current = parent;\n }\n }\n}\n\n/** A `{ \"$file\": \"<path>\" }` object and nothing else. */\nexport function isFileReference(value: unknown): value is FileReference {\n return (\n isPlainObject(value) &&\n Object.keys(value).length === 1 &&\n typeof value[FILE_REFERENCE_KEY] === \"string\"\n );\n}\n\n/**\n * The absolute path a reference points at. E_VALIDATION when the path, or the\n * real target behind any symlink on the way, leaves the project.\n */\nexport function resolveFileReference(context: FileReferenceContext, ref: string): string {\n const absolute = resolve(context.cwd, context.baseDir, ref);\n const root = realTarget(resolve(context.cwd));\n const target = realTarget(absolute);\n const inside =\n isWithin(resolve(context.cwd), absolute) &&\n root !== undefined &&\n target !== undefined &&\n isWithin(root, target);\n if (!inside) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `$file ${JSON.stringify(ref)} points outside the project`,\n {\n hint:\n \"Keep referenced files inside the project, next to the file that references them; \" +\n \"a symlink on the way must resolve inside the project too.\",\n },\n );\n }\n return absolute;\n}\n\n/** Every reference in `document`, with the path that leads to it. */\nexport function findFileReferences(document: unknown): Array<{ path: Path; ref: string }> {\n const found: Array<{ path: Path; ref: string }> = [];\n const walk = (node: unknown, path: Path): void => {\n if (isFileReference(node)) {\n found.push({ path, ref: node[FILE_REFERENCE_KEY] });\n } else if (Array.isArray(node)) {\n node.forEach((item, index) => {\n walk(item, [...path, index]);\n });\n } else if (isPlainObject(node)) {\n for (const [key, value] of Object.entries(node)) {\n walk(value, [...path, key]);\n }\n }\n };\n walk(document, []);\n return found;\n}\n\n/**\n * Returns a copy of `document` with every reference replaced by the content\n * of the file it points at. With `onMissing: \"throw\"` an unreadable file is\n * E_VALIDATION, which is what plan's gate wants; with `\"omit\"` the value is\n * dropped instead (the key from an object, the element from an array), so\n * normalizing and hashing stay total. A path leaving the project is always\n * E_VALIDATION.\n */\nexport function inlineFileReferences<T>(\n document: T,\n context: FileReferenceContext,\n options: { readonly onMissing: \"throw\" | \"omit\" },\n): T {\n const inline = (node: unknown): unknown => {\n if (isFileReference(node)) {\n const ref = node[FILE_REFERENCE_KEY];\n return readFileReference(resolveFileReference(context, ref), ref, options);\n }\n if (Array.isArray(node)) {\n return node.map(inline).filter((item) => item !== omittedReference);\n }\n if (isPlainObject(node)) {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n const inlined = inline(value);\n if (inlined !== omittedReference) {\n out[key] = inlined;\n }\n }\n return out;\n }\n return node;\n };\n return inline(document) as T;\n}\n","import { relative } from \"node:path\";\n\nimport { ZitadelError } from \"../errors\";\nimport {\n type FileReferenceContext,\n findFileReferences,\n inlineFileReferences,\n resolveFileReference,\n} from \"../local-files\";\n\n/**\n * Relative directory (from the project root) where local branding files live:\n * the `branding.json` descriptor plus the sibling `.liquid` template it\n * references. Owned here so commands, syncers, and tests share one source of\n * truth; only `*.json` files are sync-discovered, the template rides along as\n * a `$file` reference in `liquid_template`.\n */\nexport const BRANDING_DIR = \".zitadel/branding\";\n\n/**\n * The key descriptors used before `$file` references. It is still recognised\n * so plan can say how to migrate instead of reporting an unknown key.\n */\nconst LEGACY_TEMPLATE_FILE_KEY = \"liquid_template_file\";\n\n/**\n * References in a descriptor resolve against its directory; all descriptors\n * live flat in {@link BRANDING_DIR}.\n */\nconst referenceContext = (cwd: string): FileReferenceContext => ({ cwd, baseDir: BRANDING_DIR });\n\n/** E_VALIDATION with a migration hint when a descriptor still carries `liquid_template_file`. */\nexport function assertNoLegacyTemplateKey(data: object): void {\n const legacy = (data as Record<string, unknown>)[LEGACY_TEMPLATE_FILE_KEY];\n if (legacy === undefined) {\n return;\n }\n const path = typeof legacy === \"string\" ? legacy : \"./login.liquid\";\n throw new ZitadelError(\"E_VALIDATION\", `${LEGACY_TEMPLATE_FILE_KEY} is no longer supported`, {\n hint: `Replace it with \"liquid_template\": { \"$file\": ${JSON.stringify(path)} }.`,\n });\n}\n\n/**\n * Returns the template string a descriptor carries, inline or behind a\n * `$file` reference. Undefined when it has none (a legal descriptor that only\n * sets layout or asset URLs); E_VALIDATION when a reference cannot be read.\n */\nexport function readDescriptorTemplate(cwd: string, data: object): string | undefined {\n const { liquid_template } = inlineFileReferences(\n data as { liquid_template?: unknown },\n referenceContext(cwd),\n { onMissing: \"throw\" },\n );\n return typeof liquid_template === \"string\" ? liquid_template : undefined;\n}\n\n/**\n * Converts a local descriptor to the wire body of `POST /branding`: strips the\n * editor `$schema` affordance and inlines every `$file` reference. Non-throwing\n * on an unreadable file (the field is left out) so normalizing and hashing stay\n * total; `validate` reports that case with a hint before any planning happens.\n */\n/**\n * The project-relative files a descriptor's `$file` references point at, for a\n * diff's pathspec: the bundle inlines them, so editing one changes what a\n * deploy publishes even though the file may sit outside `.zitadel/branding/`.\n */\nexport function brandingReferencePaths(cwd: string, data: object): string[] {\n return findFileReferences(data).map(({ ref }) =>\n relative(cwd, resolveFileReference(referenceContext(cwd), ref)),\n );\n}\n\nexport function toBrandingWireBody(cwd: string, data: object): object {\n const { $schema, ...rest } = data as { $schema?: unknown };\n void $schema;\n return inlineFileReferences(rest, referenceContext(cwd), { onMissing: \"omit\" });\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\n\n/** One `*.json` file read by {@link readJsonDirEntries}: its file name and parsed body. */\nexport type JsonDirEntry = { name: string; body: Record<string, unknown> };\n\n/**\n * Read every `*.json` file under `absDir` and return each body as a plain\n * object. Files are read in lexical filename order so the result is\n * deterministic for downstream hashing and diffs. Each file is parsed by\n * `JSON.parse`; this function does **not** apply any schema validation —\n * unknown keys, forward-compatible fields, and `${VAR}` placeholders survive\n * intact. Callers that need a typed shape pass the result through their\n * resource's Zod schema.\n *\n * Returns an empty array when the directory is missing. Throws `E_VALIDATION`\n * `ZitadelError` on invalid JSON or when a file's root value is not an object.\n *\n * @param absDir - Absolute path to the directory to scan.\n */\nexport async function readJsonDir(absDir: string): Promise<ReadonlyArray<Record<string, unknown>>> {\n return (await readJsonDirEntries(absDir)).map((entry) => entry.body);\n}\n\n/**\n * {@link readJsonDir}, keeping each body's file name — for callers that report\n * a problem against the file it came from. `skip` leaves out files by name\n * before they are read, so a file the caller does not own (a policy test file\n * beside the policies) can never fail it.\n */\nexport async function readJsonDirEntries(\n absDir: string,\n { skip }: { skip?: (name: string) => boolean } = {},\n): Promise<ReadonlyArray<JsonDirEntry>> {\n let entries: string[];\n try {\n entries = await readdir(absDir);\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n const result: JsonDirEntry[] = [];\n for (const entry of entries.filter((name) => name.endsWith(\".json\") && !skip?.(name)).sort()) {\n const abs = join(absDir, entry);\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(abs, \"utf8\"));\n } catch {\n throw new ZitadelError(\"E_VALIDATION\", `${entry} is not valid JSON`);\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new ZitadelError(\"E_VALIDATION\", `${entry} must contain a JSON object at the root`);\n }\n result.push({ name: entry, body: raw as Record<string, unknown> });\n }\n return result;\n}\n","/**\n * Operation policies (ADR 066): one `.zitadel/policies/<operation>.json` file\n * per guarded operation, which `deploy` carries in the release bundle. The\n * server publishes each as the operation's newest revision when the config\n * changed, and the release pins it.\n *\n * **Source of truth.** The file is the publish body plus `$schema`; its shape\n * is `policy.json`, the meta-schema generated from the OpenAPI spec and\n * shipped by `@zitadel/config`, and the CLI checks it with\n * `policyConfigSchema` from the same generated contract. The server's template\n * checks it again on the build, together with the rules that relate settings\n * to each other.\n *\n * **Dependency rule.** No upward imports (`commands/`, `release/`).\n */\nimport {\n PublishPolicyBody as PublishPolicyBodySchema,\n publishPolicyBodyOneConfigMinLengthMax,\n} from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\nimport type { PublishPolicyBody } from \"@zitadel/api/generated/model\";\nimport { policyConfigSchema, RECOMMENDED_PASSWORD_MIN_LENGTH } from \"@zitadel/config/schemas\";\nimport type { Parsed } from \"@zitadel/config/idp\";\nimport { POLICY_FILE_SCHEMA_REF } from \"@zitadel/config/meta-schemas\";\n\n/** Project-relative directory the policy files live in. */\nexport const POLICIES_DIR = \".zitadel/policies\";\n\n/** A policy file as `policyConfigSchema` accepts it. */\nexport type PolicyFile = {\n $schema?: string;\n operation: PublishPolicyBody[\"operation\"];\n config: PublishPolicyBody[\"config\"];\n};\n\n/**\n * The body `POST /policies` takes, and the form a stored policy compares in:\n * the file without its editor pointer.\n */\nexport function toPolicyWireBody(file: PolicyFile): PublishPolicyBody {\n return { operation: file.operation, config: file.config };\n}\n\n/**\n * The suffix of a policy test file (`<operation>.test.json`), which sits\n * beside the policies but is never deployed: `zitadel policies test` runs it.\n */\nexport const POLICY_TEST_SUFFIX = \".test.json\";\n\n/** Whether a file in `.zitadel/policies/` is a test file rather than a policy. */\nexport function isPolicyTestFile(name: string): boolean {\n return name.endsWith(POLICY_TEST_SUFFIX);\n}\n\n/** The name a policy file must have: its operation, so one file holds one operation's policy. */\nexport function policyFileName(operation: string): string {\n return `${operation}.json`;\n}\n\n/**\n * What is wrong with a policy file, each as a line naming the file, or none.\n * The file must parse against the strict `policyConfigSchema`, built from the\n * generated publish body, and be named after its operation: one file per\n * operation, so two files can never carry the same policy. The rules that\n * relate settings to each other (a minimum above the maximum) are the server\n * template's, and fail the release build.\n */\nexport function policyFileIssues(data: unknown, file: string): string[] {\n const result = policyConfigSchema.safeParse(data);\n if (!result.success) {\n return result.error.issues.map(\n (issue) => `${file}: ${issue.path.join(\".\") || \"(root)\"} ${issue.message}`,\n );\n }\n const expected = policyFileName(result.data.operation);\n const name = file.split(\"/\").at(-1);\n if (name !== expected) {\n return [`${file} holds the ${result.data.operation} policy, so it must be named ${expected}`];\n }\n return [];\n}\n\n/** The operation the password policy guards, and the name of its file. */\nexport const PASSWORD_POLICY_OPERATION = \"auth.factor.password.set\";\n\n/** Where `setup` writes the password policy. */\nexport const PASSWORD_POLICY_PATH = `${POLICIES_DIR}/${policyFileName(PASSWORD_POLICY_OPERATION)}`;\n\n/**\n * A minimum password length as `setup` was given it: a number, or `null` for\n * an explicit \"none\" (an empty answer, or 0), which is not the same as not\n * being asked: a new policy file gets {@link RECOMMENDED_PASSWORD_MIN_LENGTH}\n * when nothing was given, and a kept one loses its `min_length` on \"none\" and\n * keeps it when nothing was given.\n */\nexport type PasswordMinLength = number | null;\n\n/**\n * The password policy file `setup` writes for a new project: the given\n * minimum, {@link RECOMMENDED_PASSWORD_MIN_LENGTH} when none was given, and an\n * empty `config`, which enforces nothing, for an explicit \"none\".\n */\nexport function passwordPolicyFile(\n minLength?: PasswordMinLength,\n): PolicyFile & { $schema: string } {\n const value = minLength === undefined ? RECOMMENDED_PASSWORD_MIN_LENGTH : minLength;\n return {\n $schema: POLICY_FILE_SCHEMA_REF,\n operation: PASSWORD_POLICY_OPERATION,\n config: value === null ? {} : { min_length: value },\n };\n}\n\n/**\n * Reads a minimum password length the way `setup` takes one, from its flag or\n * its prompt: empty or 0 means none (`null`), anything else a whole number the\n * template's bounds accept. The bounds come from the generated publish body,\n * so the CLI and the server cannot disagree on them.\n */\nexport function parsePasswordMinLength(value: string): Parsed<PasswordMinLength> {\n const text = value.trim();\n // A minimum of 0 enforces nothing, so it means none: the file keeps one\n // form for \"off\", the setting left out, which its bounds (1 and up) teach.\n if (text === \"\" || /^0+$/.test(text)) {\n return { ok: true, value: null };\n }\n const result = PublishPolicyBodySchema.shape.config.shape.min_length.safeParse(Number(text));\n if (!/^\\d+$/.test(text) || !result.success || result.data === undefined) {\n return {\n ok: false,\n problem: `Must be a whole number from 1 to ${publishPolicyBodyOneConfigMinLengthMax}, or 0 for none`,\n };\n }\n return { ok: true, value: result.data };\n}\n","import { join } from \"node:path\";\n\nimport { BRANDING_DIR, toBrandingWireBody } from \"../branding\";\nimport { ZitadelError } from \"../errors\";\nimport { FLOWS_DIR } from \"../flows\";\nimport { IDPS_DIR } from \"../idp\";\nimport { readJsonDir, readJsonDirEntries } from \"../json-dir\";\nimport { isPolicyTestFile, POLICIES_DIR } from \"../policies\";\nimport { SCHEMAS_DIR } from \"../user-schema\";\n\n/**\n * The resources of `.zitadel/` as `POST /releases/build` takes them, grouped by\n * kind: the schemas, flow definitions, identity-provider connections and\n * operation policies as authored, and the branding descriptor with its `$file`\n * template inlined. The\n * editor-only `$schema` affordance is stripped from each so it never reaches\n * the wire.\n *\n * Connections ride the bundle like every other kind, so the server creates or\n * revises them inside the same transaction as the release: a build that fails\n * leaves none of them behind, and a release that is never deployed writes none.\n */\nexport type ConfigurationBundle = {\n schemas: Record<string, unknown>[];\n flow_definitions: Record<string, unknown>[];\n idps: Record<string, unknown>[];\n /** Absent when `.zitadel/policies/` holds none, so a server without the kind takes the bundle. */\n policies?: Record<string, unknown>[];\n branding?: Record<string, unknown>;\n};\n\n/** A built bundle and the number of resources it carries across every kind. */\nexport type BuiltBundle = {\n bundle: ConfigurationBundle;\n resourceCount: number;\n /**\n * The branding descriptors as authored, before `$file` inlining. The wire\n * bundle drops an unreadable reference so hashing stays total, so `validate`\n * needs the originals to report a missing `$file` before anything is written.\n */\n brandingSources: Record<string, unknown>[];\n /**\n * The connection files' names, in the order their bodies sit in the bundle,\n * so `validate` can name the file a bad connection came from.\n */\n idpFiles: string[];\n /** The policy files' names, positional with `bundle.policies`, likewise. */\n policyFiles: string[];\n};\n\n/** The most resources a release may pin — the cap `POST /releases/build` enforces. */\nconst MAX_BUNDLE_RESOURCES = 50;\n\n/** Drop the editor-only `$schema` pointer; the server never echoes it. */\nfunction stripSchema(resource: Record<string, unknown>): Record<string, unknown> {\n const { $schema, ...rest } = resource;\n void $schema;\n return rest;\n}\n\n/**\n * Read `.zitadel/` and assemble the bundle a deploy sends. Schemas and flows\n * are taken as authored with their `$schema` affordance removed; the branding\n * descriptor is converted to its wire body, which inlines the `$file` template\n * and strips `$schema`. An empty directory and a bundle over the cap both fail\n * before any server call, with the same messages the server would answer.\n */\nexport async function buildBundle(cwd: string): Promise<BuiltBundle> {\n const schemas = (await readJsonDir(join(cwd, SCHEMAS_DIR))).map(stripSchema);\n const flow_definitions = (await readJsonDir(join(cwd, FLOWS_DIR))).map(stripSchema);\n // Kept with their file names: `validate` reports a bad connection against\n // the file it came from, and the bundle carries only the bodies.\n const idpEntries = await readJsonDirEntries(join(cwd, IDPS_DIR));\n const idps = idpEntries.map((entry) => stripSchema(entry.body));\n // Test files sit beside the policies; `policies test` runs them, and a\n // release never carries them.\n const policyEntries = await readJsonDirEntries(join(cwd, POLICIES_DIR), {\n skip: isPolicyTestFile,\n });\n const policies = policyEntries.map((entry) => stripSchema(entry.body));\n const brandingSources = (await readJsonDir(join(cwd, BRANDING_DIR))).map((descriptor) => ({\n ...descriptor,\n }));\n // A project has one branding, so the wire bundle carries a single `branding`\n // (ADR: `configuration-bundle`). The total-resource cap below would not catch\n // a second descriptor, so it is refused here — before `$file` inlining and\n // before anything is sent — with the same message the server would answer.\n if (brandingSources.length > 1) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `A release carries at most one branding, but .zitadel/branding/ holds ${brandingSources.length}`,\n {\n hint: \"A project has a single branding; keep one descriptor under .zitadel/branding/.\",\n },\n );\n }\n\n const [descriptor] = brandingSources;\n const branding =\n descriptor === undefined\n ? undefined\n : (toBrandingWireBody(cwd, descriptor) as Record<string, unknown>);\n\n const resourceCount =\n schemas.length +\n flow_definitions.length +\n idps.length +\n policies.length +\n (branding === undefined ? 0 : 1);\n if (resourceCount === 0) {\n throw new ZitadelError(\"E_VALIDATION\", \"There is nothing in .zitadel/ to deploy\", {\n hint: \"Add a schema, flow, policy or branding under .zitadel/, or run `zitadel setup` to scaffold one.\",\n });\n }\n if (resourceCount > MAX_BUNDLE_RESOURCES) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `A release pins at most ${MAX_BUNDLE_RESOURCES} resources, but .zitadel/ holds ${resourceCount}`,\n );\n }\n\n return {\n bundle: {\n schemas,\n flow_definitions,\n idps,\n ...(policies.length === 0 ? {} : { policies }),\n ...(branding === undefined ? {} : { branding }),\n },\n resourceCount,\n brandingSources,\n idpFiles: idpEntries.map((entry) => entry.name),\n policyFiles: policyEntries.map((entry) => entry.name),\n };\n}\n","import type { ZitadelClient } from \"@zitadel/api/client\";\nimport type {\n CreateDeployment200,\n CreateDeployment201,\n ListDeployments200DeploymentsItem,\n RollbackDeployment200,\n RollbackDeployment201,\n} from \"@zitadel/api/generated/model\";\n\nimport { collectPages } from \"../oclif/crud/paging\";\n\n/**\n * A deployment, as create returns it: 200 when every target already served it,\n * 201 when it wrote a new one. The two shapes match.\n */\nexport type Deployment = CreateDeployment200 | CreateDeployment201;\n\n/**\n * A rollback, as the server returns it: 201 when it wrote a new deployment, 200\n * when every target already served the target deployment and nothing changed.\n * Kept as the union — like {@link Deployment} — for fidelity to the API contract\n * rather than casting one arm away. The two bodies are structurally identical\n * and the client does not surface the status code, so a caller cannot yet tell a\n * no-op from a write; distinguishing them would need the status threaded through.\n */\nexport type RolledBackDeployment = RollbackDeployment200 | RollbackDeployment201;\n\n/** One row of the deployment list. */\nexport type ListedDeployment = ListDeployments200DeploymentsItem;\n\n/**\n * Every live deployment of the project, newest first, drained across pages: one\n * live preview per open pull request can push the primary origins' deployment\n * off the first page, and a guard, a baseline or a rollback read from that page\n * alone would quietly miss it.\n */\nexport async function listLiveDeployments(\n client: ZitadelClient,\n projectId: string,\n options: { origin?: string; withRelease?: boolean } = {},\n): Promise<ListedDeployment[]> {\n const { items } = await collectPages(\n (token) =>\n client.listDeployments({\n project_id: projectId,\n live: true,\n ...(options.origin === undefined ? {} : { origin: options.origin }),\n ...(options.withRelease ? { expand: [\"release\"] } : {}),\n ...(token === undefined ? {} : { page_token: token }),\n }),\n { items: \"deployments\", all: true, nextPageToken: \"next_page_token\" },\n );\n return items as ListedDeployment[];\n}\n\n/**\n * Whether a deployment serves a primary origin. A preview deployment's targets\n * carry an expiry; it is never the baseline, the guard or the thing a bare\n * rollback undoes.\n */\nexport function servesPrimary(deployment: Pick<ListedDeployment, \"targets\">): boolean {\n return deployment.targets.some((target) => target.expires_at == null);\n}\n\n/** What target a deploy goes to: every primary origin, or one exact origin. */\nexport type DeployTargets = [\"primary\"] | [string];\n\n/**\n * Make a release live. The release is named by id or by content digest, never\n * both, and the targets are `primary` (every primary origin), one exact primary\n * origin, or the preview URLs a pull-request build registers. `ttl` sets how\n * long each preview stays live and is only valid with preview URLs. The server\n * answers 201 when it wrote a deployment and 200 when every target already\n * served the release.\n */\nexport async function createDeployment(\n client: ZitadelClient,\n projectId: string,\n input: {\n releaseId?: string;\n contentHash?: string;\n targets: string[];\n message?: string;\n ttl?: string;\n /**\n * Optimistic-concurrency guard: the deployment the caller believes is the\n * newest one to the targets. The server answers 409 (`dep.conflict`) when\n * another deploy raced in, so nothing is overwritten unseen.\n */\n expectedDeploymentId?: string;\n },\n): Promise<Deployment> {\n const result = await client.createDeployment(\n {\n ...(input.releaseId === undefined ? {} : { release_id: input.releaseId }),\n ...(input.contentHash === undefined ? {} : { content_hash: input.contentHash }),\n targets: input.targets,\n ...(input.message === undefined ? {} : { message: input.message }),\n ...(input.ttl === undefined ? {} : { ttl: input.ttl }),\n ...(input.expectedDeploymentId === undefined\n ? {}\n : { expected_deployment_id: input.expectedDeploymentId }),\n },\n { project_id: projectId },\n );\n return result;\n}\n\n/**\n * Re-apply a deployment: a new deployment with its release and its targets,\n * recorded as a rollback. Returns 200 when the targets already serve it.\n */\nexport async function rollbackDeployment(\n client: ZitadelClient,\n projectId: string,\n deploymentId: string,\n options?: {\n message?: string;\n /**\n * Optimistic-concurrency guard: the deployment the caller believes is the\n * newest one to the targets. The server answers 409 (`dep.conflict`) when\n * another deploy raced in between the caller reading state and this write,\n * so a rollback never overwrites a change the caller never saw.\n */\n expectedDeploymentId?: string;\n },\n): Promise<RolledBackDeployment> {\n const body = {\n ...(options?.message === undefined ? {} : { message: options.message }),\n ...(options?.expectedDeploymentId === undefined\n ? {}\n : { expected_deployment_id: options.expectedDeploymentId }),\n };\n return client.rollbackDeployment(\n deploymentId,\n { project_id: projectId },\n Object.keys(body).length === 0 ? undefined : body,\n );\n}\n","import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { copyFile, mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst run = promisify(execFile);\n\n/**\n * The directories a release is built from, the only paths a deploy diffs. Not\n * the whole of `.zitadel/`: `state.json` and `meta/` are not published, and\n * `.zitadel/secret` or `.zitadel/local/`, left untracked but not ignored, would\n * otherwise be marked for the diff and their contents printed.\n */\nconst CONFIG_PATHS = [\n \".zitadel/schemas/\",\n \".zitadel/flows/\",\n \".zitadel/branding/\",\n \".zitadel/idps/\",\n];\n\n/** Run git in `cwd`, returning its stdout, or null when git cannot answer. */\nasync function git(cwd: string, args: string[], env?: NodeJS.ProcessEnv): Promise<string | null> {\n try {\n const { stdout } = await run(\"git\", args, {\n cwd,\n maxBuffer: 16 * 1024 * 1024,\n ...(env ? { env: { ...process.env, ...env } } : {}),\n });\n return stdout;\n } catch {\n // git missing, not a repo, or the command failed — the caller decides what\n // that means for it.\n return null;\n }\n}\n\n/** The current commit, or null when there is no repo or no commit yet. */\nexport async function headSha(cwd: string): Promise<string | null> {\n const stdout = await git(cwd, [\"rev-parse\", \"HEAD\"]);\n return stdout === null ? null : stdout.trim() || null;\n}\n\n/**\n * Whether the repository's working tree has any uncommitted change, anywhere —\n * not only under `.zitadel/`. A release records the provenance of the whole\n * commit it was built from, so a change outside `.zitadel/` (a code change that\n * the config depends on, say) makes that provenance just as inexact.\n */\nexport async function worktreeIsDirty(cwd: string): Promise<boolean> {\n const stdout = await git(cwd, [\"status\", \"--porcelain\"]);\n return stdout !== null && stdout.trim() !== \"\";\n}\n\n/**\n * The `git diff` options the terminal's diff and the `--json` one share, so\n * the two never disagree: git's own unified diff, never an external diff\n * program's, with paths relative to the project, as the CLI reports them\n * everywhere else.\n */\nconst DIFF_OPTIONS = [\"--no-ext-diff\", \"--relative\"];\n\n/**\n * The coloured diff of `.zitadel/` against `sha`, or null when no diff can be\n * shown: git is missing, this is not a repo, or the commit is not in local\n * history (a shallow clone, say). A dead commit is told apart from a clean tree\n * by first checking the commit resolves.\n */\nexport async function diffConfigAgainst(\n cwd: string,\n sha: string,\n color: boolean,\n /**\n * Project-relative files the bundle inlines from outside {@link CONFIG_PATHS}\n * — a branding descriptor's `$file` template may sit anywhere in the project.\n * Editing only that file changes what a deploy publishes, so it diffs too.\n */\n referenced: readonly string[] = [],\n): Promise<string | null> {\n return diffConfig(cwd, sha, [color ? \"--color=always\" : \"--no-color\"], referenced);\n}\n\n/** One changed file of a deploy's diff, as `deploy --json` reports it. */\nexport interface ConfigDiffFile {\n /** Project-relative; for a rename or a copy, where the file is now. */\n readonly path: string;\n readonly status: \"added\" | \"modified\" | \"deleted\" | \"renamed\" | \"copied\";\n /** Where a renamed or copied file came from. */\n readonly previous_path?: string;\n /** The file's part of the diff, uncoloured, exactly as the terminal shows it. */\n readonly patch: string;\n}\n\n/**\n * {@link diffConfigAgainst}, uncoloured and split by file: joined back\n * together, the patches are the diff the terminal shows. Null when no diff can\n * be shown, for the same reasons.\n */\nexport async function diffConfigFilesAgainst(\n cwd: string,\n sha: string,\n referenced: readonly string[] = [],\n): Promise<ConfigDiffFile[] | null> {\n // `--raw -z` lists every file's status and paths, unquoted, ahead of the patch.\n const output = await diffConfig(cwd, sha, [\"--no-color\", \"--raw\", \"-z\", \"--patch\"], referenced);\n return output === null ? null : splitByFile(output);\n}\n\n/**\n * Pair the `--raw -z` records with the patch's per-file sections. git writes\n * both from one list of files, in one order, so they line up one to one, except\n * for a file whose type changed (a file replaced by a symlink): git shows it as\n * a deletion and a creation, two sections under one header, joined here.\n */\nfunction splitByFile(output: string): ConfigDiffFile[] {\n let at = 0;\n const field = (): string => {\n const end = output.indexOf(\"\\0\", at);\n const value = output.slice(at, end === -1 ? output.length : end);\n at = end === -1 ? output.length : end + 1;\n return value;\n };\n const records: Omit<ConfigDiffFile, \"patch\">[] = [];\n // A record is `:<modes> <ids> <status letter>[<score>]`, then its path, or\n // for a rename or a copy the path it came from and the path it went to.\n while (output.startsWith(\":\", at)) {\n const meta = field();\n const letter = meta.charAt(meta.lastIndexOf(\" \") + 1);\n const path = field();\n if (letter === \"R\" || letter === \"C\") {\n const status = letter === \"R\" ? \"renamed\" : \"copied\";\n records.push({ path: field(), status, previous_path: path });\n } else {\n const status = letter === \"A\" ? \"added\" : letter === \"D\" ? \"deleted\" : \"modified\";\n records.push({ path, status });\n }\n }\n\n // One more NUL ends the records; the patch follows.\n const sections = output.slice(at + 1).split(/^(?=diff --git )/m);\n let next = 0;\n return records.map((record) => {\n let patch = sections[next++] ?? \"\";\n while (next < sections.length && headerOf(sections[next]) === headerOf(patch)) {\n patch += sections[next++];\n }\n return { ...record, patch };\n });\n}\n\n/** A patch section's first line, its `diff --git` header. */\nfunction headerOf(section = \"\"): string {\n const end = section.indexOf(\"\\n\");\n return end === -1 ? section : section.slice(0, end);\n}\n\n/** `git diff` of the release's paths against `sha`, in `format`. */\nasync function diffConfig(\n cwd: string,\n sha: string,\n format: readonly string[],\n referenced: readonly string[],\n): Promise<string | null> {\n const paths = [...CONFIG_PATHS, ...referenced];\n const resolved = await git(cwd, [\"cat-file\", \"-e\", `${sha}^{commit}`]);\n if (resolved === null) {\n return null;\n }\n const diffArgs = [\"diff\", ...DIFF_OPTIONS, ...format, sha, \"--\", ...paths];\n\n // `git diff` omits untracked files, but a release bundle includes every new\n // file under `.zitadel/`, so a brand-new (untracked) resource must show in\n // the diff too. We mark the untracked files intent-to-add (`git add -N`) in a\n // throwaway copy of the index, selected with GIT_INDEX_FILE, so they diff as\n // additions — without touching the real index another process in this\n // worktree may be using. If anything in that setup fails we fall back to the\n // plain diff, which still shows every tracked change.\n const indexPath = (await git(cwd, [\"rev-parse\", \"--git-path\", \"index\"]))?.trim();\n if (!indexPath) {\n return git(cwd, diffArgs);\n }\n let scratch: string | undefined;\n try {\n scratch = await mkdtemp(join(tmpdir(), \"zitadel-diff-\"));\n const tempIndex = join(scratch, \"index\");\n // The real index may not exist yet (a fresh repo); start empty if so.\n await copyFile(resolve(cwd, indexPath), tempIndex).catch(() => undefined);\n const env: NodeJS.ProcessEnv = { GIT_INDEX_FILE: tempIndex };\n // `git add` refuses a whole pathspec when one part matches nothing, so only\n // the directories this project has are marked.\n const present = paths.filter((path) => existsSync(join(cwd, path)));\n if (present.length > 0) {\n await git(cwd, [\"add\", \"-N\", \"--\", ...present], env);\n }\n // Fall back to the plain diff if the scratch-index diff could not run, so a\n // resolvable commit never reports \"no diff available\" by mistake.\n return (await git(cwd, diffArgs, env)) ?? (await git(cwd, diffArgs));\n } finally {\n if (scratch) {\n await rm(scratch, { recursive: true, force: true });\n }\n }\n}\n","import type { LookupAddress } from \"node:dns\";\nimport { lookup } from \"node:dns/promises\";\nimport type { RequestOptions } from \"node:https\";\nimport { BlockList, isIP } from \"node:net\";\n\nimport { consola } from \"consola\";\nimport { Agent, type Dispatcher } from \"undici\";\n\nimport { userAgentInterceptor } from \"../../user-agent\";\n\n/**\n * Branding descriptor fields whose value is a URL the login page fetches as\n * an image. Both are optional and both fail the same invisible way when the\n * URL is well-formed but dead.\n */\nconst ASSET_FIELDS = [\"logo_url\", \"hero_url\"] as const;\n\n/**\n * Per-URL probe budget. Short on purpose: this runs on the critical path of\n * every `deploy` and `preview`, and a dead host that never answers must cost a\n * couple of seconds, not a hung command.\n */\nconst DEFAULT_TIMEOUT_MS = 2500;\n\n/** Keep redirect chains bounded and re-validate every destination ourselves. */\nconst MAX_REDIRECTS = 5;\n\n/**\n * Addresses an untrusted descriptor must never make the planning host contact.\n * The browser-side render gate still supports canonical loopback HTTP for local\n * development; the CLI probe deliberately leaves those URLs inconclusive\n * instead of turning `deploy` over repo content into a localhost/network scanner.\n */\nconst UNSAFE_IPV4_ADDRESSES = new BlockList();\nfor (const [network, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.88.99.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n UNSAFE_IPV4_ADDRESSES.addSubnet(network, prefix, \"ipv4\");\n}\nconst UNSAFE_IPV6_ADDRESSES = new BlockList();\nfor (const [network, prefix] of [\n // Global unicast currently lives in 2000::/3. Excluding everything outside\n // it also covers mapped IPv4, translation, ULA, link-local, and multicast.\n [\"::\", 3],\n [\"4000::\", 2],\n [\"8000::\", 1],\n // Special-purpose ranges inside 2000::/3 are not public asset hosts.\n [\"2001::\", 23],\n [\"2001:db8::\", 32],\n [\"2002::\", 16],\n [\"3fff::\", 20],\n] as const) {\n UNSAFE_IPV6_ADDRESSES.addSubnet(network, prefix, \"ipv6\");\n}\n\n/** Content types that are images despite not being `image/*`. */\nconst EXTRA_IMAGE_TYPES = new Set([\"application/octet-stream\"]);\n\nexport type AssetProbeVerdict =\n | { kind: \"ok\" }\n /** The probe could not decide — no warning is worth a false alarm. */\n | { kind: \"inconclusive\" }\n | { kind: \"unreachable\"; detail: string }\n | { kind: \"status\"; status: number }\n | { kind: \"empty\"; status: number }\n | { kind: \"content-type\"; contentType: string };\n\n/**\n * Probe every asset URL the bundle's branding descriptors carry and return one\n * warning line per URL that is well-formed but will not render: an unreachable\n * host, a non-2xx status, or a response that is not an image.\n *\n * Why the CLI probes at all: a bad `logo_url` clears every gate on the way in\n * (the CLI's Zod shape check, the server's save gate) and then fails silently\n * in the browser as a 0×0 `<img>` — no deploy output, no console error. The\n * probe is the only place in the pipeline that can see it.\n *\n * Deliberately non-fatal and best-effort. A developer on a plane, behind a\n * proxy, or pointing at a CDN that only resolves from production gets a\n * warning, never a failed deploy — the machine running `deploy` is not\n * necessarily the machine that renders the login page. Set\n * `ZITADEL_SKIP_ASSET_PROBE` to turn it off entirely, and\n * `ZITADEL_ASSET_PROBE_TIMEOUT_MS` to retune the per-URL budget. Only public\n * HTTPS destinations are contacted: loopback/private/internal targets and\n * redirects to them stay inconclusive so repo config cannot scan the running\n * host's network.\n */\nexport async function brandingAssetWarnings(brandings: ReadonlyArray<object>): Promise<string[]> {\n if (process.env.ZITADEL_SKIP_ASSET_PROBE) {\n consola.debug(\"Branding asset probe skipped (ZITADEL_SKIP_ASSET_PROBE is set)\");\n return [];\n }\n\n // One probe per distinct URL: the same logo referenced twice is one request.\n const fields = brandings.flatMap((branding) => assetUrlsOf(branding));\n const urls = new Set(fields.map(({ url }) => url));\n if (urls.size === 0) {\n return [];\n }\n\n const timeoutMs = probeTimeoutMs();\n const verdicts = new Map(\n await Promise.all(\n [...urls].map(\n async (url): Promise<[string, AssetProbeVerdict]> => [\n url,\n await probeAsset(url, timeoutMs),\n ],\n ),\n ),\n );\n\n const warnings: string[] = [];\n for (const { field, url } of fields) {\n const warning = describeVerdict(field, url, verdicts.get(url) ?? { kind: \"inconclusive\" });\n if (warning) {\n warnings.push(warning);\n }\n }\n return warnings;\n}\n\n/**\n * The probe itself: a HEAD request bounded by an abort timeout. HEAD keeps a\n * multi-megabyte hero image off the wire — we only need the status line and\n * the content type.\n */\nexport async function probeAsset(url: string, timeoutMs: number): Promise<AssetProbeVerdict> {\n let current: URL;\n try {\n current = new URL(url);\n } catch {\n // Shape is the schema's job; an unparseable URL never reaches here.\n return { kind: \"inconclusive\" };\n }\n const signal = AbortSignal.timeout(timeoutMs);\n try {\n for (let redirects = 0; ; redirects += 1) {\n if (!isSafeProbeUrl(current)) {\n consola.debug(`asset probe ${url} skipped unsafe/private target: ${current.href}`);\n return { kind: \"inconclusive\" };\n }\n\n const response = await requestHead(current, signal);\n\n if (isRedirect(response.status)) {\n const location = response.location;\n if (!location) {\n return { kind: \"status\", status: response.status };\n }\n if (redirects >= MAX_REDIRECTS) {\n return { kind: \"unreachable\", detail: `more than ${MAX_REDIRECTS} redirects` };\n }\n current = new URL(location, current);\n continue;\n }\n\n // Some origins refuse HEAD outright. That says nothing about the asset,\n // and a false \"your logo is broken\" is worse than staying quiet.\n if (response.status === 405 || response.status === 501) {\n return { kind: \"inconclusive\" };\n }\n if (response.status < 200 || response.status >= 300) {\n return { kind: \"status\", status: response.status };\n }\n // These successful statuses are explicitly bodyless. Treating them as\n // healthy because they also omit Content-Type recreates the exact\n // \"well-formed URL that serves nothing\" failure this probe exists for.\n if (response.status === 204 || response.status === 205) {\n return { kind: \"empty\", status: response.status };\n }\n\n const contentType = response.contentType?.split(\";\")[0]?.trim().toLowerCase();\n if (!contentType) {\n return { kind: \"ok\" };\n }\n if (contentType.startsWith(\"image/\") || EXTRA_IMAGE_TYPES.has(contentType)) {\n return { kind: \"ok\" };\n }\n return { kind: \"content-type\", contentType };\n }\n } catch (error) {\n if (isUnsafeProbeTargetError(error)) {\n consola.debug(`asset probe ${url} skipped unsafe/private target`);\n return { kind: \"inconclusive\" };\n }\n consola.debug(`asset probe ${url} failed:`, error);\n return { kind: \"unreachable\", detail: describeProbeError(error, timeoutMs) };\n }\n}\n\nfunction isRedirect(status: number): boolean {\n return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;\n}\n\n/**\n * Reject targets whose URL alone proves they are unsafe. Hostname resolution\n * happens inside the connector lookup below so validation and connection use\n * the same DNS answer, without a rebinding window.\n */\nfunction isSafeProbeUrl(url: URL): boolean {\n if (url.protocol !== \"https:\" || url.username !== \"\" || url.password !== \"\") {\n return false;\n }\n\n const hostname = url.hostname\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\")\n .toLowerCase();\n if (\n hostname === \"localhost\" ||\n !hostname.includes(\".\") ||\n hostname.endsWith(\".localhost\") ||\n hostname.endsWith(\".local\") ||\n hostname.endsWith(\".internal\") ||\n hostname.endsWith(\".lan\") ||\n hostname.endsWith(\".home.arpa\")\n ) {\n return false;\n }\n\n const literalFamily = isIP(hostname);\n return literalFamily === 0 || !isUnsafeAddress(hostname, literalFamily);\n}\n\n/** Resolve once and accept the answer only when every address is public. */\nexport async function resolvePublicAddresses(\n hostname: string,\n): Promise<LookupAddress[] | undefined> {\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n return addresses.length > 0 &&\n addresses.every(({ address, family }) => !isUnsafeAddress(address, family))\n ? addresses\n : undefined;\n}\n\nfunction isUnsafeAddress(address: string, family: number): boolean {\n return family === 6\n ? UNSAFE_IPV6_ADDRESSES.check(address, \"ipv6\")\n : UNSAFE_IPV4_ADDRESSES.check(address, \"ipv4\");\n}\n\ninterface HeadResponse {\n status: number;\n location?: string;\n contentType?: string;\n}\n\nconst UNSAFE_PROBE_TARGET_CODE = \"ERR_ZITADEL_UNSAFE_ASSET_TARGET\";\n\nfunction unsafeProbeTargetError(hostname: string): NodeJS.ErrnoException {\n return Object.assign(new Error(`asset target ${hostname} resolves to a non-public address`), {\n code: UNSAFE_PROBE_TARGET_CODE,\n });\n}\n\n/**\n * Validate DNS in the connector's own lookup and return only approved\n * addresses. The socket cannot perform a second lookup, which closes the DNS\n * rebinding gap while preserving the hostname for TLS SNI/certificate checks.\n */\nasync function requestHead(url: URL, signal: AbortSignal): Promise<HeadResponse> {\n const safeLookup: NonNullable<RequestOptions[\"lookup\"]> = (hostname, options, callback) => {\n resolvePublicAddresses(hostname).then(\n (addresses) => {\n if (!addresses) {\n callback(unsafeProbeTargetError(hostname), \"\", 0);\n return;\n }\n const candidates =\n options.family === 4 || options.family === 6\n ? addresses.filter(({ family }) => family === options.family)\n : addresses;\n const candidate = candidates[0];\n if (!candidate) {\n callback(unsafeProbeTargetError(hostname), \"\", 0);\n return;\n }\n if (options.all) {\n callback(null, candidates);\n return;\n }\n callback(null, candidate.address, candidate.family);\n },\n (error: NodeJS.ErrnoException) => callback(error, \"\", 0),\n );\n };\n\n // A private agent bypasses the global dispatcher, so it composes the user\n // agent itself.\n const dispatcher = new Agent({ connect: { lookup: safeLookup } }).compose(userAgentInterceptor);\n try {\n const response = await fetch(url, {\n method: \"HEAD\",\n redirect: \"manual\",\n signal,\n dispatcher,\n } as RequestInit & { dispatcher: Dispatcher });\n return {\n status: response.status,\n location: response.headers.get(\"location\") ?? undefined,\n contentType: response.headers.get(\"content-type\") ?? undefined,\n };\n } finally {\n await dispatcher.destroy();\n }\n}\n\nfunction isUnsafeProbeTargetError(error: unknown): boolean {\n let current = error;\n for (let depth = 0; depth < 4 && current instanceof Error; depth += 1) {\n if ((current as NodeJS.ErrnoException).code === UNSAFE_PROBE_TARGET_CODE) {\n return true;\n }\n current = current.cause;\n }\n return false;\n}\n\nfunction describeVerdict(\n field: string,\n url: string,\n verdict: AssetProbeVerdict,\n): string | undefined {\n switch (verdict.kind) {\n case \"ok\":\n case \"inconclusive\":\n return undefined;\n case \"status\":\n return (\n `${field} ${url} returned HTTP ${verdict.status} — the login page renders a ` +\n `well-formed URL that serves nothing as a 0×0 image, with no error anywhere.`\n );\n case \"empty\":\n return (\n `${field} ${url} returned HTTP ${verdict.status} with no representation — the login ` +\n `page has no image bytes to render.`\n );\n case \"unreachable\":\n return (\n `${field} ${url} could not be reached (${verdict.detail}) — the login page renders ` +\n `an unreachable URL as a 0×0 image. Ignore this if the host is only reachable from ` +\n `where the login page renders; set ZITADEL_SKIP_ASSET_PROBE to stop checking.`\n );\n case \"content-type\":\n return (\n `${field} ${url} responded with content-type \"${verdict.contentType}\", not an image — ` +\n `the login page renders a non-image response as a 0×0 image.`\n );\n }\n}\n\n/** The `logo_url` / `hero_url` values a descriptor actually sets. */\nfunction assetUrlsOf(content: object): Array<{ field: string; url: string }> {\n const body = content as Record<string, unknown>;\n const out: Array<{ field: string; url: string }> = [];\n for (const field of ASSET_FIELDS) {\n const value = body[field];\n if (typeof value === \"string\" && value !== \"\") {\n out.push({ field, url: value });\n }\n }\n return out;\n}\n\nfunction probeTimeoutMs(): number {\n const raw = Number(process.env.ZITADEL_ASSET_PROBE_TIMEOUT_MS);\n return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_TIMEOUT_MS;\n}\n\nfunction describeProbeError(error: unknown, timeoutMs: number): string {\n if (\n error instanceof Error &&\n (error.name === \"TimeoutError\" ||\n (error.cause instanceof Error && error.cause.name === \"TimeoutError\"))\n ) {\n return `no response within ${timeoutMs}ms`;\n }\n if (error instanceof Error) {\n const cause = error.cause;\n const detail = cause instanceof Error ? cause.message : error.message;\n return detail || error.name;\n }\n return String(error);\n}\n","import { isVariableReference, missingEndpoints, referencedVariable } from \"@zitadel/config/idp\";\nimport { idpConnectionConfigSchema } from \"@zitadel/config/schemas\";\nimport { ApiError } from \"@zitadel/api/runtime/fetch\";\n\nimport { ZitadelError } from \"../../errors\";\nimport { IDPS_DIR, refuseResolvedSecret } from \"../../idp\";\nimport { valuesOfKind } from \"../../variables\";\nimport type { StepContext } from \"../pipeline\";\n\n/**\n * The checks a connection file gets before the release is built.\n *\n * The server creates the connections from the bundle, inside the release's own\n * transaction, and holds them to the same rules. These run first anyway so a\n * bad file is named locally — with the file it came from and the command that\n * fixes it — rather than coming back as one bulk `rel.invalid`. Two of them the\n * server cannot run for us: that a `client_secret` references a variable rather\n * than holding a value, which must fail before anything leaves the machine, and\n * that the variables a connection names are the kind the engine needs.\n *\n * A preview is checked the same way, except that its token may not read the\n * project's variables; that check then belongs to the deploy that merges it.\n */\nexport async function validateConnections(ctx: StepContext): Promise<void> {\n const files = ctx.idpFiles;\n const named = ctx.bundle.idps.map((body, index) => ({\n body,\n file: `${IDPS_DIR}/${files[index] ?? \"(unnamed)\"}`,\n }));\n // Every file first: a later bad one must not be reported only after the\n // earlier ones passed, because the whole bundle is built or none of it is.\n for (const { body, file } of named) {\n validateConnection(body, file, ctx.suggest);\n }\n if (named.length === 0) {\n return;\n }\n const held = await heldVariables(ctx);\n if (held === undefined) {\n return;\n }\n for (const { body, file } of named) {\n checkCredentialVariables(body, file, held, ctx.suggest, ctx.mode === \"preview\");\n }\n}\n\n/**\n * The connection's shape, and the one mistake that would publish a credential:\n * a `client_secret` held as a value rather than a `${{ NAME }}` reference.\n */\nfunction validateConnection(data: object, file: string, suggest: StepContext[\"suggest\"]): void {\n const result = idpConnectionConfigSchema.safeParse(data);\n if (!result.success) {\n const literalSecret = result.error.issues.some((issue) => {\n if (issue.path[issue.path.length - 1] !== \"client_secret\") {\n return false;\n }\n const stored = valueAt(data, issue.path);\n return typeof stored === \"string\" && !isVariableReference(stored);\n });\n throw new ZitadelError(\n \"E_VALIDATION\",\n literalSecret\n ? \"Connection file's client_secret must reference a variable, not hold a value\"\n : \"Connection file is not a valid identity provider connection\",\n {\n hint: literalSecret\n ? `Use \"client_secret\": \"\\${{ NAME }}\" and publish the value with \\`${suggest(\"variable set NAME --secret\")}\\`.`\n : undefined,\n details: { issues: result.error.issues },\n },\n );\n }\n // A valid document is then held to the server's endpoint rule: an `oidc`\n // block names no endpoint or every one it needs. The server refuses anything\n // in between, so it is refused here, before a deploy could stop part-way.\n const missing = missingEndpoints((data as { oidc?: unknown }).oidc);\n if (missing.length > 0) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `${file}: oidc names some endpoints but not ${missing.join(\", \")}`,\n {\n hint:\n \"Name every endpoint (authorization_endpoint, jwks_uri, token_endpoint, and \" +\n \"userinfo_endpoint unless id_token_mapping is true), or none to read them from \" +\n \"the issuer's discovery document.\",\n details: { file, missing },\n },\n );\n }\n // A read that resolved a secret must never be sent on; validate the body too.\n refuseResolvedSecret(data, \"the connection\");\n}\n\n/** The value a Zod issue path points at, or undefined when it is absent. */\nfunction valueAt(data: object, path: ReadonlyArray<PropertyKey>): unknown {\n let current: unknown = data;\n for (const key of path) {\n if (typeof current !== \"object\" || current === null) {\n return undefined;\n }\n current = (current as Record<PropertyKey, unknown>)[key];\n }\n return current;\n}\n\n/**\n * The variables the deploy would freeze, by name, and whether each is a secret:\n * the primary kind's for a deploy and the preview kind's for a preview, with no\n * fallback from one to the other (ADR 069). A preview's token may not read them,\n * which leaves the check to the deploy that merges it.\n */\nasync function heldVariables(ctx: StepContext): Promise<Map<string, boolean> | undefined> {\n const kind = ctx.mode === \"preview\" ? \"preview\" : \"primary\";\n let held: Awaited<ReturnType<StepContext[\"client\"][\"getVariables\"]>>;\n try {\n held = await ctx.client.getVariables({ project_id: ctx.projectId, kind });\n } catch (error) {\n if (ctx.mode === \"preview\" && error instanceof ApiError && error.status === 403) {\n return undefined;\n }\n throw error;\n }\n // A secret reads back as `{ secret: true }`, a plain value as the value.\n return new Map(\n Object.entries(valuesOfKind(held, kind)).map(([name, value]) => [\n name,\n typeof value === \"object\",\n ]),\n );\n}\n\n/**\n * What the engine needs from the variables a connection names: they exist,\n * the client id is a plain one it can put in the authorize URL, the client\n * secret is a secret one, and they are not one and the same.\n */\nfunction checkCredentialVariables(\n connection: object,\n file: string,\n held: ReadonlyMap<string, boolean>,\n suggest: StepContext[\"suggest\"],\n preview: boolean,\n): void {\n // A preview freezes the preview kind alone, so the value it lacks is set for\n // that kind.\n const setCommand = (name: string, secret: boolean) =>\n suggest(`variable set ${name}${secret ? \" --secret\" : \"\"}${preview ? \" --preview\" : \"\"}`);\n const body = connection as {\n oidc?: { client_id?: unknown; client_secret?: unknown };\n };\n const block = body.oidc;\n const nameOf = (value: unknown) =>\n typeof value === \"string\" ? referencedVariable(value) : undefined;\n const named = [\n { field: \"client_id\", secret: false, name: nameOf(block?.client_id) },\n { field: \"client_secret\", secret: true, name: nameOf(block?.client_secret) },\n ].flatMap((credential) =>\n credential.name === undefined ? [] : [{ ...credential, name: credential.name }],\n );\n const [id, secret] = named;\n if (id !== undefined && secret !== undefined && id.name === secret.name) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `${file}: client_id and client_secret both name the variable ${id.name}`,\n {\n hint: \"Give each its own variable: a plain one for the client id, a secret one for the client secret.\",\n details: { variable: id.name, file },\n },\n );\n }\n for (const { field, secret: wantsSecret, name } of named) {\n const isSecret = held.get(name);\n if (isSecret === undefined) {\n throw new ZitadelError(\n \"E_CREDENTIAL_MISSING\",\n `${file}: ${field} names the variable ${name}, which the project does not have`,\n {\n hint: \"Publish it with the command below, then deploy again.\",\n nextCommands: [setCommand(name, wantsSecret)],\n details: { variable: name, field, file },\n },\n );\n }\n if (isSecret !== wantsSecret) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `${file}: ${field} names the variable ${name}, which is ${isSecret ? \"a secret\" : \"not a secret\"}`,\n {\n hint: wantsSecret\n ? \"The client secret must be a secret variable: publish it with the command below.\"\n : \"The client id must be a plain variable the engine can read back: publish it with the command below, without --secret.\",\n nextCommands: [setCommand(name, wantsSecret)],\n details: { variable: name, field, file, secret: isSecret },\n },\n );\n }\n }\n}\n","import { join } from \"node:path\";\n\nimport { type ProjectTree, validateProject } from \"@zitadel/config/validate\";\n\nimport { ZitadelError } from \"../../errors\";\nimport { FLOWS_DIR } from \"../../flows\";\nimport { IDPS_DIR } from \"../../idp\";\nimport { type JsonDirEntry, readJsonDirEntries } from \"../../json-dir\";\nimport { SCHEMAS_DIR } from \"../../user-schema\";\nimport { reportWarning } from \"../../warnings\";\n\n/**\n * Cross-file checks on the SSO configuration, before anything is sent.\n *\n * A flow that offers a provider its schema does not list, or a schema that\n * lists a provider with no connection file, is only visible when the files are\n * read together, and the server would reveal it late or not at all. This reads\n * the whole of `.zitadel/` so the rules can see what each file points at, and\n * throws one `E_VALIDATION` naming every problem, so a deploy (or a dry run)\n * stops before any request.\n *\n * A deploy publishes everything under `.zitadel/`, so everything is judged;\n * there is no narrower set of files a deploy \"touches\".\n */\nexport async function validateSsoConsistency(cwd: string): Promise<void> {\n const [schemas, flows, connections] = await Promise.all([\n readJsonDirEntries(join(cwd, SCHEMAS_DIR)),\n readJsonDirEntries(join(cwd, FLOWS_DIR)),\n readJsonDirEntries(join(cwd, IDPS_DIR)),\n ]);\n const keyed = (dir: string, entries: ReadonlyArray<JsonDirEntry>) =>\n new Map(entries.map((entry) => [`${dir}/${entry.name}`, entry.body] as const));\n const schemaFiles = keyed(SCHEMAS_DIR, schemas);\n\n const tree: ProjectTree = {\n schemas: schemaFiles,\n flows: new Map(\n flows.map((flow) => {\n const path = `${FLOWS_DIR}/${flow.name}`;\n const schemaPath = pinnedSchemaPath(flow.body, schemaFiles);\n // Said aloud, because the alternative is a flow that passes by not being\n // checked: its schema may be one this project does not keep locally.\n if (schemaPath === undefined && offeredProviders(flow.body).length > 0) {\n reportWarning(\n `${path}: could not tell which local schema this flow pins, so its provider rules were not checked against a schema`,\n );\n }\n return [path, { body: flow.body, schemaPath }] as const;\n }),\n ),\n connections: keyed(IDPS_DIR, connections),\n };\n\n const issues = validateProject(tree);\n if (issues.length === 0) {\n return;\n }\n const noun = issues.length === 1 ? \"issue\" : \"issues\";\n throw new ZitadelError(\n \"E_VALIDATION\",\n `SSO configuration is not consistent (${issues.length} ${noun}):\\n` +\n issues.map((issue) => ` - ${issue.file}: ${issue.message}`).join(\"\\n\"),\n {\n hint:\n \"These checks read the schemas, flows and connection files together. \" +\n \"Fix the files named above and re-run; no changes were made. \" +\n \"Only the CLI makes these checks.\",\n details: {\n issues: issues.map(({ rule, file, steps, message }) => ({\n rule,\n path: file,\n ...(steps === undefined ? {} : { steps }),\n message,\n })),\n },\n },\n );\n}\n\n/** The provider slugs the steps of a flow offer. */\nfunction offeredProviders(flow: object): string[] {\n const steps = (flow as { steps?: unknown }).steps;\n if (!Array.isArray(steps)) {\n return [];\n }\n return steps.flatMap((step) => {\n const providers =\n typeof step === \"object\" && step !== null\n ? (step as { sso_providers?: unknown }).sso_providers\n : undefined;\n return Array.isArray(providers)\n ? providers.filter((item): item is string => typeof item === \"string\")\n : [];\n });\n}\n\n/**\n * The local schema a flow's `user_schema` pins, or `undefined` when it cannot\n * be told. A flow names its schema by `objectType`; a schema's `$id` is also\n * accepted for a flow written against the URL form.\n */\nfunction pinnedSchemaPath(flow: object, schemas: ReadonlyMap<string, object>): string | undefined {\n const ref = (flow as { user_schema?: unknown }).user_schema;\n if (typeof ref !== \"string\" || ref === \"\") {\n return undefined;\n }\n for (const [path, schema] of schemas) {\n const { $id, objectType } = schema as { $id?: unknown; objectType?: unknown };\n if ($id === ref || objectType === ref) {\n return path;\n }\n }\n return undefined;\n}\n","import { type FlowValidationIssue, validateFlowDefinition } from \"@zitadel/config/validate\";\nimport {\n brandingConfigSchema,\n flowConfigSchema,\n schemaConfigSchema,\n} from \"@zitadel/config/schemas\";\n\nimport { assertNoLegacyTemplateKey, readDescriptorTemplate } from \"../../branding\";\nimport { ZitadelError } from \"../../errors\";\nimport { flowEnvRefs } from \"../../flows\";\nimport { POLICIES_DIR, policyFileIssues } from \"../../policies\";\nimport { reportWarning } from \"../../warnings\";\nimport type { Step, StepContext } from \"../pipeline\";\nimport { brandingAssetWarnings } from \"./asset-probe\";\nimport { validateConnections } from \"./idp-checks\";\nimport { validateSsoConsistency } from \"./sso-consistency\";\nimport { validateLoginTemplate } from \"@zitadel/config/template\";\n\n/**\n * Validate the bundle the way the server does before it builds the release, so\n * a misconfiguration fails here with the file named rather than as a bulk\n * `rel.invalid` from the server. Two checks the server cannot run live earn\n * their place: every `${VAR}` / `*_env` reference must resolve in the running\n * environment, and every branding asset URL must actually serve an image.\n *\n * Moved out of the sync engine, where it validated a diff; here it validates\n * the bundle a deploy (and, later, a preview) assembles.\n */\nexport const validateStep: Step = {\n name: \"validate\",\n runsFor: [\"deploy\", \"preview\"],\n async run(ctx: StepContext): Promise<undefined> {\n assertEnvRefsResolve(ctx);\n // Structural parsing first: `validateFlowDefinition` is the semantic\n // validator and assumes its input already parsed against `flowConfigSchema`,\n // so a flow missing a required `name`/`status`/`user_schema` has to be\n // rejected here, not left to fail at release creation after the IdP step\n // has already written.\n validateBundleShapes(ctx);\n validateFlows(ctx);\n await validateConnections(ctx);\n await validateSsoConsistency(ctx.cwd);\n for (const warning of await brandingAssetWarnings(brandingsOf(ctx))) {\n reportWarning(warning);\n }\n },\n};\n\n/**\n * Parse every schema, flow, policy and branding descriptor against the same Zod\n * the server enforces, before any writing step runs. Without this a malformed\n * schema, flow or branding only fails at `createRelease`, after the IdP-sync\n * step has already written — leaving a half-applied deploy. Errors across\n * every bundle kind aggregate into one `E_VALIDATION`. Branding is parsed from\n * the descriptor as authored (not the inlined wire body), so a `$file` that\n * cannot be read is reported here rather than silently dropped.\n */\nfunction validateBundleShapes(ctx: StepContext): void {\n const failures: string[] = [];\n ctx.bundle.schemas.forEach((schema, index) => {\n const result = schemaConfigSchema.safeParse(schema);\n if (!result.success) {\n const handle =\n typeof schema.objectType === \"string\" ? schema.objectType : `schema #${index + 1}`;\n for (const issue of result.error.issues) {\n failures.push(`${handle}: ${issue.path.join(\".\") || \"(root)\"} ${issue.message}`);\n }\n }\n });\n ctx.bundle.flow_definitions.forEach((flow, index) => {\n const result = flowConfigSchema.safeParse(flow);\n if (!result.success) {\n const handle = typeof flow.name === \"string\" ? flow.name : `flow #${index + 1}`;\n for (const issue of result.error.issues) {\n failures.push(`${handle}: ${issue.path.join(\".\") || \"(root)\"} ${issue.message}`);\n }\n }\n });\n // A policy file is reported by its path: its operation names it, and a\n // file named after another operation is itself the problem.\n (ctx.bundle.policies ?? []).forEach((policy, index) => {\n const file = `${POLICIES_DIR}/${ctx.policyFiles[index] ?? \"(unnamed)\"}`;\n failures.push(...policyFileIssues(policy, file));\n });\n ctx.brandingSources.forEach((descriptor, index) => {\n const handle = `branding #${index + 1}`;\n // The retired `liquid_template_file` key gets its migration, not the bare\n // unrecognised-key error the schema would give.\n try {\n assertNoLegacyTemplateKey(descriptor);\n } catch (error) {\n const hint = error instanceof ZitadelError && error.hint ? ` ${error.hint}` : \"\";\n failures.push(`${handle}: ${error instanceof Error ? error.message : String(error)}.${hint}`);\n return;\n }\n const result = brandingConfigSchema.safeParse(descriptor);\n if (!result.success) {\n for (const issue of result.error.issues) {\n failures.push(`${handle}: ${issue.path.join(\".\") || \"(root)\"} ${issue.message}`);\n }\n }\n // An unreadable `$file` reference throws here; the wire bundle dropped it,\n // so this is the only place the deploy can still catch it.\n let template: string | undefined;\n try {\n template = readDescriptorTemplate(ctx.cwd, descriptor);\n } catch (error) {\n failures.push(`${handle}: ${error instanceof Error ? error.message : String(error)}`);\n }\n // The login template runs through the same LiquidJS rules the server\n // applies (`no-script-tag`, `mandatory-gates`, ...), so a dry run, which\n // makes no server call, still catches a template the release would refuse.\n if (template !== undefined) {\n for (const issue of validateLoginTemplate(template)) {\n if (issue.severity === \"error\") {\n failures.push(`${handle}: template ${issue.rule}: ${issue.message}`);\n }\n }\n }\n });\n if (failures.length === 0) {\n return;\n }\n const noun = failures.length === 1 ? \"issue\" : \"issues\";\n throw new ZitadelError(\n \"E_VALIDATION\",\n `Configuration validation failed (${failures.length} ${noun}):\\n` +\n failures.map((failure) => ` - ${failure}`).join(\"\\n\"),\n {\n hint: \"These are the same rules the server enforces. Fix the file(s) and re-run.\",\n details: { issues: failures },\n },\n );\n}\n\n/** The schema a flow's `user_schema` names, found by `objectType` in the bundle. */\nfunction schemaFor(ctx: StepContext, flow: Record<string, unknown>): object | undefined {\n const ref = flow.user_schema;\n if (typeof ref !== \"string\" || ref === \"\") {\n return undefined;\n }\n return ctx.bundle.schemas.find((schema) => schema.objectType === ref);\n}\n\n/**\n * The semantic flow validation the server enforces when it builds the release:\n * errors aggregate into one `E_VALIDATION`, warnings are reported as they are\n * found. The schema a flow pins is resolved from the bundle so schema-aware\n * rules run.\n */\nfunction validateFlows(ctx: StepContext): void {\n const failures: Array<{ handle: string; issue: FlowValidationIssue }> = [];\n for (const flow of ctx.bundle.flow_definitions) {\n const handle = typeof flow.name === \"string\" ? flow.name : \"flow\";\n for (const issue of validateFlowDefinition(flow, schemaFor(ctx, flow))) {\n if (issue.severity === \"error\") {\n failures.push({ handle, issue });\n } else {\n reportWarning(`${handle}: ${issue.message}`);\n }\n }\n }\n if (failures.length === 0) {\n return;\n }\n const noun = failures.length === 1 ? \"issue\" : \"issues\";\n throw new ZitadelError(\n \"E_VALIDATION\",\n `Flow validation failed (${failures.length} ${noun}):\\n` +\n failures.map(({ handle, issue }) => ` - ${handle}: ${issue.message}`).join(\"\\n\"),\n {\n hint: \"These are the same rules the server enforces. Fix the flow definition(s) and re-run.\",\n details: {\n issues: failures.map(({ handle, issue }) => ({\n handle,\n rule: issue.rule,\n message: issue.message,\n ...(issue.step === undefined ? {} : { step: issue.step }),\n })),\n },\n },\n );\n}\n\n/**\n * Fail when a `${VAR}` or `*_env` reference names an environment variable the\n * running environment does not hold: the deploy would otherwise send the\n * placeholder literally, and the login page would never resolve it. The server\n * cannot check this — the references point at the deployer's environment.\n */\n/** The bundle's branding as a list, empty when it carries none. */\nfunction brandingsOf(ctx: StepContext): Record<string, unknown>[] {\n return ctx.bundle.branding === undefined ? [] : [ctx.bundle.branding];\n}\n\nfunction assertEnvRefsResolve(ctx: StepContext): void {\n const missing = new Set<string>();\n for (const resource of [\n ...ctx.bundle.schemas,\n ...ctx.bundle.flow_definitions,\n ...brandingsOf(ctx),\n ]) {\n for (const name of flowEnvRefs(resource)) {\n if (!ctx.env[name]) {\n missing.add(name);\n }\n }\n }\n if (missing.size > 0) {\n throw new ZitadelError(\n \"E_VALIDATION\",\n `Missing environment variables: ${[...missing].sort().join(\", \")}`,\n );\n }\n}\n","import { brandingReferencePaths } from \"../../branding\";\nimport { type ConfigDiffFile, diffConfigAgainst, diffConfigFilesAgainst } from \"../git\";\nimport type { Step, StepContext, StepReport } from \"../pipeline\";\nimport { listLiveDeployments, servesPrimary } from \"../deployment\";\n\n/**\n * The diff as `--json` reports it, in `data.diff`: what the terminal shows,\n * split by file.\n */\nexport interface ConfigDiff {\n /** The commit of the release the primary origins serve: what the diff is against. */\n readonly against: string | null;\n /**\n * One entry per changed file: empty when nothing changed, null when no diff\n * can be shown, with `note` saying why.\n */\n readonly files: readonly ConfigDiffFile[] | null;\n /** The line the terminal prints instead of the diff, or above it. */\n readonly note?: string;\n}\n\n/**\n * Show what `.zitadel/` changed since the release the target serves now.\n *\n * It reads the live release's `git_sha` from its metadata and runs\n * `git diff <sha> -- .zitadel/` against the working tree. There is no diff\n * library and no server fallback: when git is missing, this is not a repo, the\n * commit is not in local history, or the live release carries no `git_sha`, it\n * prints one line saying no diff is available and carries on. Colour is\n * suppressed under `--no-color` and a non-terminal. Under `--json` nothing is\n * printed, so the envelope travels alone on stdout: the diff, split by file, or\n * the line saying why there is none, is reported as `diff` instead.\n */\nexport const diffStep: Step = {\n name: \"diff\",\n runsFor: [\"deploy\", \"preview\"],\n async run(ctx: StepContext): Promise<StepReport | undefined> {\n const deployments = await listLiveDeployments(ctx.client, ctx.projectId, {\n withRelease: true,\n });\n // What the primary origins serve: a live preview deployment is never the\n // baseline, even when it is the newest one in the project.\n const live = deployments.find(servesPrimary)?.release?.metadata;\n const sha = live?.git_sha;\n if (!sha) {\n return noDiff(\n ctx,\n null,\n \"No diff available: nothing is deployed yet, or the live release has no commit.\",\n );\n }\n // A release built from an uncommitted tree records the commit it was built\n // from, not the content it pinned, so a diff against it can come back empty\n // while this deploy would still change what is live.\n if (live?.git_dirty) {\n return noDiff(\n ctx,\n sha,\n `No reliable diff available: the live release was built from an uncommitted tree at ${sha.slice(0, 12)}.`,\n );\n }\n\n // The deploy lands on every primary origin, and they need not serve the\n // same release: the diff is against the newest one, so it is said aloud\n // that another origin moves from something else.\n const releases = new Set(deployments.filter(servesPrimary).map((entry) => entry.release_id));\n const note =\n releases.size > 1\n ? `The primary origins serve ${releases.size} different releases; the diff is against the newest, ${sha.slice(0, 12)}.`\n : undefined;\n const unknown = `No diff available: ${sha.slice(0, 12)} is not in this repository's history.`;\n\n const referenced = ctx.brandingSources.flatMap((descriptor) =>\n brandingReferencePaths(ctx.cwd, descriptor),\n );\n if (ctx.json) {\n const files = await diffConfigFilesAgainst(ctx.cwd, sha, referenced);\n if (files === null) {\n return noDiff(ctx, sha, unknown);\n }\n const diff: ConfigDiff = { against: sha, files, ...(note === undefined ? {} : { note }) };\n return { diff };\n }\n\n if (note !== undefined) {\n process.stdout.write(`${note}\\n`);\n }\n const diff = await diffConfigAgainst(ctx.cwd, sha, ctx.color, referenced);\n if (diff === null) {\n return noDiff(ctx, sha, unknown);\n }\n const shown = diff.trim() === \"\" ? `No changes to .zitadel/ since ${sha.slice(0, 12)}.` : diff;\n process.stdout.write(shown.endsWith(\"\\n\") ? shown : `${shown}\\n`);\n return undefined;\n },\n};\n\n/** No diff to show: the line saying why, printed, or reported under `--json`. */\nfunction noDiff(ctx: StepContext, against: string | null, note: string): StepReport | undefined {\n if (!ctx.json) {\n process.stdout.write(`${note}\\n`);\n return undefined;\n }\n const diff: ConfigDiff = { against, files: null, note };\n return { diff };\n}\n","/**\n * The publish pipeline: build a release bundle from `.zitadel/`, run the steps\n * that prepare and check it, create the release, and deploy it. `deploy` and\n * (later) `preview` are thin compositions of these.\n */\nexport { buildBundle, type BuiltBundle, type ConfigurationBundle } from \"./bundle\";\nexport {\n createReleaseFromBundle,\n revokeRelease,\n type Release,\n type ReleaseSource,\n} from \"./release\";\nexport {\n createDeployment,\n rollbackDeployment,\n type Deployment,\n type DeployTargets,\n} from \"./deployment\";\nexport { worktreeIsDirty, headSha } from \"./git\";\nexport { runSteps, type PipelineMode, type Step, type StepContext } from \"./pipeline\";\nexport { validateStep } from \"./steps/validate\";\nexport { diffStep } from \"./steps/diff\";\nexport { originMatchesPattern, type ProjectOriginEntry } from \"./origins\";\n\n/**\n * The arguments of a suggested publish. `deploy` refuses to run without `-m` when\n * no one can be asked for a message, which is every agent and every `--json`\n * run, so a suggested deploy carries one for the reader to fill in.\n */\nexport const DEPLOY_ARGS = \"deploy -m '<what changed>'\";\nexport { type ListedDeployment, listLiveDeployments, servesPrimary } from \"./deployment\";\n","import pc from \"picocolors\";\nimport wrapAnsi from \"wrap-ansi\";\n\n/**\n * Frame overhead of a `consola.box` with `padding: 1`: two border columns,\n * the padding columns, and consola's left margin. Content wrapped to the\n * terminal width minus this stays inside the frame instead of soft-wrapping\n * under the right border.\n */\nconst BOX_OVERHEAD = 8;\nconst MIN_CONTENT_WIDTH = 20;\nconst MAX_TERMINAL_WIDTH = 80;\n\n/** Bold cyan, for commands the user should run (URLs/paths stay plain cyan). */\nexport const command = (s: string): string => pc.bold(pc.cyan(s));\n\n/**\n * Wraps box content to the terminal (capped at 80 columns) so consola's\n * frame, which sizes itself to the longest content line, never exceeds the\n * window. ANSI-aware, preserves hard line breaks and indentation, and never\n * splits a token: URLs and commands stay whole for clicking, copying, and the\n * journey e2e scrape (claim.spec.ts), even when such a token alone is wider\n * than a very narrow window.\n */\nexport function wrapForBox(message: string, columns = process.stdout.columns): string {\n const width = Math.max(\n MIN_CONTENT_WIDTH,\n Math.min(columns ?? MAX_TERMINAL_WIDTH, MAX_TERMINAL_WIDTH) - BOX_OVERHEAD,\n );\n return wrapAnsi(message, width, { hard: false, trim: false });\n}\n\n/**\n * A next-step line for the human box: prose plus, when the step is literally\n * a command to run, that command pulled out of the sentence. The JSON\n * envelope keeps its own plain `next_actions`/`next_commands` strings; this\n * shape exists only so {@link renderBoxActions} can put the command alone on\n * an indented styled line, where it stands out and a drag-select copies it\n * without surrounding prose. (Line selection such as triple-click still\n * includes the box border and padding — commands that must copy as a whole\n * physical line belong outside a frame, like the claim URL.)\n */\nexport type BoxAction = { text: string; command?: string };\n\nexport function renderBoxActions(actions: BoxAction[]): string {\n return actions\n .map((action) =>\n action.command ? `${action.text}\\n\\n ${command(action.command)}` : action.text,\n )\n .join(\"\\n\\n\");\n}\n","import { publicCliCommand } from \"./public-cli\";\nimport { type EnvironmentSelector, projectCommand } from \"./suggestion\";\nimport { DEPLOY_ARGS } from \"./release\";\n\n/**\n * Guidance copy that commands share, so the story doesn't fork; most of it is\n * the journey-staged copy of `setup` and `status`.\n *\n * The staging exists because of alpha tester feedback (Elina, alpha.15):\n * printing customize/publish steps before the user has logged in once reads\n * as noise, but dropping them entirely recreates the round-1 dead end where\n * nothing pointed to the next step. So the guidance tracks journey position —\n * verify first, customize/publish once login demonstrably works — and both\n * commands quote the same copy so the story doesn't fork.\n */\n\n/**\n * The verify mission: prove the scaffolded auth round-trips before touching\n * config. `openUrl` prefixes the browser destination for callers that have\n * not already narrated it (setup's box has a separate \"Start your project\"\n * line; status has only the issuer).\n */\nexport function verifyLoginAction(openUrl?: string): string {\n const open = openUrl ? `open ${openUrl}, ` : \"\";\n return (\n `Verify auth in the browser: ${open}register a user, log out, ` +\n \"log in again with the same user, and confirm /profile shows Signed in.\"\n );\n}\n\n/**\n * Where to look when something fails against the local server, shared by\n * `start` and `doctor`. A sign-in step only says that a provider or a check\n * failed, because the login is public; the server logs why.\n */\nexport function serverLogAction(cliVersion: string): string {\n return (\n \"When a sign-in or a request fails, the server's log says why: run \" +\n `${publicCliCommand(\"logs --follow\", cliVersion)} in another terminal to watch it.`\n );\n}\n\n/**\n * Where the list of every command is: the CLI run with no subcommand. Setup,\n * status and every command's help end with it, after their own next steps, so\n * the overview can be found without already knowing it exists. The command is on\n * a line of its own, with nothing around it, so it can be copied as written.\n */\nexport function exploreAllCommands(cliVersion: string): string {\n return [\"Explore all commands:\", ` ${publicCliCommand(\"\", cliVersion)}`].join(\"\\n\");\n}\n\n/**\n * The customize/publish pair, in Elina's tested wording. `selector` is the\n * run's environment selection, so the quoted commands publish to the project\n * the run was about.\n */\nexport function customizeAndPublishActions(\n cliVersion: string,\n selector: EnvironmentSelector,\n): string[] {\n return [\n \"Customize what you ask for and how people sign in: edit .zitadel/schemas/ to change \" +\n \"the information you collect, and .zitadel/flows/ to change the sign-up/sign-in \" +\n \"experience. Each folder has a README with examples.\",\n `See your changes before they go live: ${projectCommand(\"deploy --dry-run\", selector, cliVersion)} to ` +\n `preview, then ${projectCommand(DEPLOY_ARGS, selector, cliVersion)} to publish. Nothing is ` +\n \"released yet, so publishing is what pins this configuration rather than leaving the project \" +\n \"on whatever its newest revisions happen to be.\",\n ];\n}\n\n/**\n * How to change the login's look after setup. Setup never ejects a template\n * or publishes a branding revision (#1039): the app embeds the maintained\n * `<zitadel-login>`, so its look is the app's own CSS (`--zl-*` tokens) and\n * layout around it. Taking ownership of the widget's structure stays the\n * opt-in `branding eject`, surfaced here so it remains discoverable.\n */\nexport function brandingGuidanceAction(cliVersion: string): string {\n return (\n \"Change how the login looks: it is a component in your app, so theme it with `--zl-*` \" +\n \"custom properties in your own stylesheet and build any page layout around it in your \" +\n \"code. To change the widget's structure, \" +\n `${publicCliCommand(\"branding eject\", cliVersion)} scaffolds an editable template ` +\n \"in .zitadel/branding/.\"\n );\n}\n","import { existsSync, mkdirSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nimport consola from \"consola\";\nimport * as rosie from \"rosie-skills\";\n\nimport { command } from \"./box\";\nimport { telemetryConfigDir } from \"./telemetry/identity\";\n\nexport type SkillsHintInput = {\n env: NodeJS.ProcessEnv;\n /** False for `--json`, `--non-interactive`, or a non-TTY stream. */\n interactive: boolean;\n};\n\nconst SHOWN_FILE = \"skills-hint.json\";\nconst INSTALL_COMMAND = \"npx skills add zitadel/nextgen --full-depth\";\n\n/**\n * Tell a developer who has AI coding agents installed how to give them the\n * Zitadel skills, once per machine and after the command's own next steps.\n * The CLI never installs anything itself: it names the command and the\n * developer runs it. Modelled on Wrangler's skills suggestion, minus the prompt.\n *\n * The marker lives in the user's CLI config directory (`telemetryConfigDir`),\n * not in a project, so a second project on the same machine does not show it\n * again. It is written only once the note is about to be shown, and removed\n * again if showing it fails.\n *\n * Silent in CI, in non-interactive runs, when no agent is detected, once it has\n * been shown, and when `NO_SKILLS_PROMPT` is set. Fail-open: nothing here may\n * fail the command the user actually ran, and losing the race to create the marker\n * (`EEXIST`) just means another run is showing the note.\n */\nexport async function showSkillsHint({ env, interactive }: SkillsHintInput): Promise<void> {\n try {\n if (!interactive || isCI(env) || isOptedOut(env)) {\n return;\n }\n const shownPath = join(telemetryConfigDir(env), SHOWN_FILE);\n if (existsSync(shownPath)) {\n return;\n }\n // Detected agents only decide whether the note is relevant; it does not\n // name them.\n const detected = (await rosie.agents()).some(\n (agent) => agent.detected && agent.installPath !== null,\n );\n if (!detected) {\n return;\n }\n // Created exclusively and before printing: of two concurrent first runs only\n // one gets past `wx`, and an interrupted run never shows the note twice.\n mkdirSync(dirname(shownPath), { recursive: true });\n writeFileSync(shownPath, `${JSON.stringify({ date: new Date().toISOString() })}\\n`, {\n flag: \"wx\",\n });\n\n try {\n consola.log(\n [\n \"\",\n \"Using an AI coding agent?\",\n \"Install Zitadel skills to help your agent work with Zitadel’s CLI and authentication integrations:\",\n \"\",\n ` ${command(INSTALL_COMMAND)}`,\n \"\",\n \"Optional. You can continue without installing skills.\",\n ].join(\"\\n\"),\n );\n } catch (error) {\n // Not shown after all, so it must not count as shown.\n unlinkSync(shownPath);\n throw error;\n }\n } catch {\n // A hint must never break `setup` or the root help.\n }\n}\n\nfunction isCI(env: NodeJS.ProcessEnv): boolean {\n return Boolean(env.CI) && env.CI !== \"0\" && env.CI !== \"false\";\n}\n\nfunction isOptedOut(env: NodeJS.ProcessEnv): boolean {\n const value = env.NO_SKILLS_PROMPT?.trim().toLowerCase();\n return value !== undefined && value !== \"\" && value !== \"0\" && value !== \"false\";\n}\n"],"mappings":"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"}
|