@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,5 +1,4 @@
1
1
  import { CreateFlowDefinitionBodyFlowDefinition, CreateSchemaBody } from "@zitadel/api/generated/model";
2
-
3
2
  //#region src/readmes.d.ts
4
3
  /**
5
4
  * README content the CLI copies to `.zitadel/schemas/README.md` during setup.
@@ -37,28 +36,34 @@ declare const SETUP_PRESETS: readonly ["password-first", "passkey-first"];
37
36
  type SetupPreset = (typeof SETUP_PRESETS)[number];
38
37
  declare const DEFAULT_SETUP_PRESET: SetupPreset;
39
38
  /**
40
- * Login-design starting points `zitadel branding eject --design <name>` (and
41
- * `zitadel setup --design <name>`) scaffold into `.zitadel/branding/`. A
42
- * design is a full Liquid template plus the descriptor `layout` it degrades
43
- * to — the wire `layout` enum stays `centered | split`, richer designs are
44
- * delivered as templates (ADR 040).
39
+ * Widget-template starting points `zitadel branding eject --design <name>`
40
+ * scaffolds into `.zitadel/branding/` (setup never does, #1039). Only
41
+ * widget structure belongs here: `centered` is the bundled default card and
42
+ * `minimal` the same form without card chrome. Page layouts (the former
43
+ * `split`, `split-right`, `hero`) were page chrome and live in the embedding
44
+ * application instead; revisions already published from them keep rendering
45
+ * (see docs/design/branding/customization-strategy.md). Add a design here
46
+ * only when it changes the widget's structure, not the page around it.
45
47
  */
46
- declare const BRANDING_DESIGNS: readonly ["centered", "split", "split-right", "hero", "minimal"];
48
+ declare const BRANDING_DESIGNS: readonly ["centered", "minimal"];
47
49
  type BrandingDesign = (typeof BRANDING_DESIGNS)[number];
48
50
  declare const DEFAULT_BRANDING_DESIGN: BrandingDesign;
49
51
  type DefaultBrandingConfig = {
50
- /** The `.zitadel/branding/branding.json` descriptor body (sans `$schema`). */branding: {
51
- layout: "centered" | "split"; /** A `$file` reference to the sibling template; the CLI inlines it before publishing. */
52
+ /** The `.zitadel/branding/branding.json` descriptor body (sans `$schema`). */
53
+ branding: {
54
+ layout: "centered";
55
+ /** A `$file` reference to the sibling template; the CLI inlines it before publishing. */
52
56
  liquid_template: {
53
57
  $file: string;
54
58
  };
55
- }; /** The `.zitadel/branding/login.liquid` template content. */
59
+ };
60
+ /** The `.zitadel/branding/login.liquid` template content. */
56
61
  template: string;
57
62
  };
58
63
  /**
59
64
  * Renders the scaffold files for a branding design. The `centered` template
60
65
  * is a drift-tested copy of the bundled default in `@zitadel/components`;
61
- * the other designs are authored variants of it.
66
+ * `minimal` is an authored variant of it.
62
67
  */
63
68
  declare function getDefaultBrandingConfig(design?: string): DefaultBrandingConfig;
64
69
  /**
@@ -74,8 +79,10 @@ type SetupUseCase = (typeof SETUP_USE_CASES)[number];
74
79
  declare const DEFAULT_SETUP_USE_CASE: SetupUseCase;
75
80
  type DefaultConfigRenderOptions = {
76
81
  builtinSchemaBase?: string;
77
- userSchemaUrl?: string; /** Which flow/auth bundle to render; defaults to {@link DEFAULT_SETUP_PRESET}. */
78
- preset?: string; /** Which field set to collect; defaults to {@link DEFAULT_SETUP_USE_CASE}. */
82
+ userSchemaUrl?: string;
83
+ /** Which flow/auth bundle to render; defaults to {@link DEFAULT_SETUP_PRESET}. */
84
+ preset?: string;
85
+ /** Which field set to collect; defaults to {@link DEFAULT_SETUP_USE_CASE}. */
79
86
  useCase?: string;
80
87
  };
81
88
  declare function defaultHumanUserSchemaUrl(builtinSchemaBase?: string): string;
@@ -83,4 +90,4 @@ declare function getDefaultHumanUserSchema(options?: DefaultConfigRenderOptions)
83
90
  declare function getDefaultLoginFlow(options?: DefaultConfigRenderOptions): CreateFlowDefinitionBodyFlowDefinition;
84
91
  //#endregion
85
92
  export { flowsReadmeContent as C, brandingReadmeContent as S, SetupUseCase as _, DEFAULT_BRANDING_TEMPLATE_PATH as a, getDefaultHumanUserSchema as b, DEFAULT_FLOW_SCHEMA_URI as c, DEFAULT_SETUP_USE_CASE as d, DefaultBrandingConfig as f, SetupPreset as g, SETUP_USE_CASES as h, DEFAULT_BRANDING_DESIGN as i, DEFAULT_SCHEMA_CONFIG_PATH as l, SETUP_PRESETS as m, BrandingDesign as n, DEFAULT_BUILTIN_SCHEMA_BASE as o, DefaultConfigRenderOptions as p, DEFAULT_BRANDING_CONFIG_PATH as r, DEFAULT_FLOW_CONFIG_PATH as s, BRANDING_DESIGNS as t, DEFAULT_SETUP_PRESET as u, defaultHumanUserSchemaUrl as v, schemasReadmeContent as w, getDefaultLoginFlow as x, getDefaultBrandingConfig as y };
86
- //# sourceMappingURL=defaults-BxGCGdqS.d.mts.map
93
+ //# sourceMappingURL=defaults-BtKIcWxW.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults-BtKIcWxW.d.mts","names":[],"sources":["../src/readmes.ts","../src/defaults.ts"],"mappings":";;;;;;;iBAQgB;;;;;iBAQA;;;;;;iBASA;;;cCJH;cACA;cACA;cACA;cACA;cACA;;;;;;;;cASA;KAED,sBAAsB;cAErB,sBAAsB;;;;;;;;;;;cAmCtB;KAED,yBAAyB;cAExB,yBAAyB;KAa1B;;EAEV;IACE;;IAEA;MAAmB;;;;EAGrB;;;;;;;iBAQc,yBACd,kBACC;;;;;;;;;cAmCU;KAED,uBAAuB;cAEtB,wBAAwB;KA0GzB;EACV;EACA;;EAEA;;EAEA;;iBAGc,0BAA0B;iBAI1B,0BACd,UAAS,6BACR;iBAca,oBACd,UAAS,6BACR"}
@@ -348,32 +348,31 @@ function presetTemplates(preset) {
348
348
  return PRESET_TEMPLATES[preset];
349
349
  }
350
350
  /**
351
- * Login-design starting points `zitadel branding eject --design <name>` (and
352
- * `zitadel setup --design <name>`) scaffold into `.zitadel/branding/`. A
353
- * design is a full Liquid template plus the descriptor `layout` it degrades
354
- * to — the wire `layout` enum stays `centered | split`, richer designs are
355
- * delivered as templates (ADR 040).
351
+ * Widget-template starting points `zitadel branding eject --design <name>`
352
+ * scaffolds into `.zitadel/branding/` (setup never does, #1039). Only
353
+ * widget structure belongs here: `centered` is the bundled default card and
354
+ * `minimal` the same form without card chrome. Page layouts (the former
355
+ * `split`, `split-right`, `hero`) were page chrome and live in the embedding
356
+ * application instead; revisions already published from them keep rendering
357
+ * (see docs/design/branding/customization-strategy.md). Add a design here
358
+ * only when it changes the widget's structure, not the page around it.
356
359
  */
357
- const BRANDING_DESIGNS = [
358
- "centered",
359
- "split",
360
- "split-right",
361
- "hero",
362
- "minimal"
363
- ];
360
+ const BRANDING_DESIGNS = ["centered", "minimal"];
364
361
  const DEFAULT_BRANDING_DESIGN = "centered";
365
- /** Descriptor `layout` each design degrades to when its template is rejected. */
362
+ /**
363
+ * Descriptor `layout` each design's `branding.json` carries. Both shipped
364
+ * designs are widget structure and carry `centered`; the wire enum still has
365
+ * `split` for revisions published from the retired page-layout designs
366
+ * (#1039), which no catalog entry produces any more.
367
+ */
366
368
  const DESIGN_LAYOUTS = {
367
369
  centered: "centered",
368
- split: "split",
369
- "split-right": "split",
370
- hero: "split",
371
370
  minimal: "centered"
372
371
  };
373
372
  /**
374
373
  * Renders the scaffold files for a branding design. The `centered` template
375
374
  * is a drift-tested copy of the bundled default in `@zitadel/components`;
376
- * the other designs are authored variants of it.
375
+ * `minimal` is an authored variant of it.
377
376
  */
378
377
  function getDefaultBrandingConfig(design = DEFAULT_BRANDING_DESIGN) {
379
378
  if (!Object.hasOwn(DESIGN_LAYOUTS, design)) throw new Error(`unknown branding design ${JSON.stringify(design)} (known designs: ${BRANDING_DESIGNS.join(", ")})`);
@@ -540,4 +539,4 @@ function trimTrailingSlash(value) {
540
539
  //#endregion
541
540
  export { brandingReadmeContent as _, DEFAULT_BUILTIN_SCHEMA_BASE as a, DEFAULT_SCHEMA_CONFIG_PATH as c, SETUP_PRESETS as d, SETUP_USE_CASES as f, getDefaultLoginFlow as g, getDefaultHumanUserSchema as h, DEFAULT_BRANDING_TEMPLATE_PATH as i, DEFAULT_SETUP_PRESET as l, getDefaultBrandingConfig as m, DEFAULT_BRANDING_CONFIG_PATH as n, DEFAULT_FLOW_CONFIG_PATH as o, defaultHumanUserSchemaUrl as p, DEFAULT_BRANDING_DESIGN as r, DEFAULT_FLOW_SCHEMA_URI as s, BRANDING_DESIGNS as t, DEFAULT_SETUP_USE_CASE as u, flowsReadmeContent as v, schemasReadmeContent as y };
542
541
 
543
- //# sourceMappingURL=defaults-DV6hY2KT.mjs.map
542
+ //# sourceMappingURL=defaults-COLBFU3S.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults-COLBFU3S.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 { type: \"json\" };\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 * Widget-template starting points `zitadel branding eject --design <name>`\n * scaffolds into `.zitadel/branding/` (setup never does, #1039). Only\n * widget structure belongs here: `centered` is the bundled default card and\n * `minimal` the same form without card chrome. Page layouts (the former\n * `split`, `split-right`, `hero`) were page chrome and live in the embedding\n * application instead; revisions already published from them keep rendering\n * (see docs/design/branding/customization-strategy.md). Add a design here\n * only when it changes the widget's structure, not the page around it.\n */\nexport const BRANDING_DESIGNS = [\"centered\", \"minimal\"] as const;\n\nexport type BrandingDesign = (typeof BRANDING_DESIGNS)[number];\n\nexport const DEFAULT_BRANDING_DESIGN: BrandingDesign = \"centered\";\n\n/**\n * Descriptor `layout` each design's `branding.json` carries. Both shipped\n * designs are widget structure and carry `centered`; the wire enum still has\n * `split` for revisions published from the retired page-layout designs\n * (#1039), which no catalog entry produces any more.\n */\nconst DESIGN_LAYOUTS: Record<BrandingDesign, \"centered\"> = {\n centered: \"centered\",\n minimal: \"centered\",\n};\n\nexport type DefaultBrandingConfig = {\n /** The `.zitadel/branding/branding.json` descriptor body (sans `$schema`). */\n branding: {\n layout: \"centered\";\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 * `minimal` is an authored variant 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(builtinSchemaBase = DEFAULT_BUILTIN_SCHEMA_BASE): 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AIQA,SAAgB,uBAA+B;CAC7C,OAAO,aAAa,UAAU,mBAAmB,GAAG,MAAM;AAC5D;;;;;AAMA,SAAgB,qBAA6B;CAC3C,OAAO,aAAa,UAAU,iBAAiB,GAAG,MAAM;AAC1D;;;;;;AAOA,SAAgB,wBAAgC;CAC9C,OAAO,aAAa,UAAU,oBAAoB,GAAG,MAAM;AAC7D;AAEA,SAAS,UAAU,UAA0B;CAC3C,OAAO,cAAc,IAAI,IAAI,eAAe,YAAY,YAAY,GAAG,CAAC;AAC1E;;;ACVA,MAAa,8BAA8B;AAC3C,MAAa,0BAA0B;AACvC,MAAa,6BAA6B;AAC1C,MAAa,2BAA2B;AACxC,MAAa,+BAA+B;AAC5C,MAAa,iCAAiC;;;;;;;;AAS9C,MAAa,gBAAgB,CAAC,kBAAkB,eAAe;AAI/D,MAAa,uBAAoC;AAEjD,MAAM,mBAA4E;CAChF,kBAAkB;EAChB,QAAQA;EACR,MAAMC;CACR;CACA,iBAAiB;EACf,QAAQC;EACR,MAAMC;CACR;AACF;AAEA,SAAS,gBAAgB,QAAoD;CAI3E,IAAI,CAAC,OAAO,OAAO,kBAAkB,MAAM,GACzC,MAAM,IAAI,MACR,wBAAwB,KAAK,UAAU,MAAM,EAAE,mBAAmB,cAAc,KAAK,IAAI,EAAE,EAC7F;CAEF,OAAO,iBAAiB;AAC1B;;;;;;;;;;;AAYA,MAAa,mBAAmB,CAAC,YAAY,SAAS;AAItD,MAAa,0BAA0C;;;;;;;AAQvD,MAAM,iBAAqD;CACzD,UAAU;CACV,SAAS;AACX;;;;;;AAkBA,SAAgB,yBACd,SAAiB,yBACM;CACvB,IAAI,CAAC,OAAO,OAAO,gBAAgB,MAAM,GACvC,MAAM,IAAI,MACR,2BAA2B,KAAK,UAAU,MAAM,EAAE,mBAAmB,iBAAiB,KAAK,IAAI,EAAE,EACnG;CAEF,MAAM,QAAQ;CACd,OAAO;EACL,UAAU;GACR,QAAQ,eAAe;GACvB,iBAAiB,EAAE,OAAO,iBAAiB;EAC7C;EACA,UAAU,aAAa,gBAAgB,wBAAwB,MAAM,cAAc,GAAG,MAAM;CAC9F;AACF;;;;;;;AAQA,SAAS,gBAAgB,UAA0B;CACjD,MAAM,OAAO,cAAc,IAAI,IAAI,UAAU,YAAY,GAAG,CAAC;CAC7D,OAAO,KAAK,WAAW,OAAO,IAAI,KAAK,MAAM,CAAa,IAAI;AAChE;;;;;;;;;AAUA,MAAa,kBAAkB;CAAC;CAAW;CAAY;AAAU;AAIjE,MAAa,yBAAuC;;;;;;;;;AAUpD,MAAM,kBAA2D;CAC/D,SAAS,CAAC,OAAO;CACjB,UAAU;EAAC;EAAS;EAAa;CAAY;CAC7C,UAAU;EAAC;EAAS;EAAa;EAAc;CAAa;AAC9D;;;;;;;;;;AAWA,MAAM,qBAA8D;CAClE,WAAW;EACT,MAAM;EACN,WAAW;EACX,aAAa;CACf;CACA,YAAY;EACV,MAAM;EACN,WAAW;EACX,aAAa;CACf;CACA,aAAa;EACX,MAAM;EACN,WAAW;EACX,aAAa;CACf;AACF;AAEA,SAAS,cAAc,SAAoC;CAGzD,IAAI,CAAC,OAAO,OAAO,iBAAiB,OAAO,GACzC,MAAM,IAAI,MACR,0BAA0B,KAAK,UAAU,OAAO,EAAE,qBAAqB,gBAAgB,KAAK,IAAI,EAAE,EACpG;CAEF,OAAO,gBAAgB;AACzB;;;;;;;AAQA,SAAS,UACP,OACA,eACyB;CACzB,IAAI,OAAO,OAAO,eAAe,KAAK,GACpC,OAAO,EAAE,GAAG,cAAc,OAAO;CAEnC,IAAI,OAAO,OAAO,oBAAoB,KAAK,GACzC,OAAO,EAAE,GAAG,mBAAmB,OAAO;CAExC,OAAO;EAAE,MAAM;EAAU,aAAa,cAAc,MAAM;CAAG;AAC/D;;;;;;AAOA,SAAS,qBACP,QACA,SACyB;CACzB,MAAM,gBAAiB,OAAO,cAAc,CAAC;CAC7C,MAAM,aAAsC,CAAC;CAC7C,KAAK,MAAM,SAAS,cAAc,OAAO,GACvC,WAAW,SAAS,UAAU,OAAO,aAAa;CAEpD,OAAO;EAAE,GAAG;EAAQ,UAAU,CAAC,OAAO;EAAG;CAAW;AACtD;;;;;;AAOA,SAAS,mBACP,MACA,SACyB;CACzB,MAAM,SAAS,CAAC,GAAG,cAAc,OAAO,CAAC;CACzC,MAAM,QAAS,KAAK,MAAyC,KAAK,SAChE,KAAK,SAAS,aAAa;EAAE,GAAG;EAAM;CAAO,IAAI,IACnD;CACA,OAAO;EAAE,GAAG;EAAM;CAAM;AAC1B;AAWA,SAAgB,0BAA0B,oBAAoB,6BAAqC;CACjG,OAAO,GAAG,kBAAkB,iBAAiB,EAAE;AACjD;AAEA,SAAgB,0BACd,UAAsC,CAAC,GACrB;CAClB,MAAM,oBAAoB,kBACxB,QAAQ,qBAAA,iCACV;CAKA,OAAO,qBAJU,eAAe,gBAAgB,QAAQ,UAAA,gBAA8B,CAAC,CAAC,QAAQ;EAC9F,YAAY;EACZ,iBAAiB,QAAQ,iBAAiB,0BAA0B,iBAAiB;CACvF,CAES,GACP,QAAQ,WAAA,SACV;AACF;AAEA,SAAgB,oBACd,UAAsC,CAAC,GACC;CACxC,MAAM,oBAAoB,kBACxB,QAAQ,qBAAA,iCACV;CAKA,OAAO,mBAJU,eAAe,gBAAgB,QAAQ,UAAA,gBAA8B,CAAC,CAAC,MAAM;EAC5F,YAAY;EACZ,iBAAiB,QAAQ,iBAAiB,0BAA0B,iBAAiB;CACvF,CAES,GACP,QAAQ,WAAA,SACV;AACF;AAEA,SAAS,eAAe,OAAgB,cAA+C;CACrF,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,KAAK,SAAS,eAAe,MAAM,YAAY,CAAC;CAE/D,IAAI,UAAU,QAAQ,OAAO,UAAU,UACrC,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,eAAe,MAAM,YAAY,CAAC,CAAC,CACtF;CAEF,IAAI,OAAO,UAAU,UACnB,OAAO,MAAM,WAAW,qBAAqB,OAAO,SAAiB;EACnE,OAAO,aAAa,SAAS;CAC/B,CAAC;CAEH,OAAO;AACT;AAEA,SAAS,kBAAkB,OAAuB;CAChD,IAAI,UAAU;CACd,OAAO,QAAQ,SAAS,GAAG,GACzB,UAAU,QAAQ,MAAM,GAAG,EAAE;CAE/B,OAAO;AACT"}
@@ -1,2 +1,2 @@
1
- import { C as flowsReadmeContent, S as brandingReadmeContent, _ as SetupUseCase, a as DEFAULT_BRANDING_TEMPLATE_PATH, b as getDefaultHumanUserSchema, c as DEFAULT_FLOW_SCHEMA_URI, d as DEFAULT_SETUP_USE_CASE, f as DefaultBrandingConfig, g as SetupPreset, h as SETUP_USE_CASES, i as DEFAULT_BRANDING_DESIGN, l as DEFAULT_SCHEMA_CONFIG_PATH, m as SETUP_PRESETS, n as BrandingDesign, o as DEFAULT_BUILTIN_SCHEMA_BASE, p as DefaultConfigRenderOptions, r as DEFAULT_BRANDING_CONFIG_PATH, s as DEFAULT_FLOW_CONFIG_PATH, t as BRANDING_DESIGNS, u as DEFAULT_SETUP_PRESET, v as defaultHumanUserSchemaUrl, w as schemasReadmeContent, x as getDefaultLoginFlow, y as getDefaultBrandingConfig } from "./defaults-BxGCGdqS.mjs";
1
+ import { C as flowsReadmeContent, S as brandingReadmeContent, _ as SetupUseCase, a as DEFAULT_BRANDING_TEMPLATE_PATH, b as getDefaultHumanUserSchema, c as DEFAULT_FLOW_SCHEMA_URI, d as DEFAULT_SETUP_USE_CASE, f as DefaultBrandingConfig, g as SetupPreset, h as SETUP_USE_CASES, i as DEFAULT_BRANDING_DESIGN, l as DEFAULT_SCHEMA_CONFIG_PATH, m as SETUP_PRESETS, n as BrandingDesign, o as DEFAULT_BUILTIN_SCHEMA_BASE, p as DefaultConfigRenderOptions, r as DEFAULT_BRANDING_CONFIG_PATH, s as DEFAULT_FLOW_CONFIG_PATH, t as BRANDING_DESIGNS, u as DEFAULT_SETUP_PRESET, v as defaultHumanUserSchemaUrl, w as schemasReadmeContent, x as getDefaultLoginFlow, y as getDefaultBrandingConfig } from "./defaults-BtKIcWxW.mjs";
2
2
  export { BRANDING_DESIGNS, BrandingDesign, DEFAULT_BRANDING_CONFIG_PATH, DEFAULT_BRANDING_DESIGN, DEFAULT_BRANDING_TEMPLATE_PATH, DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, DEFAULT_SETUP_PRESET, DEFAULT_SETUP_USE_CASE, DefaultBrandingConfig, DefaultConfigRenderOptions, SETUP_PRESETS, SETUP_USE_CASES, SetupPreset, SetupUseCase, brandingReadmeContent, defaultHumanUserSchemaUrl, flowsReadmeContent, getDefaultBrandingConfig, getDefaultHumanUserSchema, getDefaultLoginFlow, schemasReadmeContent };
package/dist/defaults.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as brandingReadmeContent, a as DEFAULT_BUILTIN_SCHEMA_BASE, c as DEFAULT_SCHEMA_CONFIG_PATH, d as SETUP_PRESETS, f as SETUP_USE_CASES, g as getDefaultLoginFlow, h as getDefaultHumanUserSchema, i as DEFAULT_BRANDING_TEMPLATE_PATH, l as DEFAULT_SETUP_PRESET, m as getDefaultBrandingConfig, n as DEFAULT_BRANDING_CONFIG_PATH, o as DEFAULT_FLOW_CONFIG_PATH, p as defaultHumanUserSchemaUrl, r as DEFAULT_BRANDING_DESIGN, s as DEFAULT_FLOW_SCHEMA_URI, t as BRANDING_DESIGNS, u as DEFAULT_SETUP_USE_CASE, v as flowsReadmeContent, y as schemasReadmeContent } from "./defaults-DV6hY2KT.mjs";
1
+ import { _ as brandingReadmeContent, a as DEFAULT_BUILTIN_SCHEMA_BASE, c as DEFAULT_SCHEMA_CONFIG_PATH, d as SETUP_PRESETS, f as SETUP_USE_CASES, g as getDefaultLoginFlow, h as getDefaultHumanUserSchema, i as DEFAULT_BRANDING_TEMPLATE_PATH, l as DEFAULT_SETUP_PRESET, m as getDefaultBrandingConfig, n as DEFAULT_BRANDING_CONFIG_PATH, o as DEFAULT_FLOW_CONFIG_PATH, p as defaultHumanUserSchemaUrl, r as DEFAULT_BRANDING_DESIGN, s as DEFAULT_FLOW_SCHEMA_URI, t as BRANDING_DESIGNS, u as DEFAULT_SETUP_USE_CASE, v as flowsReadmeContent, y as schemasReadmeContent } from "./defaults-COLBFU3S.mjs";
2
2
  export { BRANDING_DESIGNS, DEFAULT_BRANDING_CONFIG_PATH, DEFAULT_BRANDING_DESIGN, DEFAULT_BRANDING_TEMPLATE_PATH, DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, DEFAULT_SETUP_PRESET, DEFAULT_SETUP_USE_CASE, SETUP_PRESETS, SETUP_USE_CASES, brandingReadmeContent, defaultHumanUserSchemaUrl, flowsReadmeContent, getDefaultBrandingConfig, getDefaultHumanUserSchema, getDefaultLoginFlow, schemasReadmeContent };
@@ -0,0 +1,2 @@
1
+ import { a as ISSUER_REQUIREMENT, c as ConnectionEndpoints, d as ScaffoldOptions, f as credentialVariable, g as variableReference, h as referencedVariable, i as OidcProvider, l as CredentialVariables, m as isVariableReference, n as idpProvider, o as isSupportedIssuer, p as credentialVariables, r as GoogleProvider, s as CallbackGuidance, t as IDP_PROVIDERS, u as IdpProvider } from "../index-Cuxu-zQD.mjs";
2
+ export { type CallbackGuidance, type ConnectionEndpoints, type CredentialVariables, GoogleProvider, IDP_PROVIDERS, ISSUER_REQUIREMENT, type IdpProvider, OidcProvider, type ScaffoldOptions, credentialVariable, credentialVariables, idpProvider, isSupportedIssuer, isVariableReference, referencedVariable, variableReference };
@@ -0,0 +1,2 @@
1
+ import { a as GoogleProvider, c as credentialVariables, d as variableReference, i as isSupportedIssuer, l as isVariableReference, n as idpProvider, o as OidcProvider, r as ISSUER_REQUIREMENT, s as credentialVariable, t as IDP_PROVIDERS, u as referencedVariable } from "../idp-ByzXQN85.mjs";
2
+ export { GoogleProvider, IDP_PROVIDERS, ISSUER_REQUIREMENT, OidcProvider, credentialVariable, credentialVariables, idpProvider, isSupportedIssuer, isVariableReference, referencedVariable, variableReference };
@@ -0,0 +1,207 @@
1
+ import { t as idp_connection_default } from "./idp-connection-CHxGm1Wr.mjs";
2
+ //#region src/idp/provider.ts
3
+ /**
4
+ * The variables a connection scaffolded under `slug` references.
5
+ *
6
+ * Derived from the slug rather than the provider: a Project may hold a second
7
+ * connection for the same provider under a slug of its own, and its
8
+ * credentials belong to that connection, not to the provider.
9
+ */
10
+ function credentialVariables(slug) {
11
+ return {
12
+ clientId: credentialVariable(slug, "CLIENT_ID"),
13
+ clientSecret: credentialVariable(slug, "CLIENT_SECRET")
14
+ };
15
+ }
16
+ /**
17
+ * A credential's variable name: the slug uppercased with every non-alphanumeric
18
+ * replaced by `_`, then the suffix. A slug may start with a digit, which no
19
+ * shell accepts as the first character of a name, so such a name gains a `_`.
20
+ */
21
+ function credentialVariable(slug, suffix) {
22
+ const name = `${slug.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_${suffix}`;
23
+ return /^[0-9]/.test(name) ? `_${name}` : name;
24
+ }
25
+ /**
26
+ * The `${{ NAME }}` reference written to a credential field, as
27
+ * `idp-connection.json` requires: a whole-value placeholder, with no text
28
+ * around it that would be rendered into the resolved credential.
29
+ */
30
+ function variableReference(name) {
31
+ return `\${{ ${name} }}`;
32
+ }
33
+ /**
34
+ * The variable a `${{ NAME }}` reference names, or `undefined` when the value
35
+ * is not one.
36
+ *
37
+ * A connection is editable, so the name it references need not be the one this
38
+ * CLI would have chosen — a hand-written file may point at `ACME_SECRET`.
39
+ * Publishing to a name derived from the slug instead would store the credential
40
+ * where nothing reads it and report success.
41
+ */
42
+ function referencedVariable(value) {
43
+ return /^\$\{\{ *(\w+) *\}\}$/.exec(value.trim())?.[1];
44
+ }
45
+ /** Whether a stored value is a reference rather than a credential. */
46
+ function isVariableReference(value) {
47
+ return referencedVariable(value) !== void 0;
48
+ }
49
+ //#endregion
50
+ //#region src/idp/oidc-provider.ts
51
+ /**
52
+ * The parts of a connection document every OIDC provider composes the same way.
53
+ *
54
+ * A subclass supplies what is genuinely its own — the vendor's identity, its
55
+ * issuer, its claim table, and any protocol settings it needs — and inherits
56
+ * the composition. Nothing here knows about a specific vendor, so a provider
57
+ * whose document is shaped differently overrides rather than adds a branch.
58
+ */
59
+ var OidcProvider = class {
60
+ /** The claim that carries the provider's stable, unique id for an account. */
61
+ subjectClaim = "sub";
62
+ /**
63
+ * Schema property name → how its value is verified: a claim to read, `true`
64
+ * for a provider trusted outright, or `"$supplementary_fetch"`.
65
+ *
66
+ * Keyed by schema property, like {@link claimTable}, so it narrows with it.
67
+ */
68
+ verifiedClaims = {};
69
+ /** Parameters the vendor wants on every authorization request. */
70
+ staticAuthorizeParameters = {};
71
+ claimMapping(schemaProperties) {
72
+ const defined = new Set(schemaProperties);
73
+ return Object.fromEntries(Object.entries(this.claimTable).filter(([property]) => defined.has(property)));
74
+ }
75
+ /**
76
+ * Compose the connection document. Pure: it returns the object the caller
77
+ * writes to `.zitadel/idps/<slug>.json`, and performs no IO.
78
+ *
79
+ * Neither credential is written into it. Both are `${{ NAME }}` references to
80
+ * project variables: the secret because the document is committed and a
81
+ * revision is immutable, so a literal could never be scrubbed; the id because
82
+ * each environment registers its own application, and a literal would force
83
+ * one connection file per environment.
84
+ *
85
+ * Endpoints are named only when the connection points somewhere other than
86
+ * the vendor, and then only the issuer. The engine accepts a connection
87
+ * naming every endpoint or none, and it needs four — so a subset is rejected,
88
+ * and a stand-in serves its own discovery document as the vendor does.
89
+ */
90
+ connection(options) {
91
+ const slug = options.slug ?? this.slug;
92
+ const claimMapping = this.claimMapping(options.schemaProperties);
93
+ const verifiedClaims = Object.fromEntries(Object.entries(this.verifiedClaims).filter(([property]) => property in claimMapping));
94
+ const issuer = options.endpoints?.issuer;
95
+ const variables = credentialVariables(slug);
96
+ return {
97
+ ...options.schemaRef ? { $schema: options.schemaRef } : {},
98
+ slug,
99
+ protocol: "oidc",
100
+ template: this.template,
101
+ display_name: this.displayName,
102
+ subject_claim: this.subjectClaim,
103
+ ...Object.keys(verifiedClaims).length > 0 ? { verified_claims: verifiedClaims } : {},
104
+ ...Object.keys(claimMapping).length > 0 ? { claim_mapping: claimMapping } : {},
105
+ provisioning: { creation: "auto" },
106
+ oidc: {
107
+ issuer: issuer !== void 0 && issuer !== "" ? issuer : this.issuer,
108
+ scopes: [...this.scopes],
109
+ ...Object.keys(this.staticAuthorizeParameters).length > 0 ? { static_authorize_parameters: { ...this.staticAuthorizeParameters } } : {},
110
+ client_id: variableReference(variables.clientId),
111
+ client_secret: variableReference(variables.clientSecret)
112
+ }
113
+ };
114
+ }
115
+ };
116
+ //#endregion
117
+ //#region src/idp/google.ts
118
+ /**
119
+ * Google, as `zitadel setup` and `sso enable` scaffold it.
120
+ *
121
+ * Everything here is Google's own documented behaviour, cross-checked against
122
+ * its discovery document and the provider packages in zitadel/zitadel. It names
123
+ * no endpoints: Google publishes a discovery document, its endpoints do not
124
+ * share the issuer's host, and the engine resolves them at runtime — so a value
125
+ * committed here would be a guess that ages.
126
+ */
127
+ var GoogleProvider = class extends OidcProvider {
128
+ slug = "google";
129
+ displayName = "Google";
130
+ template = "google";
131
+ consoleUrl = "https://console.cloud.google.com/apis/credentials";
132
+ docsUrl = "https://developers.google.com/identity/openid-connect/openid-connect";
133
+ /** One client takes many redirect URIs, so one application serves every environment. */
134
+ callbackGuidance = "multi_uri_client";
135
+ issuer = "https://accounts.google.com";
136
+ claimTable = {
137
+ email: "email",
138
+ givenName: "given_name",
139
+ familyName: "family_name"
140
+ };
141
+ scopes = [
142
+ "openid",
143
+ "profile",
144
+ "email"
145
+ ];
146
+ /** `sub` never changes, unlike an email, so identity keys on it. */
147
+ subjectClaim = "sub";
148
+ verifiedClaims = { email: "email_verified" };
149
+ /** Google reuses a signed-in session silently without it. */
150
+ staticAuthorizeParameters = { prompt: "select_account" };
151
+ };
152
+ //#endregion
153
+ //#region src/idp/issuer.ts
154
+ /**
155
+ * The issuer values a connection may name: HTTPS anywhere, or HTTP on
156
+ * `localhost`/`127.0.0.1` for a local stand-in.
157
+ *
158
+ * Read out of the generated meta-schema rather than restated here, so a prompt
159
+ * that accepts a value and the document written from it cannot disagree. That
160
+ * file is generated from the OpenAPI YAML the server embeds, which makes it
161
+ * also what the server will enforce — `http://idp.internal:9100` would be
162
+ * taken by a hand-rolled URL check and then rejected on apply.
163
+ */
164
+ function issuerPattern() {
165
+ const pattern = ((idp_connection_default.properties?.oidc)?.properties?.issuer)?.pattern;
166
+ if (typeof pattern !== "string") throw new Error("idp-connection.json no longer states properties.oidc.properties.issuer.pattern");
167
+ return new RegExp(pattern);
168
+ }
169
+ let compiled;
170
+ /** Whether a connection may name this issuer. */
171
+ function isSupportedIssuer(value) {
172
+ compiled ??= issuerPattern();
173
+ return compiled.test(value.trim());
174
+ }
175
+ /** What to tell someone who typed an issuer the contract does not allow. */
176
+ const ISSUER_REQUIREMENT = "Use an https:// URL, or http:// on localhost or 127.0.0.1.";
177
+ //#endregion
178
+ //#region src/idp/index.ts
179
+ /**
180
+ * The providers `zitadel setup` and `sso enable` can scaffold a connection for.
181
+ *
182
+ * Adding one means adding a class and listing it here. That is a code change
183
+ * rather than a data change, which is the point: a provider is not only a table
184
+ * of values, and the ones that differ — OAuth2 rather than OIDC, a second
185
+ * request to read an email, a claim the vendor does not emit — differ in
186
+ * behaviour. Holding that in the provider keeps it out of the callers.
187
+ */
188
+ const PROVIDERS = Object.freeze([new GoogleProvider()]);
189
+ const BY_SLUG = new Map(PROVIDERS.map((provider) => [provider.slug, provider]));
190
+ /** Every provider's slug, in listing order. The `--provider` flag takes one. */
191
+ const IDP_PROVIDERS = Object.freeze(PROVIDERS.map((provider) => provider.slug));
192
+ /**
193
+ * One provider by slug.
194
+ *
195
+ * Throws rather than returning `undefined`: every caller has already had the
196
+ * slug validated against {@link IDP_PROVIDERS}, so a miss here is a bug in this
197
+ * package and not something a caller can act on.
198
+ */
199
+ function idpProvider(slug) {
200
+ const provider = BY_SLUG.get(slug);
201
+ if (provider === void 0) throw new Error(`unknown identity provider ${JSON.stringify(slug)} (known providers: ${IDP_PROVIDERS.join(", ")})`);
202
+ return provider;
203
+ }
204
+ //#endregion
205
+ export { GoogleProvider as a, credentialVariables as c, variableReference as d, isSupportedIssuer as i, isVariableReference as l, idpProvider as n, OidcProvider as o, ISSUER_REQUIREMENT as r, credentialVariable as s, IDP_PROVIDERS as t, referencedVariable as u };
206
+
207
+ //# sourceMappingURL=idp-ByzXQN85.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idp-ByzXQN85.mjs","names":["idpConnectionMetaSchema"],"sources":["../src/idp/provider.ts","../src/idp/oidc-provider.ts","../src/idp/google.ts","../src/idp/issuer.ts","../src/idp/index.ts"],"sourcesContent":["/**\n * What the CLI needs to know about one identity provider to scaffold a working\n * connection for it: how to name it, where to send the developer to register an\n * application, and how to compose the connection document.\n *\n * One class per provider, because a provider is not only a table of values.\n * Google is pure data today; GitHub speaks OAuth2 rather than OIDC, has no\n * family-name claim, and needs a second request to read an email at all. A\n * shape that only holds data forces that behaviour somewhere else, where it\n * stops being the provider's business and starts being a branch in shared code.\n */\n\n/**\n * Whether the vendor accepts many redirect URIs on a single client, or needs a\n * separate application per environment. Surfaced when the developer is told\n * what to register, so they register the right thing.\n */\nexport type CallbackGuidance = \"multi_uri_client\" | \"app_per_environment\";\n\n/** Where a connection points, when not at the vendor. */\nexport type ConnectionEndpoints = {\n readonly issuer?: string;\n};\n\n/** What a connection document needs beyond the provider's own knowledge. */\nexport type ScaffoldOptions = {\n /** Properties the target user schema defines, which bounds the claim mapping. */\n readonly schemaProperties: Iterable<string>;\n /** Slug to write under; defaults to the provider's own. */\n readonly slug?: string;\n /** `$schema` pointer, relative to `.zitadel/idps/`. */\n readonly schemaRef?: string;\n /** Point the connection somewhere other than the vendor (local testing). */\n readonly endpoints?: ConnectionEndpoints;\n};\n\nexport interface IdpProvider {\n /** Default connection slug, and the name `--provider` takes. */\n readonly slug: string;\n /** Written to the connection and shown on the sign-in button. */\n readonly displayName: string;\n /**\n * Written to the connection as `template`. Keys vendor knowledge only —\n * glyphs, button branding, the setup scan — and carries no protocol\n * behaviour.\n */\n readonly template: string;\n /** Where the developer registers the application. */\n readonly consoleUrl: string;\n /** The vendor's own integration documentation. */\n readonly docsUrl: string;\n readonly callbackGuidance: CallbackGuidance;\n /** The issuer the vendor publishes, and the default when one is asked for. */\n readonly issuer: string;\n /**\n * The claims this provider emits, keyed by schema property name, narrowed to\n * the properties the target schema actually defines.\n */\n claimMapping(schemaProperties: Iterable<string>): Record<string, string>;\n /** The document `zitadel setup` writes to `.zitadel/idps/<slug>.json`. */\n connection(options: ScaffoldOptions): Record<string, unknown>;\n}\n\n/** The project variables a connection's two credentials reference. */\nexport type CredentialVariables = {\n readonly clientId: string;\n readonly clientSecret: string;\n};\n\n/**\n * The variables a connection scaffolded under `slug` references.\n *\n * Derived from the slug rather than the provider: a Project may hold a second\n * connection for the same provider under a slug of its own, and its\n * credentials belong to that connection, not to the provider.\n */\nexport function credentialVariables(slug: string): CredentialVariables {\n return {\n clientId: credentialVariable(slug, \"CLIENT_ID\"),\n clientSecret: credentialVariable(slug, \"CLIENT_SECRET\"),\n };\n}\n\n/**\n * A credential's variable name: the slug uppercased with every non-alphanumeric\n * replaced by `_`, then the suffix. A slug may start with a digit, which no\n * shell accepts as the first character of a name, so such a name gains a `_`.\n */\nexport function credentialVariable(slug: string, suffix: string): string {\n const name = `${slug.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}_${suffix}`;\n return /^[0-9]/.test(name) ? `_${name}` : name;\n}\n\n/**\n * The `${{ NAME }}` reference written to a credential field, as\n * `idp-connection.json` requires: a whole-value placeholder, with no text\n * around it that would be rendered into the resolved credential.\n */\nexport function variableReference(name: string): string {\n return `\\${{ ${name} }}`;\n}\n\n/**\n * The variable a `${{ NAME }}` reference names, or `undefined` when the value\n * is not one.\n *\n * A connection is editable, so the name it references need not be the one this\n * CLI would have chosen — a hand-written file may point at `ACME_SECRET`.\n * Publishing to a name derived from the slug instead would store the credential\n * where nothing reads it and report success.\n */\nexport function referencedVariable(value: string): string | undefined {\n return /^\\$\\{\\{ *(\\w+) *\\}\\}$/.exec(value.trim())?.[1];\n}\n\n/** Whether a stored value is a reference rather than a credential. */\nexport function isVariableReference(value: string): boolean {\n return referencedVariable(value) !== undefined;\n}\n","import {\n credentialVariables,\n variableReference,\n type CallbackGuidance,\n type IdpProvider,\n type ScaffoldOptions,\n} from \"./provider.js\";\n\n/**\n * The parts of a connection document every OIDC provider composes the same way.\n *\n * A subclass supplies what is genuinely its own — the vendor's identity, its\n * issuer, its claim table, and any protocol settings it needs — and inherits\n * the composition. Nothing here knows about a specific vendor, so a provider\n * whose document is shaped differently overrides rather than adds a branch.\n */\nexport abstract class OidcProvider implements IdpProvider {\n abstract readonly slug: string;\n abstract readonly displayName: string;\n abstract readonly template: string;\n abstract readonly consoleUrl: string;\n abstract readonly docsUrl: string;\n abstract readonly callbackGuidance: CallbackGuidance;\n abstract readonly issuer: string;\n\n /**\n * Schema property name → the claim this provider documents for it.\n *\n * Authored per provider rather than derived: each row pairs a property with\n * the vendor's documented claim name, and a wrong one fails silently — the\n * claim is never found and the property stays unmapped.\n */\n protected abstract readonly claimTable: Readonly<Record<string, string>>;\n\n /** Scopes the connection requests. */\n protected abstract readonly scopes: readonly string[];\n\n /** The claim that carries the provider's stable, unique id for an account. */\n protected readonly subjectClaim: string = \"sub\";\n\n /**\n * Schema property name → how its value is verified: a claim to read, `true`\n * for a provider trusted outright, or `\"$supplementary_fetch\"`.\n *\n * Keyed by schema property, like {@link claimTable}, so it narrows with it.\n */\n protected readonly verifiedClaims: Readonly<Record<string, string | true>> = {};\n\n /** Parameters the vendor wants on every authorization request. */\n protected readonly staticAuthorizeParameters: Readonly<Record<string, string>> = {};\n\n claimMapping(schemaProperties: Iterable<string>): Record<string, string> {\n const defined = new Set(schemaProperties);\n return Object.fromEntries(\n Object.entries(this.claimTable).filter(([property]) => defined.has(property)),\n );\n }\n\n /**\n * Compose the connection document. Pure: it returns the object the caller\n * writes to `.zitadel/idps/<slug>.json`, and performs no IO.\n *\n * Neither credential is written into it. Both are `${{ NAME }}` references to\n * project variables: the secret because the document is committed and a\n * revision is immutable, so a literal could never be scrubbed; the id because\n * each environment registers its own application, and a literal would force\n * one connection file per environment.\n *\n * Endpoints are named only when the connection points somewhere other than\n * the vendor, and then only the issuer. The engine accepts a connection\n * naming every endpoint or none, and it needs four — so a subset is rejected,\n * and a stand-in serves its own discovery document as the vendor does.\n */\n connection(options: ScaffoldOptions): Record<string, unknown> {\n const slug = options.slug ?? this.slug;\n const claimMapping = this.claimMapping(options.schemaProperties);\n // Verification is of a mapped value, so it narrows to what was mapped: a\n // schema without `email` gets no email mapping, and an `email` entry here\n // would then claim to verify a value this connection never supplies.\n const verifiedClaims = Object.fromEntries(\n Object.entries(this.verifiedClaims).filter(([property]) => property in claimMapping),\n );\n const issuer = options.endpoints?.issuer;\n const variables = credentialVariables(slug);\n return {\n ...(options.schemaRef ? { $schema: options.schemaRef } : {}),\n slug,\n protocol: \"oidc\",\n template: this.template,\n display_name: this.displayName,\n subject_claim: this.subjectClaim,\n ...(Object.keys(verifiedClaims).length > 0 ? { verified_claims: verifiedClaims } : {}),\n ...(Object.keys(claimMapping).length > 0 ? { claim_mapping: claimMapping } : {}),\n provisioning: { creation: \"auto\" },\n oidc: {\n issuer: issuer !== undefined && issuer !== \"\" ? issuer : this.issuer,\n scopes: [...this.scopes],\n ...(Object.keys(this.staticAuthorizeParameters).length > 0\n ? { static_authorize_parameters: { ...this.staticAuthorizeParameters } }\n : {}),\n client_id: variableReference(variables.clientId),\n client_secret: variableReference(variables.clientSecret),\n },\n };\n }\n}\n","import { OidcProvider } from \"./oidc-provider.js\";\nimport type { CallbackGuidance } from \"./provider.js\";\n\n/**\n * Google, as `zitadel setup` and `sso enable` scaffold it.\n *\n * Everything here is Google's own documented behaviour, cross-checked against\n * its discovery document and the provider packages in zitadel/zitadel. It names\n * no endpoints: Google publishes a discovery document, its endpoints do not\n * share the issuer's host, and the engine resolves them at runtime — so a value\n * committed here would be a guess that ages.\n */\nexport class GoogleProvider extends OidcProvider {\n readonly slug = \"google\";\n readonly displayName = \"Google\";\n readonly template = \"google\";\n readonly consoleUrl = \"https://console.cloud.google.com/apis/credentials\";\n readonly docsUrl = \"https://developers.google.com/identity/openid-connect/openid-connect\";\n /** One client takes many redirect URIs, so one application serves every environment. */\n readonly callbackGuidance: CallbackGuidance = \"multi_uri_client\";\n readonly issuer = \"https://accounts.google.com\";\n\n protected readonly claimTable = {\n email: \"email\",\n givenName: \"given_name\",\n familyName: \"family_name\",\n };\n\n protected readonly scopes = [\"openid\", \"profile\", \"email\"];\n\n /** `sub` never changes, unlike an email, so identity keys on it. */\n protected override readonly subjectClaim = \"sub\";\n\n protected override readonly verifiedClaims = { email: \"email_verified\" };\n\n /** Google reuses a signed-in session silently without it. */\n protected override readonly staticAuthorizeParameters = { prompt: \"select_account\" };\n}\n","import idpConnectionMetaSchema from \"../../meta-schemas/idp-connection.json\" with { type: \"json\" };\n\n/**\n * The issuer values a connection may name: HTTPS anywhere, or HTTP on\n * `localhost`/`127.0.0.1` for a local stand-in.\n *\n * Read out of the generated meta-schema rather than restated here, so a prompt\n * that accepts a value and the document written from it cannot disagree. That\n * file is generated from the OpenAPI YAML the server embeds, which makes it\n * also what the server will enforce — `http://idp.internal:9100` would be\n * taken by a hand-rolled URL check and then rejected on apply.\n */\nfunction issuerPattern(): RegExp {\n const oidc = (idpConnectionMetaSchema as { properties?: Record<string, unknown> }).properties\n ?.oidc;\n const issuer = (oidc as { properties?: Record<string, unknown> } | undefined)?.properties?.issuer;\n const pattern = (issuer as { pattern?: unknown } | undefined)?.pattern;\n if (typeof pattern !== \"string\") {\n // Silently accepting everything would be the worst outcome: the prompt\n // would go on reporting success for connections the server refuses.\n throw new Error(\n \"idp-connection.json no longer states properties.oidc.properties.issuer.pattern\",\n );\n }\n return new RegExp(pattern);\n}\n\nlet compiled: RegExp | undefined;\n\n/** Whether a connection may name this issuer. */\nexport function isSupportedIssuer(value: string): boolean {\n compiled ??= issuerPattern();\n return compiled.test(value.trim());\n}\n\n/** What to tell someone who typed an issuer the contract does not allow. */\nexport const ISSUER_REQUIREMENT = \"Use an https:// URL, or http:// on localhost or 127.0.0.1.\";\n","/**\n * The providers `zitadel setup` and `sso enable` can scaffold a connection for.\n *\n * Adding one means adding a class and listing it here. That is a code change\n * rather than a data change, which is the point: a provider is not only a table\n * of values, and the ones that differ — OAuth2 rather than OIDC, a second\n * request to read an email, a claim the vendor does not emit — differ in\n * behaviour. Holding that in the provider keeps it out of the callers.\n */\nimport { GoogleProvider } from \"./google.js\";\nimport type { IdpProvider } from \"./provider.js\";\n\nconst PROVIDERS: readonly IdpProvider[] = Object.freeze([new GoogleProvider()]);\n\nconst BY_SLUG: ReadonlyMap<string, IdpProvider> = new Map(\n PROVIDERS.map((provider) => [provider.slug, provider]),\n);\n\n/** Every provider's slug, in listing order. The `--provider` flag takes one. */\nexport const IDP_PROVIDERS: readonly string[] = Object.freeze(\n PROVIDERS.map((provider) => provider.slug),\n);\n\n/**\n * One provider by slug.\n *\n * Throws rather than returning `undefined`: every caller has already had the\n * slug validated against {@link IDP_PROVIDERS}, so a miss here is a bug in this\n * package and not something a caller can act on.\n */\nexport function idpProvider(slug: string): IdpProvider {\n const provider = BY_SLUG.get(slug);\n if (provider === undefined) {\n throw new Error(\n `unknown identity provider ${JSON.stringify(slug)} (known providers: ${IDP_PROVIDERS.join(\", \")})`,\n );\n }\n return provider;\n}\n\nexport { ISSUER_REQUIREMENT, isSupportedIssuer } from \"./issuer.js\";\n\nexport { GoogleProvider } from \"./google.js\";\nexport { OidcProvider } from \"./oidc-provider.js\";\nexport {\n credentialVariable,\n credentialVariables,\n isVariableReference,\n referencedVariable,\n variableReference,\n type CallbackGuidance,\n type ConnectionEndpoints,\n type CredentialVariables,\n type IdpProvider,\n type ScaffoldOptions,\n} from \"./provider.js\";\n"],"mappings":"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"}