@zitadel/config 1.0.0-alpha.21 → 1.0.0-alpha.23

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.
Files changed (49) hide show
  1. package/README.md +2 -0
  2. package/defaults/README-branding.md +1 -1
  3. package/defaults/README-flows.md +9 -4
  4. package/defaults/default-login.json +0 -27
  5. package/dist/branding-contrast.d.mts +107 -0
  6. package/dist/branding-contrast.d.mts.map +1 -0
  7. package/dist/branding-contrast.mjs +229 -0
  8. package/dist/branding-contrast.mjs.map +1 -0
  9. package/dist/css-color.d.mts +36 -0
  10. package/dist/css-color.d.mts.map +1 -0
  11. package/dist/css-color.mjs +231 -0
  12. package/dist/css-color.mjs.map +1 -0
  13. package/dist/{defaults-Bh4_xVbh.d.mts → defaults-BxGCGdqS.d.mts} +5 -3
  14. package/dist/defaults-BxGCGdqS.d.mts.map +1 -0
  15. package/dist/{defaults-DPq0o3iU.mjs → defaults-DV6hY2KT.mjs} +25 -53
  16. package/dist/defaults-DV6hY2KT.mjs.map +1 -0
  17. package/dist/defaults.d.mts +1 -1
  18. package/dist/defaults.mjs +1 -1
  19. package/dist/index.d.mts +3 -3
  20. package/dist/index.mjs +4 -4
  21. package/dist/meta-schemas-OowgSUfU.mjs +1173 -0
  22. package/dist/meta-schemas-OowgSUfU.mjs.map +1 -0
  23. package/dist/meta-schemas.d.mts +4 -3
  24. package/dist/meta-schemas.d.mts.map +1 -1
  25. package/dist/meta-schemas.mjs +1 -1
  26. package/dist/schemas-7oNU25Qz.mjs +173 -0
  27. package/dist/schemas-7oNU25Qz.mjs.map +1 -0
  28. package/dist/schemas.d.mts +12 -5
  29. package/dist/schemas.d.mts.map +1 -1
  30. package/dist/schemas.mjs +3 -69
  31. package/dist/validate.d.mts +8 -2
  32. package/dist/validate.d.mts.map +1 -1
  33. package/dist/validate.mjs +9 -2
  34. package/dist/validate.mjs.map +1 -1
  35. package/meta-schemas/auth-method.json +1 -0
  36. package/meta-schemas/auth-methods.json +5 -3
  37. package/meta-schemas/branding.json +268 -19
  38. package/meta-schemas/flow-definition.json +375 -171
  39. package/meta-schemas/idp-connection.json +397 -0
  40. package/meta-schemas/property-name.json +1 -0
  41. package/meta-schemas/sso-auth-method.json +54 -0
  42. package/meta-schemas/user-property.json +10 -13
  43. package/meta-schemas/user-schema.json +20 -13
  44. package/package.json +18 -5
  45. package/dist/defaults-Bh4_xVbh.d.mts.map +0 -1
  46. package/dist/defaults-DPq0o3iU.mjs.map +0 -1
  47. package/dist/meta-schemas-z4IlqbLd.mjs +0 -531
  48. package/dist/meta-schemas-z4IlqbLd.mjs.map +0 -1
  49. package/dist/schemas.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"defaults-DPq0o3iU.mjs","names":["defaultHumanUserSchemaTemplate","defaultLoginFlowTemplate","passkeyFirstHumanUserSchemaTemplate","passkeyFirstLoginFlowTemplate"],"sources":["../defaults/default-human-user.json","../defaults/default-login.json","../defaults/presets/passkey-first/human-user.json","../defaults/presets/passkey-first/login.json","../src/readmes.ts","../src/defaults.ts"],"sourcesContent":["","","","","import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * README content the CLI copies to `.zitadel/schemas/README.md` during setup.\n * Source of truth is `packages/config/defaults/README-schemas.md`; the Go\n * server-side embed reads the same file (see `defaults.go`).\n */\nexport function schemasReadmeContent(): string {\n return readFileSync(readmeUrl(\"README-schemas.md\"), \"utf8\");\n}\n\n/**\n * README content the CLI copies to `.zitadel/flows/README.md` during setup.\n * Source of truth is `packages/config/defaults/README-flows.md`.\n */\nexport function flowsReadmeContent(): string {\n return readFileSync(readmeUrl(\"README-flows.md\"), \"utf8\");\n}\n\n/**\n * README content the CLI copies to `.zitadel/branding/README.md` when a\n * branding design is ejected. Source of truth is\n * `packages/config/defaults/README-branding.md`.\n */\nexport function brandingReadmeContent(): string {\n return readFileSync(readmeUrl(\"README-branding.md\"), \"utf8\");\n}\n\nfunction readmeUrl(filename: string): string {\n return fileURLToPath(new URL(`../defaults/${filename}`, import.meta.url));\n}\n","import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type {\n CreateFlowDefinitionBodyFlowDefinition,\n CreateSchemaBody,\n} from \"@zitadel/api/generated/model\";\n\nimport defaultHumanUserSchemaTemplate from \"../defaults/default-human-user.json\" with {\n type: \"json\",\n};\nimport defaultLoginFlowTemplate from \"../defaults/default-login.json\" with {\n type: \"json\",\n};\nimport passkeyFirstHumanUserSchemaTemplate from \"../defaults/presets/passkey-first/human-user.json\" with {\n type: \"json\",\n};\nimport passkeyFirstLoginFlowTemplate from \"../defaults/presets/passkey-first/login.json\" with {\n type: \"json\",\n};\n\nexport { brandingReadmeContent, flowsReadmeContent, schemasReadmeContent } from \"./readmes.js\";\n\nexport const DEFAULT_BUILTIN_SCHEMA_BASE = \"https://nextgen.com/api/schemas\";\nexport const DEFAULT_FLOW_SCHEMA_URI = \"https://nextgen.com/flow-definition.json\";\nexport const DEFAULT_SCHEMA_CONFIG_PATH = \".zitadel/schemas/default-human-user.json\";\nexport const DEFAULT_FLOW_CONFIG_PATH = \".zitadel/flows/default-login.json\";\nexport const DEFAULT_BRANDING_CONFIG_PATH = \".zitadel/branding/branding.json\";\nexport const DEFAULT_BRANDING_TEMPLATE_PATH = \".zitadel/branding/login.liquid\";\n\n/**\n * Named schema+flow bundles `zitadel setup` can scaffold (#448: the prompt\n * fires before any `.zitadel/` file is written; each preset maps to a\n * pre-defined bundle the CLI copies on first setup). `password-first` is\n * today's default; `passkey-first` puts a passkey ceremony on the login\n * entry step with an email→password fallback path.\n */\nexport const SETUP_PRESETS = [\"password-first\", \"passkey-first\"] as const;\n\nexport type SetupPreset = (typeof SETUP_PRESETS)[number];\n\nexport const DEFAULT_SETUP_PRESET: SetupPreset = \"password-first\";\n\nconst PRESET_TEMPLATES: Record<SetupPreset, { schema: unknown; flow: unknown }> = {\n \"password-first\": {\n schema: defaultHumanUserSchemaTemplate,\n flow: defaultLoginFlowTemplate,\n },\n \"passkey-first\": {\n schema: passkeyFirstHumanUserSchemaTemplate,\n flow: passkeyFirstLoginFlowTemplate,\n },\n};\n\nfunction presetTemplates(preset: string): { schema: unknown; flow: unknown } {\n // Own-property check: indexing a plain object with an arbitrary string\n // would let \"__proto__\"/\"constructor\" resolve via the prototype chain\n // and bypass the unknown-preset error.\n if (!Object.hasOwn(PRESET_TEMPLATES, preset)) {\n throw new Error(\n `unknown setup preset ${JSON.stringify(preset)} (known presets: ${SETUP_PRESETS.join(\", \")})`,\n );\n }\n return PRESET_TEMPLATES[preset as SetupPreset];\n}\n\n/**\n * Login-design starting points `zitadel branding eject --design <name>` (and\n * `zitadel setup --design <name>`) scaffold into `.zitadel/branding/`. A\n * design is a full Liquid template plus the descriptor `layout` it degrades\n * to — the wire `layout` enum stays `centered | split`, richer designs are\n * delivered as templates (ADR 040).\n */\nexport const BRANDING_DESIGNS = [\"centered\", \"split\", \"split-right\", \"hero\", \"minimal\"] as const;\n\nexport type BrandingDesign = (typeof BRANDING_DESIGNS)[number];\n\nexport const DEFAULT_BRANDING_DESIGN: BrandingDesign = \"centered\";\n\n/** Descriptor `layout` each design degrades to when its template is rejected. */\nconst DESIGN_LAYOUTS: Record<BrandingDesign, \"centered\" | \"split\"> = {\n centered: \"centered\",\n split: \"split\",\n \"split-right\": \"split\",\n hero: \"split\",\n minimal: \"centered\",\n};\n\nexport type DefaultBrandingConfig = {\n /** The `.zitadel/branding/branding.json` descriptor body (sans `$schema`). */\n branding: {\n layout: \"centered\" | \"split\";\n liquid_template_file: string;\n };\n /** The `.zitadel/branding/login.liquid` template content. */\n template: string;\n};\n\n/**\n * Renders the scaffold files for a branding design. The `centered` template\n * is a drift-tested copy of the bundled default in `@zitadel/components`;\n * the other designs are authored variants of it.\n */\nexport function getDefaultBrandingConfig(\n design: string = DEFAULT_BRANDING_DESIGN,\n): DefaultBrandingConfig {\n if (!Object.hasOwn(DESIGN_LAYOUTS, design)) {\n throw new Error(\n `unknown branding design ${JSON.stringify(design)} (known designs: ${BRANDING_DESIGNS.join(\", \")})`,\n );\n }\n const known = design as BrandingDesign;\n return {\n branding: {\n layout: DESIGN_LAYOUTS[known],\n liquid_template_file: \"./login.liquid\",\n },\n template: readFileSync(packageFilePath(`../defaults/branding/${known}/login.liquid`), \"utf8\"),\n };\n}\n\n/**\n * Resolves a package-relative file to a real filesystem path. Vite-driven\n * runtimes (vitest in dependent packages) rewrite `import.meta.url` to a\n * `/@fs/...` URL, which `fileURLToPath` passes through verbatim — strip the\n * prefix so `readFileSync` gets an actual path.\n */\nfunction packageFilePath(relative: string): string {\n const path = fileURLToPath(new URL(relative, import.meta.url));\n return path.startsWith(\"/@fs/\") ? path.slice(\"/@fs\".length) : path;\n}\n\n/**\n * The second setup axis (#448): *who* signs in, orthogonal to the sign-in\n * preset (*how* they sign in). The sign-in preset owns the flow shape and\n * auth methods; the use case owns which profile fields the schema collects.\n * Composing the two keeps us at one field catalog + one flow-per-preset\n * instead of a bundle per (use case × preset) pair. `minimal` is the\n * default and never blocks non-interactive runs.\n */\nexport const SETUP_USE_CASES = [\"minimal\", \"consumer\", \"business\"] as const;\n\nexport type SetupUseCase = (typeof SETUP_USE_CASES)[number];\n\nexport const DEFAULT_SETUP_USE_CASE: SetupUseCase = \"minimal\";\n\n/**\n * Fields each use case collects, in register/display order. `email` is\n * always first and stays the only required property; the rest are optional\n * profile attributes gathered on the flow's register step. `givenName`/\n * `familyName` are the attributes the backend reads for a user's identity\n * (`internal/domain/user.go`); `companyName` is stored as a plain user\n * attribute today — there is no org/team model behind it yet.\n */\nconst USE_CASE_FIELDS: Record<SetupUseCase, readonly string[]> = {\n minimal: [\"email\"],\n consumer: [\"email\", \"givenName\", \"familyName\"],\n business: [\"email\", \"givenName\", \"familyName\", \"companyName\"],\n};\n\n/**\n * JSON-Schema bodies for the optional profile fields the CLI composes in per\n * use case. The shipped templates are an email-only baseline (shared verbatim\n * with the Go server fallback), so this catalog owns every field beyond\n * `email`. Authored in the templates' style — no `x-claim`, since the backend\n * maps identity by attribute name and the user-property meta-schema defines no\n * claim keyword. `givenName`/`familyName` are the attributes the backend reads\n * for a user's identity (`internal/domain/user.go`).\n */\nconst EXTRA_FIELD_BODIES: Record<string, Record<string, unknown>> = {\n givenName: {\n type: \"string\",\n maxLength: 50,\n description: \"The user's given (first) name.\",\n },\n familyName: {\n type: \"string\",\n maxLength: 50,\n description: \"The user's family (last) name.\",\n },\n companyName: {\n type: \"string\",\n maxLength: 200,\n description: \"The user's company name.\",\n },\n};\n\nfunction useCaseFields(useCase: string): readonly string[] {\n // Own-property check, same rationale as presetTemplates: keep prototype\n // keys (\"__proto__\" etc.) from resolving to a real field list.\n if (!Object.hasOwn(USE_CASE_FIELDS, useCase)) {\n throw new Error(\n `unknown setup use case ${JSON.stringify(useCase)} (known use cases: ${SETUP_USE_CASES.join(\", \")})`,\n );\n }\n return USE_CASE_FIELDS[useCase as SetupUseCase];\n}\n\n/**\n * The body for one use-case field: reuse the template's authored body when it\n * has one (so composed schemas match the shipped defaults for shared fields),\n * else the extra catalog, else a generic editable string so composition stays\n * total for any field a future use case introduces.\n */\nfunction fieldBody(\n field: string,\n templateProps: Record<string, Record<string, unknown>>,\n): Record<string, unknown> {\n if (Object.hasOwn(templateProps, field)) {\n return { ...templateProps[field] };\n }\n if (Object.hasOwn(EXTRA_FIELD_BODIES, field)) {\n return { ...EXTRA_FIELD_BODIES[field] };\n }\n return { type: \"string\", description: `The user's ${field}.` };\n}\n\n/**\n * Narrow a rendered schema to the chosen use case: keep the preset-owned\n * header and `x-auth-methods`, but replace `properties`/`required` with the\n * use case's field set. `email` is the sole required property.\n */\nfunction applyUseCaseToSchema(\n schema: Record<string, unknown>,\n useCase: string,\n): Record<string, unknown> {\n const templateProps = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const properties: Record<string, unknown> = {};\n for (const field of useCaseFields(useCase)) {\n properties[field] = fieldBody(field, templateProps);\n }\n return { ...schema, required: [\"email\"], properties };\n}\n\n/**\n * Derive the flow's register-step fields from the use case rather than\n * copying a hard-coded list into every bundle (#448): the register step\n * collects exactly what the schema defines. Other steps are untouched.\n */\nfunction applyUseCaseToFlow(\n flow: Record<string, unknown>,\n useCase: string,\n): Record<string, unknown> {\n const fields = [...useCaseFields(useCase)];\n const steps = (flow.steps as Array<Record<string, unknown>>).map((step) =>\n step.name === \"register\" ? { ...step, fields } : step,\n );\n return { ...flow, steps };\n}\n\nexport type DefaultConfigRenderOptions = {\n builtinSchemaBase?: string;\n userSchemaUrl?: string;\n /** Which flow/auth bundle to render; defaults to {@link DEFAULT_SETUP_PRESET}. */\n preset?: string;\n /** Which field set to collect; defaults to {@link DEFAULT_SETUP_USE_CASE}. */\n useCase?: string;\n};\n\nexport function defaultHumanUserSchemaUrl(\n builtinSchemaBase = DEFAULT_BUILTIN_SCHEMA_BASE,\n): string {\n return `${trimTrailingSlash(builtinSchemaBase)}/default-human-user.json`;\n}\n\nexport function getDefaultHumanUserSchema(\n options: DefaultConfigRenderOptions = {},\n): CreateSchemaBody {\n const builtinSchemaBase = trimTrailingSlash(\n options.builtinSchemaBase ?? DEFAULT_BUILTIN_SCHEMA_BASE,\n );\n const rendered = renderTemplate(presetTemplates(options.preset ?? DEFAULT_SETUP_PRESET).schema, {\n SERVER_URL: builtinSchemaBase,\n USER_SCHEMA_URL: options.userSchemaUrl ?? defaultHumanUserSchemaUrl(builtinSchemaBase),\n }) as Record<string, unknown>;\n return applyUseCaseToSchema(\n rendered,\n options.useCase ?? DEFAULT_SETUP_USE_CASE,\n ) as CreateSchemaBody;\n}\n\nexport function getDefaultLoginFlow(\n options: DefaultConfigRenderOptions = {},\n): CreateFlowDefinitionBodyFlowDefinition {\n const builtinSchemaBase = trimTrailingSlash(\n options.builtinSchemaBase ?? DEFAULT_BUILTIN_SCHEMA_BASE,\n );\n const rendered = renderTemplate(presetTemplates(options.preset ?? DEFAULT_SETUP_PRESET).flow, {\n SERVER_URL: builtinSchemaBase,\n USER_SCHEMA_URL: options.userSchemaUrl ?? defaultHumanUserSchemaUrl(builtinSchemaBase),\n }) as Record<string, unknown>;\n return applyUseCaseToFlow(\n rendered,\n options.useCase ?? DEFAULT_SETUP_USE_CASE,\n ) as CreateFlowDefinitionBodyFlowDefinition;\n}\n\nfunction renderTemplate(value: unknown, replacements: Record<string, string>): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => renderTemplate(item, replacements));\n }\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, renderTemplate(item, replacements)]),\n );\n }\n if (typeof value === \"string\") {\n return value.replaceAll(/\\$\\{([A-Z_]+)\\}/g, (match, name: string) => {\n return replacements[name] ?? match;\n });\n }\n return value;\n}\n\nfunction trimTrailingSlash(value: string): string {\n let trimmed = value;\n while (trimmed.endsWith(\"/\")) {\n trimmed = trimmed.slice(0, -1);\n }\n return trimmed;\n}\n"],"mappings":"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"}
@@ -1,531 +0,0 @@
1
- //#region meta-schemas/auth-method.json
2
- var auth_method_default = {
3
- $schema: "https://json-schema.org/draft/2020-12/schema",
4
- title: "AuthMethod",
5
- type: "object",
6
- required: ["enabled"],
7
- additionalProperties: false,
8
- properties: { "enabled": {
9
- "type": "boolean",
10
- "description": "Whether the authentication method is enabled or not"
11
- } }
12
- };
13
- //#endregion
14
- //#region meta-schemas/auth-methods.json
15
- var auth_methods_default = {
16
- type: "object",
17
- $schema: "https://json-schema.org/draft/2020-12/schema",
18
- description: "A list of authentication methods supported by the user definition.",
19
- minProperties: 1,
20
- additionalProperties: false,
21
- properties: {
22
- "password": { "$ref": "auth-method.json" },
23
- "passkey": { "$ref": "auth-method.json" },
24
- "magic_link": { "$ref": "auth-method.json" },
25
- "sso": { "$ref": "auth-method.json" },
26
- "otp": { "$ref": "auth-method.json" }
27
- }
28
- };
29
- //#endregion
30
- //#region meta-schemas/branding.json
31
- var branding_default = {
32
- $schema: "https://json-schema.org/draft/2020-12/schema",
33
- title: "Branding",
34
- description: "Local branding descriptor for the login UI. Carries the layout preset, asset URLs, and the LiquidJS template (by file reference or inline). `zitadel apply` publishes this as an immutable branding revision; flow responses resolve the latest revision per project (ADR 040). This schema describes the local configuration shape only.",
35
- type: "object",
36
- additionalProperties: false,
37
- properties: {
38
- "$schema": {
39
- "type": "string",
40
- "description": "Editor affordance: path or URL of this meta-schema so editors validate and autocomplete the file (scaffolded branding files point at `.zitadel/meta/branding.json`). Ignored by the platform."
41
- },
42
- "layout": {
43
- "type": "string",
44
- "enum": ["centered", "split"],
45
- "default": "centered",
46
- "description": "Degrade preset (`centered` or `split`) the bundled default template branches on, not the complete design catalog. All named designs (`centered`, `split`, `split-right`, `hero`, `minimal`) ship as templates and map onto one of these two values; switch designs with the `branding eject --design <name>` command instead of editing this field. Custom templates may ignore it; the preset is also used when a template fails component-side validation."
47
- },
48
- "liquid_template_file": {
49
- "type": "string",
50
- "examples": ["./login.liquid"],
51
- "description": "Path to the LiquidJS template file, relative to this descriptor. The CLI inlines the file content into `liquid_template` when publishing, and writes server state back to the file. Mutually exclusive with `liquid_template`."
52
- },
53
- "liquid_template": {
54
- "type": "string",
55
- "maxLength": 131072,
56
- "description": "Inline LiquidJS template string. Prefer `liquid_template_file` — a real `.liquid` file edits far better than a JSON-escaped string. Mutually exclusive with `liquid_template_file`."
57
- },
58
- "logo_url": {
59
- "type": "string",
60
- "format": "uri",
61
- "pattern": "^([hH][tT][tT][pP][sS]://|[hH][tT][tT][pP]://([lL][oO][cC][aA][lL][hH][oO][sS][tT]|127\\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])|\\[::1\\])(?::0*(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?([/?#]|$))",
62
- "description": "Logo URL (https required; canonical loopback http is allowed for local development and renders only on loopback pages)."
63
- },
64
- "hero_url": {
65
- "type": "string",
66
- "format": "uri",
67
- "pattern": "^([hH][tT][tT][pP][sS]://|[hH][tT][tT][pP]://([lL][oO][cC][aA][lL][hH][oO][sS][tT]|127\\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])|\\[::1\\])(?::0*(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?([/?#]|$))",
68
- "description": "Hero/background image URL (https required; canonical loopback http is allowed for local development and renders only on loopback pages), used by split designs."
69
- }
70
- },
71
- not: { "required": ["liquid_template", "liquid_template_file"] }
72
- };
73
- //#endregion
74
- //#region meta-schemas/flow-definition.json
75
- var flow_definition_default = {
76
- $schema: "https://json-schema.org/draft/2020-12/schema",
77
- title: "FlowDefinition",
78
- description: "Admin-authored configuration for a flow. A flow definition is a directed graph of steps backed by a user schema. The flow engine selects a definition based on `purpose` and `audience`, then walks the graph by evaluating `transitions` against client submissions. This schema describes the configuration shape only. Runtime emission to the client (capability dictionaries, branding, localized text) is a separate concern and is not modelled here.",
79
- type: "object",
80
- required: [
81
- "name",
82
- "status",
83
- "user_schema",
84
- "purposes",
85
- "steps"
86
- ],
87
- additionalProperties: false,
88
- properties: {
89
- "$schema": {
90
- "type": "string",
91
- "description": "Editor affordance: path or URL of this meta-schema so editors validate and autocomplete the file (scaffolded flow files point at `.zitadel/meta/flow-definition.json`). Ignored by the platform."
92
- },
93
- "name": {
94
- "type": "string",
95
- "pattern": "^[a-z][a-z0-9-]*$",
96
- "examples": ["standard-login", "combined-auth"],
97
- "description": "Stable identifier for this flow, used as the target of cross-flow `switch` and `pivot` transitions. Renaming is not supported — the `name` is part of the public contract another definition may reference. Acts as the human display label as well; no separate slug."
98
- },
99
- "status": {
100
- "type": "string",
101
- "enum": ["active", "draft"],
102
- "description": "Lifecycle state. - active: the engine can select this definition for new flows. - draft: never selected for new flows; existing flows referencing it must handle it gracefully."
103
- },
104
- "user_schema": {
105
- "type": "string",
106
- "examples": ["sch_01KWHF18816ZQESRCS7Z2STJ05"],
107
- "description": "Server-assigned identifier of the user schema this flow operates on, as returned by `POST /schemas`. Opaque to the client — the shape is a server implementation detail. Step `fields` reference property names defined in that schema; the engine resolves field type, validation, and implicit transition outcomes from the schema's `x-*` annotations at runtime."
108
- },
109
- "purposes": {
110
- "type": "object",
111
- "minProperties": 1,
112
- "propertyNames": { "$ref": "#/$defs/Purpose" },
113
- "additionalProperties": {
114
- "type": "string",
115
- "description": "Name of an entry-point step within this definition."
116
- },
117
- "examples": [{ "login": "identify" }, {
118
- "login": "identify",
119
- "register": "identify"
120
- }],
121
- "description": "Maps each purpose this definition handles to the step that begins the flow for that purpose. Every value must match a `name` in `steps`; the check is enforced by the engine, not by this schema."
122
- },
123
- "audience": {
124
- "$ref": "#/$defs/Audience",
125
- "description": "Scopes which requests this definition applies to. Omitted or empty arrays mean project-wide. The engine ranks matches by specificity (app > team > project-wide)."
126
- },
127
- "steps": {
128
- "type": "array",
129
- "minItems": 1,
130
- "items": { "$ref": "#/$defs/Step" },
131
- "description": "Step graph. Order is for human readability; actual sequencing is determined entirely by `transitions`. Every step's `name` must be unique within this array."
132
- }
133
- },
134
- $defs: {
135
- "Purpose": {
136
- "type": "string",
137
- "enum": [
138
- "login",
139
- "register",
140
- "recovery",
141
- "profiling",
142
- "reauth",
143
- "link_account"
144
- ],
145
- "description": "What the user is trying to accomplish. - login: authenticate an existing user. - register: create a new user. - recovery: recover access (e.g. password reset). - profiling: collect required profile fields after authentication. - reauth: re-verify factors on an active session for step-up. - link_account: attach an external identity to an existing user."
146
- },
147
- "Audience": {
148
- "type": "object",
149
- "additionalProperties": false,
150
- "properties": {
151
- "team_ids": {
152
- "type": "array",
153
- "uniqueItems": true,
154
- "items": { "type": "string" },
155
- "examples": [["team_acme"]],
156
- "description": "Restrict to specific teams (organizations)."
157
- },
158
- "app_ids": {
159
- "type": "array",
160
- "uniqueItems": true,
161
- "items": { "type": "string" },
162
- "examples": [["app_dashboard"]],
163
- "description": "Restrict to specific applications."
164
- }
165
- }
166
- },
167
- "Step": {
168
- "type": "object",
169
- "required": ["name"],
170
- "additionalProperties": false,
171
- "properties": {
172
- "name": {
173
- "type": "string",
174
- "pattern": "^[a-z][a-z0-9-]*$",
175
- "examples": [
176
- "identify",
177
- "authenticate",
178
- "done"
179
- ],
180
- "description": "Unique step identifier within this definition. Slug-shaped so it is safe to use as a transition `target` and as a value in `purposes`. Referenced by other steps in the same definition."
181
- },
182
- "fields": {
183
- "type": "array",
184
- "uniqueItems": true,
185
- "items": { "type": "string" },
186
- "examples": [["email"], ["email", "password"]],
187
- "description": "Schema property names to collect from the user on this step. Each entry must resolve to a property in the definition's `user_schema`, or use the reserved token `x-auth-methods#<method>` (e.g. `x-auth-methods#password`) to collect a credential proof for a method enabled at the schema root. The engine reads the schema's `x-*` annotations to derive: - field type and validation (rendered into the runtime payload), - implicit transition outcomes - e.g. a property with a non-empty `x-unique` scope makes `user_not_found` a valid `transitions` key on this step."
188
- },
189
- "actions": {
190
- "type": "array",
191
- "items": { "$ref": "#/$defs/Action" },
192
- "description": "Ordered list of actions the user can take on this step. The `name` is what the client echoes back on submit. Every action's name must have a matching key in `transitions`; the engine rejects submissions for actions without a defined transition."
193
- },
194
- "gates": {
195
- "type": "object",
196
- "additionalProperties": { "$ref": "#/$defs/Gate" },
197
- "description": "Security challenges that must be satisfied before this step's submission is accepted. Keyed by gate name (free identifier; referenced as the key in the runtime `step.gates` dictionary). The engine may inject additional gates at runtime based on policy or risk evaluation."
198
- },
199
- "sso_providers": {
200
- "type": "array",
201
- "items": { "$ref": "#/$defs/SSOProvider" },
202
- "description": "Identity providers available on this step. When non-empty, the step must define a `transitions.callback` entry — the engine handles the reserved `sso` action transparently (redirect to the IdP, code exchange, user resolution) and fires `callback` on this step when the IdP returns. The flow author never writes a `transitions.sso`."
203
- },
204
- "on_success": {
205
- "type": "string",
206
- "enum": ["create_user"],
207
- "description": "Server-side mutation to run after the step's fields validate and before the transition fires. - create_user: materialize the user from collected schema fields. Used by register flows."
208
- },
209
- "complete": {
210
- "type": "string",
211
- "enum": ["redirect", "show"],
212
- "description": "Marks this step as terminal. A terminal step has no `fields`, `actions`, `transitions`, `gates`, or `sso_providers`. - redirect: client navigates to a `redirect_uri` resolved from the originating protocol request (OIDC, SAML). - show: client renders the step as a success or info screen."
213
- },
214
- "transitions": {
215
- "type": "object",
216
- "additionalProperties": { "$ref": "#/$defs/Transition" },
217
- "description": "Maps action names and engine-emitted outcomes to the next state. Keys are either: - an action name declared in this step's `actions`, or - a reserved outcome the engine produces: - `user_not_found` - emitted when a unique field (`x-unique`) does not match an existing user. - `user_already_exists` - emitted when registration matches an existing user. - `callback` - emitted when an external system returns control to the flow (SSO callback, device authorization poll, etc.). A transition's `action` field controls whether the target is interpreted as a step in this definition (default) or as the name of another definition to switch or pivot into."
218
- }
219
- }
220
- },
221
- "Action": {
222
- "type": "object",
223
- "additionalProperties": false,
224
- "properties": {
225
- "name": {
226
- "type": "string",
227
- "minLength": 1,
228
- "examples": [
229
- "submit",
230
- "passkey",
231
- "email_fallback"
232
- ],
233
- "description": "Action identifier, echoed back by the client on submit and matched against `transitions`. The name `back` is reserved for engine-injected back navigation."
234
- },
235
- "kind": {
236
- "type": "string",
237
- "enum": [
238
- "submit",
239
- "passkey",
240
- "passkey_register",
241
- "navigate"
242
- ],
243
- "description": "How the engine handles the action. - submit: collect the step's fields and run validate/dispatch/on_success. - passkey: issue a WebAuthn assertion challenge; the matching transition fires once the assertion verifies. - passkey_register: issue a WebAuthn registration challenge; the matching transition fires once the attestation verifies. - navigate: route through the transition without running the input pipeline. (`back` exists on the wire but is engine-injected; declaring it is rejected.)"
244
- },
245
- "primary": {
246
- "type": "boolean",
247
- "default": false,
248
- "description": "Marks this as the default/primary action. The runtime template uses this hint to choose visual emphasis. At most one action per step should be primary; this is not enforced here."
249
- },
250
- "text_key": {
251
- "type": "string",
252
- "examples": ["actions.signin.submit"],
253
- "description": "Optional localization key override for the action's label. When omitted, the engine derives a key from the step and action names. Display text is resolved client-side from a locale dictionary, never by the engine."
254
- }
255
- },
256
- "description": "Configuration for a user-invokable action on a step.",
257
- "required": ["name", "kind"]
258
- },
259
- "Gate": {
260
- "type": "object",
261
- "required": ["kind", "provider"],
262
- "additionalProperties": false,
263
- "properties": {
264
- "kind": {
265
- "type": "string",
266
- "enum": ["captcha"],
267
- "description": "The gate category. Only `captcha` is currently defined. Authenticator ceremonies (e.g. passkey) are modelled as credential auth_attempts via `x-credential` on a field, not as gates."
268
- },
269
- "provider": {
270
- "type": "string",
271
- "examples": [
272
- "altcha",
273
- "turnstile",
274
- "hcaptcha"
275
- ],
276
- "description": "Provider identifier within the gate kind — e.g. `altcha`, `turnstile`, `hcaptcha`. The engine looks up an implementation in its provider registry."
277
- },
278
- "config": {
279
- "type": "object",
280
- "additionalProperties": true,
281
- "examples": [{ "site_key": "0x4AAAAAAAxxxxxxxxxxxxxx" }],
282
- "description": "Provider-specific configuration consumed by the implementation when issuing the per-render challenge. Opaque to the engine."
283
- }
284
- }
285
- },
286
- "SSOProvider": {
287
- "type": "object",
288
- "required": [
289
- "id",
290
- "name",
291
- "template"
292
- ],
293
- "additionalProperties": false,
294
- "properties": {
295
- "id": {
296
- "type": "string",
297
- "examples": ["google", "corp_idp"],
298
- "description": "Provider instance identifier. Echoed back by the client when the user picks a provider; routed to the corresponding configured IdP at the engine."
299
- },
300
- "name": {
301
- "type": "string",
302
- "examples": ["Google", "Acme SSO"],
303
- "description": "Display name surfaced to the user. Localized client-side if a matching text key exists in the locale dictionary."
304
- },
305
- "template": {
306
- "type": "string",
307
- "examples": [
308
- "google",
309
- "entraid",
310
- "github"
311
- ],
312
- "description": "Hint for rendering (logo, brand colors) — e.g. `google`, `entraid`, `github`. Consumed by the runtime template, not by the engine."
313
- }
314
- }
315
- },
316
- "Transition": {
317
- "type": "object",
318
- "required": ["target"],
319
- "additionalProperties": false,
320
- "properties": {
321
- "target": {
322
- "type": "string",
323
- "examples": [
324
- "authenticate",
325
- "register",
326
- "recovery"
327
- ],
328
- "description": "When `action` is omitted, the `name` of a step in the same definition. When `action` is `switch` or `pivot`, the `name` of another flow definition in the same project."
329
- },
330
- "action": {
331
- "type": ["string", "null"],
332
- "enum": [
333
- "switch",
334
- "pivot",
335
- null
336
- ],
337
- "description": "How to interpret `target`. - Omitted: transition to a step in the current definition. - `switch`: replace the current flow with the target flow. No return; the current flow is discarded. Typical use: navigating between peer flows like login ↔ register. - `pivot`: push the target flow onto the stack. The current flow is paused; when the target flow completes the engine auto-pops back. Typical use: login → recovery → back to login."
338
- },
339
- "purpose": {
340
- "type": ["string", "null"],
341
- "enum": [
342
- "login",
343
- "register",
344
- "recovery",
345
- "profiling",
346
- "reauth",
347
- "link_account",
348
- null
349
- ],
350
- "description": "Local re-purposing. When set, taking this transition changes the flow's current purpose to this value — the dispatch mode a step's challenges run under — while the flow's original purpose stays pinned. Must be a purpose this definition serves, and `target` must be that purpose's entry step. Mutually exclusive with `action`: a transition either re-purposes within this flow or targets another flow, never both. Example: a \"Sign up\" navigation on the login identifier step (`{ \"target\": \"register\", \"purpose\": \"register\" }`)."
351
- }
352
- }
353
- }
354
- }
355
- };
356
- //#endregion
357
- //#region meta-schemas/property-name.json
358
- var property_name_default = {
359
- $schema: "https://json-schema.org/draft/2020-12/schema",
360
- title: "PropertyName",
361
- type: "string",
362
- pattern: "^[^.]+$",
363
- description: "The name of a single user attribute."
364
- };
365
- //#endregion
366
- //#region meta-schemas/user-property.json
367
- var user_property_default = {
368
- $schema: "https://json-schema.org/draft/2020-12/schema",
369
- title: "UserProperty",
370
- type: "object",
371
- allOf: [{ "$ref": "https://json-schema.org/draft/2020-12/schema" }],
372
- additionalProperties: true,
373
- properties: {
374
- "$schema": {
375
- "type": "string",
376
- "const": "https://json-schema.org/draft/2020-12/schema",
377
- "description": "The JSON Schema version used for this schema."
378
- },
379
- "x-unique": {
380
- "oneOf": [{
381
- "type": "string",
382
- "enum": [
383
- "unspecified",
384
- "project",
385
- "team"
386
- ]
387
- }, { "type": "null" }],
388
- "description": "The level of uniqueness for this property, if applicable"
389
- },
390
- "x-claim": {
391
- "oneOf": [{ "type": "string" }, { "type": "null" }],
392
- "description": "The claim name for this property, if applicable"
393
- },
394
- "x-audit": {
395
- "type": "boolean",
396
- "default": false,
397
- "description": "Whether this property's value may appear in audit event payloads. Audit payloads are deny-by-default: a property without this annotation contributes its key but never its value."
398
- },
399
- "properties": {
400
- "type": "object",
401
- "description": "A map of additional properties for the user definition, where the key is the property name and the value is the property schema",
402
- "propertyNames": { "$ref": "property-name.json" },
403
- "additionalProperties": { "$ref": "user-property.json" }
404
- }
405
- }
406
- };
407
- //#endregion
408
- //#region meta-schemas/user-schema.json
409
- var user_schema_default = {
410
- title: "UserSchema",
411
- $schema: "https://json-schema.org/draft/2020-12/schema",
412
- type: "object",
413
- required: [
414
- "metaSchema",
415
- "kind",
416
- "x-auth-methods"
417
- ],
418
- allOf: [{ "$ref": "https://json-schema.org/draft/2020-12/schema" }],
419
- additionalProperties: true,
420
- properties: {
421
- "$schema": {
422
- "type": "string",
423
- "const": "https://json-schema.org/draft/2020-12/schema",
424
- "description": "The JSON Schema version used for this schema."
425
- },
426
- "objectType": {
427
- "type": "string",
428
- "maxLength": 256,
429
- "description": "The type of user this schema describes. This is a customer chosen name.",
430
- "example": "human-user"
431
- },
432
- "kind": {
433
- "type": "string",
434
- "const": "user-schema",
435
- "description": "Discriminator value for a user schema create request."
436
- },
437
- "metaSchema": {
438
- "type": "string",
439
- "maxLength": 1024,
440
- "format": "uri",
441
- "description": "The user Schema version used for this schema."
442
- },
443
- "x-auth-methods": { "$ref": "auth-methods.json" },
444
- "x-identifier": {
445
- "type": "string",
446
- "minLength": 1,
447
- "description": "Path of the leaf property whose value identifies a user (nested leaves are addressed by their dot-joined attribute path). The property must carry x-unique \"project\". Required when an auth method needing identifier-first dispatch (password) is enabled. Passkey is exempt: discoverable credentials identify the user through the assertion itself, so passkey-only and API-managed schemas may designate nothing; flows using identifier-first passkey are validated at the flow level instead."
448
- },
449
- "x-display": {
450
- "type": "array",
451
- "minItems": 1,
452
- "items": {
453
- "type": "string",
454
- "minLength": 1
455
- },
456
- "description": "Ordered leaf property paths whose values, joined with a space, render the user's display name."
457
- },
458
- "properties": {
459
- "type": "object",
460
- "description": "A map of additional properties for the user definition, where the key is the property name and the value is the property schema",
461
- "propertyNames": { "$ref": "property-name.json" },
462
- "additionalProperties": { "$ref": "user-property.json" }
463
- }
464
- }
465
- };
466
- //#endregion
467
- //#region src/meta-schemas.ts
468
- /**
469
- * The dialect meta-schemas `zitadel setup` copies into a project's
470
- * `.zitadel/meta/` so the flow/schema dialect is machine-readable offline:
471
- * editors validate flow files against `flow-definition.json` via a relative
472
- * `$schema` pointer, and agents read the dialect files before authoring
473
- * edits — no docs crawl, no hosted schema required.
474
- *
475
- * The files under `meta-schemas/` are committed copies of
476
- * `api/openapi/endpoints/schemas/*.json` (the source the server embeds);
477
- * a drift-audit test keeps them byte-identical in the monorepo.
478
- */
479
- /** Project-relative directory setup writes the meta-schemas to. */
480
- const META_SCHEMA_DIR = ".zitadel/meta";
481
- /**
482
- * The `$schema` value scaffolded flow files carry, relative to
483
- * `.zitadel/flows/` — resolves to `{@link META_SCHEMA_DIR}/flow-definition.json`.
484
- */
485
- const FLOW_FILE_SCHEMA_REF = "../meta/flow-definition.json";
486
- /**
487
- * The `$schema` value scaffolded branding files carry, relative to
488
- * `.zitadel/branding/` — resolves to `{@link META_SCHEMA_DIR}/branding.json`.
489
- */
490
- const BRANDING_FILE_SCHEMA_REF = "../meta/branding.json";
491
- /**
492
- * The dialect files to materialize, in write order. `auth-methods.json` and
493
- * `auth-method.json` are pulled in by `user-schema.json`'s relative `$ref`s —
494
- * without them the copied dialect cannot resolve offline.
495
- */
496
- function metaSchemaFiles() {
497
- return [
498
- {
499
- name: "flow-definition.json",
500
- body: flow_definition_default
501
- },
502
- {
503
- name: "user-schema.json",
504
- body: user_schema_default
505
- },
506
- {
507
- name: "user-property.json",
508
- body: user_property_default
509
- },
510
- {
511
- name: "property-name.json",
512
- body: property_name_default
513
- },
514
- {
515
- name: "auth-methods.json",
516
- body: auth_methods_default
517
- },
518
- {
519
- name: "auth-method.json",
520
- body: auth_method_default
521
- },
522
- {
523
- name: "branding.json",
524
- body: branding_default
525
- }
526
- ];
527
- }
528
- //#endregion
529
- export { metaSchemaFiles as i, FLOW_FILE_SCHEMA_REF as n, META_SCHEMA_DIR as r, BRANDING_FILE_SCHEMA_REF as t };
530
-
531
- //# sourceMappingURL=meta-schemas-z4IlqbLd.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"meta-schemas-z4IlqbLd.mjs","names":["flowDefinitionMetaSchema","userSchemaMetaSchema","userPropertyMetaSchema","propertyNameMetaSchema","authMethodsMetaSchema","authMethodMetaSchema","brandingMetaSchema"],"sources":["../meta-schemas/auth-method.json","../meta-schemas/auth-methods.json","../meta-schemas/branding.json","../meta-schemas/flow-definition.json","../meta-schemas/property-name.json","../meta-schemas/user-property.json","../meta-schemas/user-schema.json","../src/meta-schemas.ts"],"sourcesContent":["","","","","","","","/**\n * The dialect meta-schemas `zitadel setup` copies into a project's\n * `.zitadel/meta/` so the flow/schema dialect is machine-readable offline:\n * editors validate flow files against `flow-definition.json` via a relative\n * `$schema` pointer, and agents read the dialect files before authoring\n * edits — no docs crawl, no hosted schema required.\n *\n * The files under `meta-schemas/` are committed copies of\n * `api/openapi/endpoints/schemas/*.json` (the source the server embeds);\n * a drift-audit test keeps them byte-identical in the monorepo.\n */\nimport authMethodMetaSchema from \"../meta-schemas/auth-method.json\" with {\n type: \"json\",\n};\nimport authMethodsMetaSchema from \"../meta-schemas/auth-methods.json\" with {\n type: \"json\",\n};\nimport brandingMetaSchema from \"../meta-schemas/branding.json\" with {\n type: \"json\",\n};\nimport flowDefinitionMetaSchema from \"../meta-schemas/flow-definition.json\" with {\n type: \"json\",\n};\nimport propertyNameMetaSchema from \"../meta-schemas/property-name.json\" with {\n type: \"json\",\n};\nimport userPropertyMetaSchema from \"../meta-schemas/user-property.json\" with {\n type: \"json\",\n};\nimport userSchemaMetaSchema from \"../meta-schemas/user-schema.json\" with {\n type: \"json\",\n};\n\n/** Project-relative directory setup writes the meta-schemas to. */\nexport const META_SCHEMA_DIR = \".zitadel/meta\";\n\n/**\n * The `$schema` value scaffolded flow files carry, relative to\n * `.zitadel/flows/` — resolves to `{@link META_SCHEMA_DIR}/flow-definition.json`.\n */\nexport const FLOW_FILE_SCHEMA_REF = \"../meta/flow-definition.json\";\n\n/**\n * The `$schema` value scaffolded branding files carry, relative to\n * `.zitadel/branding/` — resolves to `{@link META_SCHEMA_DIR}/branding.json`.\n */\nexport const BRANDING_FILE_SCHEMA_REF = \"../meta/branding.json\";\n\nexport type MetaSchemaFile = { name: string; body: object };\n\n/**\n * The dialect files to materialize, in write order. `auth-methods.json` and\n * `auth-method.json` are pulled in by `user-schema.json`'s relative `$ref`s —\n * without them the copied dialect cannot resolve offline.\n */\nexport function metaSchemaFiles(): ReadonlyArray<MetaSchemaFile> {\n return [\n { name: \"flow-definition.json\", body: flowDefinitionMetaSchema as object },\n { name: \"user-schema.json\", body: userSchemaMetaSchema as object },\n { name: \"user-property.json\", body: userPropertyMetaSchema as object },\n { name: \"property-name.json\", body: propertyNameMetaSchema as object },\n { name: \"auth-methods.json\", body: authMethodsMetaSchema as object },\n { name: \"auth-method.json\", body: authMethodMetaSchema as object },\n { name: \"branding.json\", body: brandingMetaSchema as object },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AOkCA,MAAa,kBAAkB;;;;;AAM/B,MAAa,uBAAuB;;;;;AAMpC,MAAa,2BAA2B;;;;;;AASxC,SAAgB,kBAAiD;AAC/D,QAAO;EACL;GAAE,MAAM;GAAwB,MAAMA;GAAoC;EAC1E;GAAE,MAAM;GAAoB,MAAMC;GAAgC;EAClE;GAAE,MAAM;GAAsB,MAAMC;GAAkC;EACtE;GAAE,MAAM;GAAsB,MAAMC;GAAkC;EACtE;GAAE,MAAM;GAAqB,MAAMC;GAAiC;EACpE;GAAE,MAAM;GAAoB,MAAMC;GAAgC;EAClE;GAAE,MAAM;GAAiB,MAAMC;GAA8B;EAC9D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemas.mjs","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["import {\n CreateBrandingBody,\n CreateFlowDefinitionBody,\n CreateSchemaBody,\n} from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\nimport { z } from \"zod\";\n\nimport { isCanonicalLoopbackHttpUrl } from \"./branding-url.js\";\n\nexport const schemaConfigSchema = CreateSchemaBody;\nexport const flowConfigSchema = CreateFlowDefinitionBody.shape.flow_definition;\nexport const createFlowDefinitionRequestSchema = CreateFlowDefinitionBody;\n\n/** The wire shape of a branding revision (`POST /branding` request body). */\nexport const brandingWireSchema = CreateBrandingBody;\n\n/**\n * The local `.zitadel/branding/*.json` dialect: the wire shape plus\n * `liquid_template_file`, a descriptor-relative path the CLI inlines into\n * `liquid_template` when publishing. Exactly one of the two template carriers\n * may be present (the meta-schema `branding.json` mirrors this).\n */\nexport const brandingConfigSchema = z\n .strictObject({\n // Strict, unlike the generated wire schema: a typo like `hero_urll`\n // must fail plan, not silently pass, get ignored by the server, and\n // vanish on canonical write-back. The editor meta-schema already\n // rejects unknown keys; the CLI gate has to agree.\n ...CreateBrandingBody.shape,\n // Raw strings instead of the generated uri fields: those trim and\n // normalize before refinement runs, hiding exactly the forms the wire\n // body still carries verbatim and Go's url.Parse rejects.\n logo_url: z.string().optional(),\n hero_url: z.string().optional(),\n $schema: z.string().optional(),\n liquid_template_file: z.string().min(1).optional(),\n })\n .superRefine((value, ctx) => {\n if (value.liquid_template !== undefined && value.liquid_template_file !== undefined) {\n ctx.addIssue({\n code: \"custom\",\n message: \"Use either liquid_template_file or an inline liquid_template, not both.\",\n });\n }\n // font_url is read-only in v1: the login component loads it as a\n // document-level stylesheet (shadow-scoped @font-face never registers\n // faces), which would give branding.write arbitrary CSS over the embedding\n // page. The server rejects it too; safe delivery is an ADR 040 follow-up.\n if (value.font_url !== undefined) {\n ctx.addIssue({\n code: \"custom\",\n message:\n \"font_url is not writable yet (tenant font delivery needs a safe design, see ADR 040); load fonts from the embedding page instead.\",\n });\n }\n // Mirror the server's asset URL gate (validateBrandingAssetURL in\n // internal/domain/branding_validator.go) so plan rejects what apply would.\n // Apply mutates schemas and flows before branding, so a late 400 here would\n // leave a half-applied run.\n validateBrandingAssetUrl(value.logo_url, \"logo_url\", ctx);\n validateBrandingAssetUrl(value.hero_url, \"hero_url\", ctx);\n });\n\nfunction validateBrandingAssetUrl(\n value: string | undefined,\n field: \"logo_url\" | \"hero_url\",\n ctx: z.RefinementCtx,\n): void {\n if (value === undefined || value === \"\") {\n return;\n }\n // Stricter-or-equal than the Go gate (validateBrandingAssetURL): the WHATWG\n // parser forgives what Go's url.Parse rejects — `https:example.com`,\n // backslashes, and whitespace all get silently normalized. plan must never\n // accept what apply would reject (the reverse is harmless), so reject the\n // raw forms before parsing.\n if (/[\\s\\\\]/.test(value)) {\n ctx.addIssue({ code: \"custom\", message: `${field} is not a valid URL.` });\n return;\n }\n if (!/^https?:\\/\\//i.test(value)) {\n ctx.addIssue({ code: \"custom\", message: `${field} must be an absolute https URL.` });\n return;\n }\n let parsed: URL;\n try {\n parsed = new URL(value);\n } catch {\n ctx.addIssue({ code: \"custom\", message: `${field} is not a valid URL.` });\n return;\n }\n // Loopback HTTP is the dev-posture carve-out (assets served from the app's\n // own dev server). Check the raw URL so WHATWG normalisation cannot make\n // plan accept a host spelling that the Go save gate rejects.\n if (parsed.protocol === \"http:\" && isCanonicalLoopbackHttpUrl(value)) {\n return;\n }\n if (parsed.protocol !== \"https:\" || parsed.host === \"\") {\n ctx.addIssue({\n code: \"custom\",\n message: `${field} must be an absolute https URL (http is allowed for canonical loopback development hosts only).`,\n });\n }\n}\n"],"mappings":";;;;AASA,MAAa,qBAAqB;AAClC,MAAa,mBAAmB,yBAAyB,MAAM;AAC/D,MAAa,oCAAoC;;AAGjD,MAAa,qBAAqB;;;;;;;AAQlC,MAAa,uBAAuB,EACjC,aAAa;CAKZ,GAAG,mBAAmB;CAItB,UAAU,EAAE,QAAQ,CAAC,UAAU;CAC/B,UAAU,EAAE,QAAQ,CAAC,UAAU;CAC/B,SAAS,EAAE,QAAQ,CAAC,UAAU;CAC9B,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;CACnD,CAAC,CACD,aAAa,OAAO,QAAQ;AAC3B,KAAI,MAAM,oBAAoB,KAAA,KAAa,MAAM,yBAAyB,KAAA,EACxE,KAAI,SAAS;EACX,MAAM;EACN,SAAS;EACV,CAAC;AAMJ,KAAI,MAAM,aAAa,KAAA,EACrB,KAAI,SAAS;EACX,MAAM;EACN,SACE;EACH,CAAC;AAMJ,0BAAyB,MAAM,UAAU,YAAY,IAAI;AACzD,0BAAyB,MAAM,UAAU,YAAY,IAAI;EACzD;AAEJ,SAAS,yBACP,OACA,OACA,KACM;AACN,KAAI,UAAU,KAAA,KAAa,UAAU,GACnC;AAOF,KAAI,SAAS,KAAK,MAAM,EAAE;AACxB,MAAI,SAAS;GAAE,MAAM;GAAU,SAAS,GAAG,MAAM;GAAuB,CAAC;AACzE;;AAEF,KAAI,CAAC,gBAAgB,KAAK,MAAM,EAAE;AAChC,MAAI,SAAS;GAAE,MAAM;GAAU,SAAS,GAAG,MAAM;GAAkC,CAAC;AACpF;;CAEF,IAAI;AACJ,KAAI;AACF,WAAS,IAAI,IAAI,MAAM;SACjB;AACN,MAAI,SAAS;GAAE,MAAM;GAAU,SAAS,GAAG,MAAM;GAAuB,CAAC;AACzE;;AAKF,KAAI,OAAO,aAAa,WAAW,2BAA2B,MAAM,CAClE;AAEF,KAAI,OAAO,aAAa,YAAY,OAAO,SAAS,GAClD,KAAI,SAAS;EACX,MAAM;EACN,SAAS,GAAG,MAAM;EACnB,CAAC"}