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

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 (62) hide show
  1. package/defaults/README-branding.md +26 -34
  2. package/defaults/branding/centered/login.liquid +31 -11
  3. package/defaults/branding/minimal/login.liquid +30 -10
  4. package/dist/branding-contrast.d.mts +28 -21
  5. package/dist/branding-contrast.d.mts.map +1 -1
  6. package/dist/branding-contrast.mjs +1 -1
  7. package/dist/branding-contrast.mjs.map +1 -1
  8. package/dist/branding-url.d.mts +1 -2
  9. package/dist/branding-url.d.mts.map +1 -1
  10. package/dist/branding-url.mjs.map +1 -1
  11. package/dist/css-color.d.mts +5 -10
  12. package/dist/css-color.d.mts.map +1 -1
  13. package/dist/css-color.mjs +1 -1
  14. package/dist/css-color.mjs.map +1 -1
  15. package/dist/{defaults-BxGCGdqS.d.mts → defaults-BtKIcWxW.d.mts} +21 -14
  16. package/dist/defaults-BtKIcWxW.d.mts.map +1 -0
  17. package/dist/{defaults-DV6hY2KT.mjs → defaults-COLBFU3S.mjs} +17 -18
  18. package/dist/defaults-COLBFU3S.mjs.map +1 -0
  19. package/dist/defaults.d.mts +1 -1
  20. package/dist/defaults.mjs +1 -1
  21. package/dist/idp/index.d.mts +2 -0
  22. package/dist/idp/index.mjs +2 -0
  23. package/dist/idp-ByzXQN85.mjs +207 -0
  24. package/dist/idp-ByzXQN85.mjs.map +1 -0
  25. package/dist/idp-connection-CHxGm1Wr.mjs +324 -0
  26. package/dist/idp-connection-CHxGm1Wr.mjs.map +1 -0
  27. package/dist/index-Cuxu-zQD.d.mts +210 -0
  28. package/dist/index-Cuxu-zQD.d.mts.map +1 -0
  29. package/dist/index.d.mts +4 -3
  30. package/dist/index.mjs +5 -4
  31. package/dist/{meta-schemas-OowgSUfU.mjs → meta-schemas-C03zgFux.mjs} +36 -333
  32. package/dist/meta-schemas-C03zgFux.mjs.map +1 -0
  33. package/dist/meta-schemas.d.mts +5 -6
  34. package/dist/meta-schemas.d.mts.map +1 -1
  35. package/dist/meta-schemas.mjs +1 -1
  36. package/dist/normalize.d.mts +3 -4
  37. package/dist/normalize.d.mts.map +1 -1
  38. package/dist/normalize.mjs.map +1 -1
  39. package/dist/{schemas-7oNU25Qz.mjs → schemas-CUU4Rf8J.mjs} +11 -4
  40. package/dist/schemas-CUU4Rf8J.mjs.map +1 -0
  41. package/dist/schemas.d.mts +361 -9
  42. package/dist/schemas.d.mts.map +1 -1
  43. package/dist/schemas.mjs +2 -2
  44. package/dist/template.d.mts +9 -10
  45. package/dist/template.d.mts.map +1 -1
  46. package/dist/template.mjs +1 -1
  47. package/dist/template.mjs.map +1 -1
  48. package/dist/validate.d.mts +15 -13
  49. package/dist/validate.d.mts.map +1 -1
  50. package/dist/validate.mjs +28 -18
  51. package/dist/validate.mjs.map +1 -1
  52. package/meta-schemas/branding.json +5 -5
  53. package/meta-schemas/flow-definition.json +81 -6
  54. package/meta-schemas/idp-connection.json +6 -6
  55. package/package.json +18 -8
  56. package/defaults/branding/hero/login.liquid +0 -238
  57. package/defaults/branding/split/login.liquid +0 -197
  58. package/defaults/branding/split-right/login.liquid +0 -197
  59. package/dist/defaults-BxGCGdqS.d.mts.map +0 -1
  60. package/dist/defaults-DV6hY2KT.mjs.map +0 -1
  61. package/dist/meta-schemas-OowgSUfU.mjs.map +0 -1
  62. package/dist/schemas-7oNU25Qz.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"defaults-DV6hY2KT.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 /** A `$file` reference to the sibling template; the CLI inlines it before publishing. */\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 +0,0 @@
1
- {"version":3,"file":"meta-schemas-OowgSUfU.mjs","names":["flowDefinitionMetaSchema","userSchemaMetaSchema","userPropertyMetaSchema","propertyNameMetaSchema","authMethodsMetaSchema","authMethodMetaSchema","ssoAuthMethodMetaSchema","idpConnectionMetaSchema","brandingMetaSchema"],"sources":["../meta-schemas/auth-method.json","../meta-schemas/auth-methods.json","../meta-schemas/branding.json","../meta-schemas/flow-definition.json","../meta-schemas/idp-connection.json","../meta-schemas/property-name.json","../meta-schemas/sso-auth-method.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 generated: `scripts/sync-meta-schemas.mjs`\n * copies them from `api/openapi/endpoints/schemas/*.json` (the files the\n * server embeds) ahead of build, typecheck and test. Those are generated in\n * turn from the OpenAPI YAML by `scripts/generate-meta-schemas.ts` at the repo\n * root, so the YAML is the only thing to edit.\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 idpConnectionMetaSchema from \"../meta-schemas/idp-connection.json\" with {\n type: \"json\",\n};\nimport propertyNameMetaSchema from \"../meta-schemas/property-name.json\" with {\n type: \"json\",\n};\nimport ssoAuthMethodMetaSchema from \"../meta-schemas/sso-auth-method.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`,\n * `auth-method.json`, and `sso-auth-method.json` are pulled in by\n * `user-schema.json`'s relative `$ref`s — without them the copied dialect\n * 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: \"sso-auth-method.json\", body: ssoAuthMethodMetaSchema as object },\n { name: \"idp-connection.json\", body: idpConnectionMetaSchema as object },\n { name: \"branding.json\", body: brandingMetaSchema as object },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AS0CA,MAAa,kBAAkB;;;;;AAM/B,MAAa,uBAAuB;;;;;AAMpC,MAAa,2BAA2B;;;;;;;AAUxC,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;GAAwB,MAAMC;GAAmC;EACzE;GAAE,MAAM;GAAuB,MAAMC;GAAmC;EACxE;GAAE,MAAM;GAAiB,MAAMC;GAA8B;EAC9D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemas-7oNU25Qz.mjs","names":[],"sources":["../src/branding-css.ts","../src/schemas.ts"],"sourcesContent":["/**\n * Mirror of the server's appearance-value gates\n * (`internal/domain/branding_css.go`), so `plan` rejects what `apply` would.\n *\n * The widget writes these values straight into a CSS declaration, so a value\n * able to close its own declaration can emit rules of its own. Both gates are\n * allowlists: a value is accepted only when it matches a form we recognise,\n * never merely because it avoided the characters someone thought to ban.\n */\n\nexport const MAX_BRANDING_COLOR_LENGTH = 128;\nexport const MAX_BRANDING_FONT_FAMILY_LENGTH = 256;\n/** Asset URL cap in UTF-8 bytes, like the server's `MaxBrandingURLBytes`. */\nexport const MAX_BRANDING_URL_BYTES = 2048;\n\nconst HEX_COLOR = /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\n\n/** `url` is absent by construction: it is not a colour function. */\nconst COLOR_FUNCTIONS = new Set([\n \"rgb\",\n \"rgba\",\n \"hsl\",\n \"hsla\",\n \"hwb\",\n \"lab\",\n \"lch\",\n \"oklab\",\n \"oklch\",\n \"color\",\n \"color-mix\",\n]);\n\nconst COLOR_ARGS = /^[0-9a-zA-Z%.,+\\-/ ()#]*$/;\n/**\n * A bare colour name. Which names CSS knows is the browser's business: an\n * unknown one paints nothing, and every name of this shape is inert inside a\n * declaration whatever it spells.\n */\nconst COLOR_NAME = /^[a-zA-Z]{3,24}$/;\nconst FONT_IDENT = /^[A-Za-z0-9_-]+( [A-Za-z0-9_-]+)*$/;\n\nfunction isColorFunction(value: string): boolean {\n const open = value.indexOf(\"(\");\n if (open <= 0 || !value.endsWith(\")\")) return false;\n if (!COLOR_FUNCTIONS.has(value.slice(0, open))) return false;\n\n const args = value.slice(open + 1, -1);\n if (!COLOR_ARGS.test(args)) return false;\n\n // Nesting is legal (`color-mix(in srgb, rgb(1 2 3), red)`), so the\n // parentheses only have to balance, at a bounded depth.\n let depth = 0;\n for (const char of args) {\n if (char === \"(\") {\n depth += 1;\n if (depth > 4) return false;\n } else if (char === \")\") {\n depth -= 1;\n if (depth < 0) return false;\n }\n }\n return depth === 0;\n}\n\n/** Whether a value is hex, a CSS colour name, or a colour function. */\nexport function isBrandingColor(value: string): boolean {\n if (value.length > MAX_BRANDING_COLOR_LENGTH) return false;\n if (value.trim() === \"\") return false;\n // Not trimmed: the value is stored and painted verbatim.\n if (HEX_COLOR.test(value)) return true;\n return COLOR_NAME.test(value) || isColorFunction(value.toLowerCase());\n}\n\n/** Whether a value is a CSS font stack of identifiers and quoted names. */\nexport function isBrandingFontFamily(value: string): boolean {\n if (value.length > MAX_BRANDING_FONT_FAMILY_LENGTH) return false;\n if (value.trim() === \"\") return false;\n return value.split(\",\").every((family) => isFontName(trimSpaces(family)));\n}\n\n/** Spaces around a comma are ordinary; other whitespace is not a separator. */\nfunction trimSpaces(value: string): string {\n return value.replace(/^ +/, \"\").replace(/ +$/, \"\");\n}\n\nfunction isFontName(family: string): boolean {\n if (family === \"\") return false;\n const quote = family[0];\n if (quote === '\"' || quote === \"'\") {\n // A quoted name ends at its matching quote and holds no other, so it\n // cannot leave the string it opened.\n if (family.length < 2 || family.at(-1) !== quote) return false;\n const inner = family.slice(1, -1);\n return !inner.includes(quote) && !/[\\\\;{}]/.test(inner);\n }\n return FONT_IDENT.test(family);\n}\n","import {\n CreateBrandingBody,\n CreateFlowDefinitionBody,\n CreateSchemaBody,\n} from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\nimport { z } from \"zod\";\n\nimport {\n isBrandingColor,\n isBrandingFontFamily,\n MAX_BRANDING_URL_BYTES,\n} from \"./branding-css.js\";\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 * `{ \"$file\": \"<path>\" }`, which a `.zitadel/` file may hold in place of a\n * string field the OpenAPI YAML marks `x-local: file`. The path is relative to\n * the file holding it; the CLI inlines the content before publishing.\n */\nexport const localFileReferenceSchema = z.strictObject({ $file: z.string().min(1) });\n\n/**\n * The local `.zitadel/branding/*.json` dialect: the wire shape, where\n * `liquid_template` may also be a `$file` reference to the sibling `.liquid`\n * template (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: z\n .union([CreateBrandingBody.shape.liquid_template.unwrap(), localFileReferenceSchema])\n .optional(),\n })\n .superRefine((value, ctx) => {\n // A stylesheet alone names no face to render in, so the server rejects the\n // pair as a pair (validateBrandingFontURL in\n // internal/domain/branding_validator.go). plan has to agree, or apply\n // fails after schemas and flows have already been written.\n validateBrandingAssetUrl(value.typography?.font_url, \"typography.font_url\", ctx, {\n loopback: false,\n });\n if (value.typography?.font_url !== undefined && value.typography.font_family === undefined) {\n ctx.addIssue({\n code: \"custom\",\n message:\n \"typography.font_url needs a typography.font_family to load; a stylesheet alone names no face to render in.\",\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 validateBrandingAssetUrl(value.theme?.light?.logo_url, \"theme.light.logo_url\", ctx);\n validateBrandingAssetUrl(value.theme?.dark?.logo_url, \"theme.dark.logo_url\", ctx);\n // The appearance values land in a CSS declaration, so the server stores\n // only forms it recognises (ValidateBrandingColor / ValidateBrandingFontFamily\n // in internal/domain/branding_css.go).\n validateBrandingPalette(value.theme?.light?.palette, \"theme.light\", ctx);\n validateBrandingPalette(value.theme?.dark?.palette, \"theme.dark\", ctx);\n if (value.typography?.font_family !== undefined && !isBrandingFontFamily(value.typography.font_family)) {\n ctx.addIssue({\n code: \"custom\",\n message:\n 'typography.font_family must be comma-separated font names, each an identifier (Inter, ui-sans-serif) or a quoted name (\"APK Futural\").',\n });\n }\n });\n\nfunction validateBrandingPalette(\n palette: Record<string, unknown> | undefined,\n side: string,\n ctx: z.RefinementCtx,\n): void {\n if (!palette) {\n return;\n }\n for (const [key, colour] of Object.entries(palette)) {\n // A non-string never reaches here: the generated object schema types every\n // palette value as a string, and Zod skips refinements once the base parse\n // has failed. The check is what narrows `unknown` for the call below.\n if (typeof colour !== \"string\") {\n continue;\n }\n if (isBrandingColor(colour)) {\n continue;\n }\n ctx.addIssue({\n code: \"custom\",\n message: `${side}.palette.${key} must be hex (#4F46E5), a CSS colour name, or a colour function such as rgb(), hsl() or oklch().`,\n });\n }\n}\n\nfunction validateBrandingAssetUrl(\n value: string | undefined,\n field: string,\n ctx: z.RefinementCtx,\n options: { loopback?: boolean } = {},\n): void {\n if (value === undefined || value === \"\") {\n return;\n }\n // The server counts bytes (validateBrandingAssetURL), so a URL with\n // non-ASCII characters can be short in characters and still too long.\n if (new TextEncoder().encode(value).length > MAX_BRANDING_URL_BYTES) {\n ctx.addIssue({\n code: \"custom\",\n message: `${field} must be at most ${MAX_BRANDING_URL_BYTES} bytes.`,\n });\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 // Fetched by every visitor's browser, so userinfo in it is a credential in\n // every access log — the server refuses it and so must plan.\n if (parsed.username !== \"\" || parsed.password !== \"\") {\n ctx.addIssue({\n code: \"custom\",\n message: `${field} must not carry credentials; the URL is fetched by every visitor's browser.`,\n });\n return;\n }\n // Loopback HTTP is the dev-posture carve-out (assets served from the app's\n // own dev server), and it covers images only: a stylesheet is styling rather\n // than an image, so it stays https everywhere. Check the raw URL so WHATWG\n // normalisation cannot make plan accept a host spelling that the Go save\n // gate rejects.\n if (options.loopback !== false && 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":"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"}