@zitadel/cli 1.0.0-alpha.25 → 1.0.0-alpha.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +476 -178
- package/dist/index.mjs +14573 -7975
- package/dist/index.mjs.map +1 -1
- package/dist/lib/oclif/help.mjs +5 -1
- package/dist/lib/oclif/help.mjs.map +1 -1
- package/dist/skills-hint-jV01gbMZ.mjs +166 -0
- package/dist/skills-hint-jV01gbMZ.mjs.map +1 -0
- package/oclif.manifest.json +1021 -379
- package/package.json +26 -12
- package/skills/zitadel-cli/SKILL.md +189 -29
- package/skills/zitadel-cli/references/driving-login-ui.md +33 -16
- package/dist/groups-CbWm8kCm.mjs +0 -22
- package/dist/groups-CbWm8kCm.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zitadel/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.28",
|
|
4
4
|
"description": "Agent-friendly Zitadel CLI",
|
|
5
5
|
"homepage": "https://github.com/zitadel/nextgen/tree/main/apps/cli#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -72,8 +72,17 @@
|
|
|
72
72
|
"branding": {
|
|
73
73
|
"description": "Work with login branding revisions."
|
|
74
74
|
},
|
|
75
|
-
"
|
|
76
|
-
"description": "
|
|
75
|
+
"auth-method": {
|
|
76
|
+
"description": "Turn sign-in methods on or off for a user schema."
|
|
77
|
+
},
|
|
78
|
+
"auth-method:password": {
|
|
79
|
+
"description": "Turn password sign-in on or off."
|
|
80
|
+
},
|
|
81
|
+
"auth-method:passkey": {
|
|
82
|
+
"description": "Turn passkey sign-in on or off."
|
|
83
|
+
},
|
|
84
|
+
"auth-method:sso": {
|
|
85
|
+
"description": "Add or remove identity providers."
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
88
|
},
|
|
@@ -88,32 +97,34 @@
|
|
|
88
97
|
"@oclif/plugin-search": "^1.2.50",
|
|
89
98
|
"@oclif/plugin-version": "^2.2.46",
|
|
90
99
|
"@oclif/plugin-which": "^3.2.55",
|
|
100
|
+
"@zitadel/api": "1.0.0-alpha.28",
|
|
101
|
+
"@zitadel/config": "1.0.0-alpha.28",
|
|
102
|
+
"@zitadel/server": "1.0.0-alpha.28",
|
|
91
103
|
"ajv": "^8.20.0",
|
|
92
104
|
"consola": "^3.4.2",
|
|
93
105
|
"magicast": "^0.5.3",
|
|
94
106
|
"mixpanel": "^0.18.1",
|
|
95
107
|
"safe-stable-stringify": "^2.5.0",
|
|
96
108
|
"semver": "^7.7.3",
|
|
97
|
-
"undici": "^7.
|
|
109
|
+
"undici": "^7.29.1",
|
|
98
110
|
"wrap-ansi": "^7.0.0",
|
|
99
111
|
"zod": "^4.3.6",
|
|
100
112
|
"picocolors": "^1.1.1",
|
|
101
|
-
"
|
|
102
|
-
"@zitadel/config": "1.0.0-alpha.25",
|
|
103
|
-
"@zitadel/server": "1.0.0-alpha.25"
|
|
113
|
+
"rosie-skills": "^0.8.5"
|
|
104
114
|
},
|
|
105
115
|
"devDependencies": {
|
|
106
|
-
"@types/node": "^
|
|
116
|
+
"@types/node": "^24.19.1",
|
|
107
117
|
"@types/semver": "^7.7.1",
|
|
108
118
|
"@types/wrap-ansi": "^3.0.0",
|
|
109
119
|
"@vitest/coverage-v8": "^4.1.11",
|
|
120
|
+
"@zitadel/api-mock": "0.0.0",
|
|
121
|
+
"@zitadel/sdk-next": "1.0.0-alpha.28",
|
|
110
122
|
"msw": "^2.14.6",
|
|
111
123
|
"oclif": "^4.17.46",
|
|
112
124
|
"tsdown": "^0.23.0",
|
|
113
125
|
"typescript": "^6.0.3",
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"@zitadel/sdk-next": "1.0.0-alpha.25"
|
|
126
|
+
"vite": "^8.3.1",
|
|
127
|
+
"vitest": "^4.1.11"
|
|
117
128
|
},
|
|
118
129
|
"scripts": {
|
|
119
130
|
"build": "tsdown",
|
|
@@ -121,6 +132,9 @@
|
|
|
121
132
|
"pretest": "pnpm run build",
|
|
122
133
|
"test": "vitest run",
|
|
123
134
|
"test:all": "pnpm run test",
|
|
124
|
-
"
|
|
135
|
+
"check-advisories": "vitest run --config vitest.advisories.config.ts",
|
|
136
|
+
"readme": "oclif readme",
|
|
137
|
+
"lint": "biome check .",
|
|
138
|
+
"build-release": "node ../../scripts/release-clean.mjs local-dist && pnpm run build"
|
|
125
139
|
}
|
|
126
140
|
}
|
|
@@ -4,8 +4,9 @@ description: >-
|
|
|
4
4
|
Set up and manage Zitadel authentication in a local project with the
|
|
5
5
|
agent-friendly `zitadel` CLI. Use when the user wants to add login,
|
|
6
6
|
registration, or session handling, create a Zitadel project, scaffold auth
|
|
7
|
-
for a Next.js,
|
|
8
|
-
|
|
7
|
+
for a Next.js, Nuxt, SvelteKit, SolidStart, Qwik Router, TanStack Start, React,
|
|
8
|
+
Vue, Angular, Solid, Svelte, or Qwik app, or plan and apply Zitadel config
|
|
9
|
+
changes from repo state.
|
|
9
10
|
---
|
|
10
11
|
|
|
11
12
|
# Zitadel CLI
|
|
@@ -32,10 +33,19 @@ to install first:
|
|
|
32
33
|
npx @zitadel/cli@alpha <command> --non-interactive --json
|
|
33
34
|
```
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
The CLI requires Node.js 24+.
|
|
36
|
+
Always pass `@alpha`: bare `npx @zitadel/cli` resolves npm's `latest` tag,
|
|
37
|
+
which still points at an early `0.0.0` build. Use an exact `1.0.0-alpha.N`
|
|
38
|
+
selector in agent scripts and bug reports for reproducibility.
|
|
39
|
+
The CLI requires Node.js 24+. When `setup` creates a new app it first checks the running Node.js against the `engines.node` of the framework CLI it is about to run (`@angular/cli`, `nuxi`, `create-vite`, `create-next-app`). Only the Angular CLI refuses a Node it does not accept, and that range can be newer than 24.0: if `setup` refuses with `E_VALIDATION` naming the Node versions Angular accepts, switch to one of them and run it again. The Angular CLI checks each major on its own, so only 22.22.3+ on 22, 24.15.0+ on 24 and 26.x are accepted (23 and 25 run with a warning), and Node 27 or later is refused even though the published range reads `>=26.0.0`. For the other frameworks the CLI carries on, so `setup` adds a warning to the envelope's `warnings` and continues.
|
|
40
|
+
|
|
41
|
+
The app's framework must be at or above a minimum version: Next.js 15.2.3,
|
|
42
|
+
React 18, Vue 3.2, Nuxt 4, Angular 17, Solid 1.6, Svelte 5, Qwik 2.0.0-beta.45. Newer major
|
|
43
|
+
versions are not refused. `setup` and `doctor` refuse an app below its minimum,
|
|
44
|
+
by declared range or installed release, with `E_UNSUPPORTED_PROJECT_SHAPE`
|
|
45
|
+
(exit 3); `setup` refuses before it scaffolds or patches anything, while
|
|
46
|
+
`doctor --fix` can still repair unrelated files, so do not assume a floor error
|
|
47
|
+
left the project untouched. The message names the minimum and the hint says to
|
|
48
|
+
upgrade, so upgrade the app and rerun rather than retrying.
|
|
39
49
|
|
|
40
50
|
## Using the CLI
|
|
41
51
|
|
|
@@ -74,12 +84,28 @@ The CLI requires Node.js 24+.
|
|
|
74
84
|
Two deliberate deviations worth knowing: `-n` is `--non-interactive` (not
|
|
75
85
|
`--dry-run`, which is long-only), and machine output is `--json` (not
|
|
76
86
|
`--output json`).
|
|
87
|
+
- **Writing a resource's body.** A `create` or `update` takes every field of
|
|
88
|
+
its body as a flag, nested ones too: a nested field's flag is its dot path
|
|
89
|
+
joined with `-` (`oidc.client_id` is `--oidc-client-id`), a list is a
|
|
90
|
+
repeated flag, a boolean takes `--no-<flag>` for `false`, and an open record
|
|
91
|
+
(`attributes`) takes repeated `key=value` entries. `--set <path>=<value>`
|
|
92
|
+
(or `<path>:=<json>` for JSON) reaches any field by its dot path, and
|
|
93
|
+
`--data` / `--file` take the whole document. They combine: the document
|
|
94
|
+
first, then the field flags, then each `--set`, with objects merging key by
|
|
95
|
+
key. `resources --json` lists each write's fields with their dot path
|
|
96
|
+
(`name`), `flag` (`null` when only `--set` reaches it), `kind` and
|
|
97
|
+
`required`; `--dry-run --json` returns the body that would be sent. For a
|
|
98
|
+
deeply nested body, writing the document and passing it with `--file -` is
|
|
99
|
+
often simplest.
|
|
77
100
|
- **Never put secrets on the command line.** A property whose name reads as a
|
|
78
101
|
credential (`password`, `client_secret`, `api_key`, …) is refused anywhere on
|
|
79
|
-
argv
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
argv.
|
|
102
|
+
argv when it holds free-form text — as a field flag, a `--set` or
|
|
103
|
+
`--attributes` entry, and inside an inline `--data` body alike, since argv is
|
|
104
|
+
visible to other processes and kept in shell history. Send such bodies with
|
|
105
|
+
`--file <path>` or `--file -` (stdin), which never pass through argv. A
|
|
106
|
+
`${{ NAME }}` reference to a project variable is not a secret and may stay on
|
|
107
|
+
argv (a connection's `client_secret` takes nothing else); write it in single
|
|
108
|
+
quotes, since inside double quotes the shell reads `${` as its own expansion.
|
|
83
109
|
- **Streams.** Capture stdout and stderr separately when scripting. The machine
|
|
84
110
|
contract is one parseable JSON object on stdout; installer, audit, and
|
|
85
111
|
package-manager progress belongs on stderr.
|
|
@@ -114,8 +140,9 @@ once — every resource, its verbs, each verb's `create_fields` / `update_fields
|
|
|
114
140
|
(flag name, kind, `required`, any closed value set), its `filter_fields` /
|
|
115
141
|
`sort_fields`, and the `delete_outcome` a destructive verb returns — so prefer it
|
|
116
142
|
over reading `<resource> --help` one at a time. A `list` verb's envelope carries
|
|
117
|
-
`data.count`,
|
|
118
|
-
|
|
143
|
+
`data.count`, the number of items it returned. A list returns one page unless
|
|
144
|
+
you pass `--all`, so a "how many …?" question is one `list --all --json` call:
|
|
145
|
+
read the count, do not page and tally.
|
|
119
146
|
|
|
120
147
|
## Reading the envelope
|
|
121
148
|
|
|
@@ -124,10 +151,13 @@ Each invocation prints one JSON object:
|
|
|
124
151
|
- `status`: `ok` | `skipped` | `error`.
|
|
125
152
|
- `cli_version`, `command`, `source`: always present.
|
|
126
153
|
- On success: `data` with the command-specific payload.
|
|
127
|
-
- On a no-op: `reason` (e.g. `
|
|
154
|
+
- On a no-op: `reason` (e.g. `already-initialized`, `already-claimed`,
|
|
155
|
+
`nothing-to-eject`).
|
|
128
156
|
- On failure: `code` (e.g. `E_VALIDATION`, `E_NETWORK`, `E_NOT_FOUND`,
|
|
129
|
-
`E_CONFLICT`) and `message
|
|
130
|
-
|
|
157
|
+
`E_CONFLICT`) and `message`, usually with a `hint`, and `details` when there
|
|
158
|
+
is structured context.
|
|
159
|
+
- `next_commands`: the suggested follow-ups, inside `data` on success and at
|
|
160
|
+
the top level on a no-op or failure. Prefer these over free-text hints.
|
|
131
161
|
- `warnings`: things that went wrong without stopping the command, such as a
|
|
132
162
|
value that was not published. Always present on success (often empty), and
|
|
133
163
|
present on a no-op or failure when there are any. Read them before you report
|
|
@@ -135,9 +165,18 @@ Each invocation prints one JSON object:
|
|
|
135
165
|
- A `list` verb emits `data: { items, count, next_page_token }`; when a page
|
|
136
166
|
remains, `data.next_commands` carries the exact command for the next page.
|
|
137
167
|
- `plan` and `apply` emit `data.changes`: one row per touched resource
|
|
138
|
-
(`{kind, action, file, id?, previous_id?}`, action ∈ create/
|
|
139
|
-
delete).
|
|
140
|
-
|
|
168
|
+
(`{kind, action, file, id?, previous_id?, moved_from?}`, action ∈ create/
|
|
169
|
+
update/revision/delete/move). A `move` is a file that took over a resource
|
|
170
|
+
from a removed one (`moved_from`). Plan rows preview; apply rows report, with
|
|
171
|
+
the resulting platform ids. Use it to verify an edit did what you intended.
|
|
172
|
+
`data.unsupported_deletions` counts removed files whose resource cannot be
|
|
173
|
+
deleted yet (they are kept, and are not part of `total`); on `apply` the files
|
|
174
|
+
are listed in `data.unsupported_deletion_files`.
|
|
175
|
+
- `apply` leaves the files under `.zitadel/` as written: what the server stores
|
|
176
|
+
is never written back, and a field a file leaves out reads as the server's
|
|
177
|
+
default, so `plan` reports no change after an `apply`. `data.files_updated`
|
|
178
|
+
lists the one rewrite: a flow whose `user_schema` pinned a schema revision id
|
|
179
|
+
the apply superseded, re-pinned to the new revision's id.
|
|
141
180
|
- A write verb's `--dry-run` reports what it would send without calling the
|
|
142
181
|
platform, so you can preview a mutation before making it.
|
|
143
182
|
|
|
@@ -145,6 +184,9 @@ Common error codes point at their own fix in `next_commands`:
|
|
|
145
184
|
|
|
146
185
|
- `E_VALIDATION`: the body or flags are wrong; `message` names what, and
|
|
147
186
|
`details` often lists the missing or available values.
|
|
187
|
+
- `E_CREDENTIAL_MISSING`: a connection's `client_id` or `client_secret` names a
|
|
188
|
+
project variable that does not exist; `details.variable` is the name. Publish it
|
|
189
|
+
with `variables set NAME --project-level` (add `--secret` for the secret), then retry.
|
|
148
190
|
- `E_LOCAL_SERVER_NOT_RUNNING`: start the local runtime, then retry with
|
|
149
191
|
`--server local`.
|
|
150
192
|
- `E_NOT_FOUND`: an HTTP 404 — a missing resource, or a `--server` that is not a
|
|
@@ -181,16 +223,44 @@ the conversation: you clarify with the human, then drive the CLI headlessly.
|
|
|
181
223
|
Ask about:
|
|
182
224
|
|
|
183
225
|
- **Sign-in methods** — password (the usual default), passkeys, and single
|
|
184
|
-
sign-on. If they want SSO, which providers?
|
|
185
|
-
|
|
186
|
-
the
|
|
187
|
-
|
|
226
|
+
sign-on. If they want SSO, which providers? A provider the CLI does not list
|
|
227
|
+
by name is still possible: run `zitadel auth-method sso enable --help` to see
|
|
228
|
+
whether the installed CLI takes one, and which settings it needs, and ask for
|
|
229
|
+
those too.
|
|
230
|
+
- **Profile fields** — which attributes sign-up collects. The starting field
|
|
231
|
+
set depends on the use-case you pick (see *Presets and use-cases* below) —
|
|
232
|
+
the default (`minimal`) is the login identifier only, **not** names. Confirm
|
|
233
|
+
which fields they want (first/last name, phone, username, display name) and
|
|
234
|
+
choose the use-case or edit the schema accordingly.
|
|
188
235
|
|
|
189
236
|
Offer only what the installed CLI actually supports: read the real sign-in
|
|
190
237
|
presets, profile fields, and SSO options from the CLI first (`setup --help`,
|
|
191
238
|
`resources --json`) and present those, not a list you remember — the options
|
|
192
239
|
move with the CLI version.
|
|
193
240
|
|
|
241
|
+
## Presets and use-cases — map the answers, don't trust the names
|
|
242
|
+
|
|
243
|
+
`setup` has two independent axes, and their names do **not** mean what they look
|
|
244
|
+
like. Read the current sets from `setup --help`, but know the traps:
|
|
245
|
+
|
|
246
|
+
- **Use-case = which profile fields the schema collects.** `minimal` is the
|
|
247
|
+
login identifier **only** — it does *not* include names. First + last name is
|
|
248
|
+
`--use-case consumer` (adds `givenName` + `familyName`); add a company with
|
|
249
|
+
`--use-case business`. Choosing `minimal` because the developer said "keep it
|
|
250
|
+
minimal" leaves an identifier-only schema that ignores the names they asked
|
|
251
|
+
for.
|
|
252
|
+
- **Preset = how they sign in (the login flow + auth methods).**
|
|
253
|
+
`password-first` makes password the primary step **but still leaves passkeys
|
|
254
|
+
enabled**; `passkey-first` leads with a passkey. Neither one gives you
|
|
255
|
+
password-only. If the developer does not want passkeys, turn them off
|
|
256
|
+
yourself: set `x-auth-methods.passkey.enabled` to `false` in
|
|
257
|
+
`.zitadel/schemas/*.json`, then `apply`.
|
|
258
|
+
|
|
259
|
+
Translate the developer's answers into the right axis values, then **verify
|
|
260
|
+
against what actually deployed**: read the live schema back
|
|
261
|
+
(`schemas get <objectType> --json`) and confirm the fields and auth methods
|
|
262
|
+
match what they asked for — don't assume a preset name did it.
|
|
263
|
+
|
|
194
264
|
Skip the questions and proceed with the defaults above — stating the assumptions
|
|
195
265
|
you made so the user can correct them — in exactly two cases: the user already
|
|
196
266
|
told you what they want, or you are running non-interactively (a one-shot/headless
|
|
@@ -220,33 +290,123 @@ framework, sign-in preset, and profile-field options):
|
|
|
220
290
|
```sh
|
|
221
291
|
npx @zitadel/cli@alpha doctor --non-interactive --json
|
|
222
292
|
npx @zitadel/cli@alpha start --non-interactive --json
|
|
223
|
-
npx @zitadel/cli@alpha setup --framework next --server local --
|
|
293
|
+
npx @zitadel/cli@alpha setup --framework next --server local --non-interactive --json
|
|
224
294
|
npx @zitadel/cli@alpha doctor --non-interactive --json
|
|
225
295
|
npx @zitadel/cli@alpha plan --non-interactive --json
|
|
226
296
|
npx @zitadel/cli@alpha apply --non-interactive --json
|
|
227
297
|
```
|
|
228
298
|
|
|
229
299
|
`setup` scaffolds into an empty directory, or patches an existing app project
|
|
230
|
-
where it detects a framework.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
300
|
+
where it detects a framework. What `start` leaves in a directory —
|
|
301
|
+
`.zitadel/local/` and the `.gitignore` line that ignores it — still counts as
|
|
302
|
+
empty, so the golden path runs `setup` right after `start` in the same
|
|
303
|
+
directory. Any other non-empty directory stops setup with a hint to pass
|
|
304
|
+
`--force`. Pass it only for a directory whose contents may be replaced: files
|
|
305
|
+
the new app also has, such as `package.json`, are overwritten. Without a
|
|
306
|
+
terminal `setup` cannot ask which framework to scaffold, so pass `--framework`;
|
|
307
|
+
the error lists the choices in `details.frameworks`. `setup --dry-run` creates
|
|
308
|
+
no app: where it would scaffold one, it previews the project, and
|
|
309
|
+
`data.files_written` is empty, because those files depend on the generated app.
|
|
310
|
+
When setup fails after scaffolding a new app, before its default schema and
|
|
311
|
+
flow are uploaded, it removes the app again and puts back what the directory
|
|
312
|
+
held, so rerunning the same `setup` starts over.
|
|
313
|
+
|
|
314
|
+
`start` reuses a server already running in the directory only when it is the
|
|
315
|
+
release this CLI ships; one an earlier release started is restarted, and its
|
|
316
|
+
data stays. `setup --server local` refuses a binary-runtime server another
|
|
317
|
+
release started with `E_CONFLICT` before it creates anything: that server's API
|
|
318
|
+
is its own release's. Its `next_commands` run `start`, then `setup` again.
|
|
319
|
+
|
|
320
|
+
In an existing app, `--framework` has to name the framework setup detects
|
|
321
|
+
there; another one stops setup with `E_CONFLICT` instead of offering
|
|
322
|
+
`--force`. Setup reports its conflicts with the app before it creates a
|
|
323
|
+
project, and the error's `hint` says whether `--force` resolves one: it
|
|
324
|
+
replaces a file at a path setup writes, but not the app's root component or
|
|
325
|
+
request boundary at another path.
|
|
234
326
|
|
|
235
327
|
The app may also live in a subdirectory of the one `start` ran in: `setup`,
|
|
236
|
-
`console
|
|
328
|
+
`console`, `--server local` and `doctor` read `.zitadel/local/` from the working
|
|
237
329
|
directory or the nearest parent that has it (up to the home directory), so
|
|
238
|
-
`mkdir my-app && cd my-app` after `start` works
|
|
330
|
+
`mkdir my-app && cd my-app` after `start` works too. `doctor` checks that
|
|
331
|
+
server and its port, but runs its project checks in the working directory, so run
|
|
332
|
+
it from the app. When that server is unhealthy it suggests `start` and
|
|
333
|
+
`reset --force` with `--cwd` set to the directory that holds it (when that path needs
|
|
334
|
+
shell quoting the commands are left out, the hint names the directory, and
|
|
335
|
+
`doctor --json` returns the argument lists in `details.suggested_args` to run as they are). `stop`,
|
|
336
|
+
`reset`, `logs` and `status` read only the working directory's
|
|
337
|
+
`.zitadel/local/`, so run them where `start` ran. On a local
|
|
239
338
|
server that hosts the platform project, `setup` attaches the project to the
|
|
240
339
|
local admin's team and ends `data.next_commands` with `console`; when it finds
|
|
241
340
|
no local admin for that server on the way up, it says so in the envelope's
|
|
242
341
|
`warnings` and the project stays unattached, so the local console does not
|
|
243
342
|
list it.
|
|
244
343
|
|
|
344
|
+
When `setup --sso` or `sso enable` adds a social sign-in provider, the user
|
|
345
|
+
must register the connection's redirect URI with the provider themselves: give
|
|
346
|
+
them `data.sso[].callback_uri` from `setup`, or `data.callback_uri` from
|
|
347
|
+
`sso enable`, verbatim. Each connection has its own URI, so a URI from another
|
|
348
|
+
provider or an older CLI version does not work.
|
|
349
|
+
|
|
245
350
|
After `setup`, follow `data.next_commands` to start the app. Prove the generated
|
|
246
351
|
auth flow in a visible browser by registering a unique user, logging out, logging
|
|
247
352
|
back in with the same email/password, and ending on the signed-in profile page.
|
|
248
353
|
Do not treat a rendered login or registration form as completion.
|
|
249
354
|
|
|
355
|
+
To move a set-up app to another dev port (the dev server exits with
|
|
356
|
+
`EADDRINUSE`, or another app needs the port), run `setup --dev-port <port>` in
|
|
357
|
+
the app; never change the port in one file by hand. In a directory with a
|
|
358
|
+
`zitadel.json`, `setup` returns `status: "skipped"` with `reason:
|
|
359
|
+
"already-initialized"`, unless `--dev-port` is given: then it moves the app.
|
|
360
|
+
It allows the new origin on the server first, and a refusal changes nothing.
|
|
361
|
+
It then rewrites the dev script or dev-server config, `ZITADEL_ISSUER` in
|
|
362
|
+
`.env.local`, `zitadel.json`, `.zitadel/secret` and the README/AGENTS.md
|
|
363
|
+
guidance, and removes the old origin. `data.previous_issuer` and `data.issuer`
|
|
364
|
+
name both origins, and `data.moved` is `false` when the app was already on that
|
|
365
|
+
port. A social sign-in provider still redirects to the old port: `warnings`
|
|
366
|
+
names the redirect URI to add at each provider. Restart the dev server
|
|
367
|
+
afterwards.
|
|
368
|
+
|
|
369
|
+
To change how users sign in after setup, use the `auth-method` commands. Each
|
|
370
|
+
sign-in method has its own command, with `--schema` when the project has more
|
|
371
|
+
than one:
|
|
372
|
+
|
|
373
|
+
- `auth-method password enable` and `auth-method password disable`
|
|
374
|
+
- `auth-method passkey enable` and `auth-method passkey disable`
|
|
375
|
+
- `auth-method sso enable --provider google` adds a provider. It prompts for
|
|
376
|
+
the client id and secret, or takes `--client-id` with the secret piped on
|
|
377
|
+
stdin when non-interactive. Any other OpenID Connect provider is
|
|
378
|
+
`--provider custom` with `--slug`, `--display-name`, `--issuer` and optionally
|
|
379
|
+
`--scopes` (default `openid profile email`).
|
|
380
|
+
An issuer on `http://localhost:<port>` (a test provider on this machine)
|
|
381
|
+
works against a server `zitadel start` runs as a process: `start` sets
|
|
382
|
+
`NEXTGEN_HTTPCLIENT_ALLOW_LIST=localhost,127.0.0.0/8,::1/128` unless
|
|
383
|
+
`.env.local`, `.env` or the shell sets it, and setting it empty turns it off.
|
|
384
|
+
Under `--runtime docker` localhost is the container, so the provider is not
|
|
385
|
+
reachable. Otherwise `sso enable` warns in `warnings` that sign-in will fail.
|
|
386
|
+
`auth-method sso disable --provider google` removes a provider; a custom one
|
|
387
|
+
is named by its slug, as in `auth-method sso disable --provider acme-sso`.
|
|
388
|
+
|
|
389
|
+
The commands change only local files, apart from
|
|
390
|
+
`auth-method sso enable`, which also stores the provider's credentials on the
|
|
391
|
+
project. When they refuse, they write and publish nothing, on a dry run too.
|
|
392
|
+
They refuse to disable a method a login flow still asks for, to change a method
|
|
393
|
+
while a login flow has errors that prevent checking it, to enable password on a
|
|
394
|
+
schema without `x-identifier`, to edit a value that is not the shape they edit,
|
|
395
|
+
and to edit a schema that points at an external URL. Disabling the schema's last
|
|
396
|
+
way to sign in needs `--force` when non-interactive; only pass it for a schema
|
|
397
|
+
whose users are managed through the API, and ask the user first. That refusal's
|
|
398
|
+
`details.suggested_args` lists the `--force` re-run first, then the methods that
|
|
399
|
+
could be enabled instead. A dry run of the change is not refused: it previews it
|
|
400
|
+
and warns that no way to sign in would be left. A method that is enabled but not
|
|
401
|
+
offered by any active flow is reported in `warnings` (and in `data.not_offered`
|
|
402
|
+
for password and passkey). Every command reports `data.changed`, the
|
|
403
|
+
project-relative files it wrote (on a dry run, the files it would write), empty
|
|
404
|
+
when nothing changed. Follow `data.next_commands` (`plan`, `apply`, and
|
|
405
|
+
`variables set` when a credential did not reach the project) to publish the
|
|
406
|
+
change. When a path or schema name would need shell quoting, `next_commands` is
|
|
407
|
+
empty and `data.next_args` (or `details.suggested_args` on a refusal) holds the
|
|
408
|
+
same commands as argument lists.
|
|
409
|
+
|
|
250
410
|
Repo config is authoritative: edit `zitadel.json` or files under `.zitadel/`,
|
|
251
411
|
then re-run `plan` and `apply`. See the reference below for driving the login UI
|
|
252
412
|
and the config-sync details.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
### Driving the login UI
|
|
2
2
|
|
|
3
|
-
`<zitadel-login
|
|
4
|
-
roots. The stable automation hooks live inside nested shadow roots, so a flat
|
|
3
|
+
`<zitadel-login>`, `<zitadel-session>`, and `<zitadel-logout>` are Lit elements
|
|
4
|
+
with open shadow roots. The stable automation hooks live inside nested shadow roots, so a flat
|
|
5
5
|
`document.querySelector('[data-testid="zitadel-input-email"]')` will not find
|
|
6
6
|
the native control. Browser drivers with shadow-DOM-aware locators, such as
|
|
7
7
|
Playwright, can target the hooks directly. Generic DOM-eval drivers should
|
|
@@ -29,11 +29,18 @@ button. Hooks stay method-named even when the flow engine names a credential
|
|
|
29
29
|
field `x-auth-methods#<method>`; only the `name` attribute carries that raw
|
|
30
30
|
form key. Enter inside a field submits the step's primary action, but only for
|
|
31
31
|
key events that carry `key: "Enter"` — drivers whose synthesized key events
|
|
32
|
-
omit it (some CDP wrappers) should click `zitadel-action-submit` instead.
|
|
33
|
-
`.signout-btn`; Playwright-style locators may use `zitadel-logout .signout-btn`.
|
|
34
|
-
The canonical component hook list lives in `packages/components/README.md`.
|
|
32
|
+
omit it (some CDP wrappers) should click `zitadel-action-submit` instead.
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
For sign-out, the profile page that setup generates renders `<zitadel-session>`:
|
|
35
|
+
click its `zitadel-session-logout` host, or the native button inside it,
|
|
36
|
+
`zitadel-session-logout-button`. An app that renders `<zitadel-logout>` instead
|
|
37
|
+
hides sign-out behind an avatar menu: click the "Open user menu" button, then
|
|
38
|
+
pierce to `.signout-btn` (Playwright: `zitadel-logout .signout-btn`), which
|
|
39
|
+
carries no hook. A `<zitadel-logout>` with a `<template>` child shows no menu:
|
|
40
|
+
click the app's own element marked `data-action="logout"`. The canonical
|
|
41
|
+
component hook list lives in `packages/components/README.md`.
|
|
42
|
+
|
|
43
|
+
The checked-in automated regression path is `moon run e2e:journey`, which
|
|
37
44
|
exercises fresh-app setup plus registration, logout, and login across the
|
|
38
45
|
supported frameworks.
|
|
39
46
|
|
|
@@ -49,24 +56,34 @@ revisioned and immutable: every edit — including a `.liquid`-only edit —
|
|
|
49
56
|
plans as a `revise` and `apply` publishes a new revision; the login serves
|
|
50
57
|
the newest one. `plan` validates templates with the authoritative LiquidJS
|
|
51
58
|
validator (`E_VALIDATION` lists rule ids such as `no-script-tag` and
|
|
52
|
-
`mandatory-gates`; every template must keep a
|
|
53
|
-
|
|
54
|
-
must be absolute `https
|
|
59
|
+
`mandatory-gates`; every template must keep a `{% mandatory_gates %}` tag,
|
|
60
|
+
where the login adds any required field and the primary action the template
|
|
61
|
+
left out). Asset URLs must be absolute `https://`; during development, images
|
|
62
|
+
may use `http://` on `localhost`, `127.x.x.x`, or `[::1]` (not `*.localhost`).
|
|
63
|
+
`typography.font_url` needs a `typography.font_family`, is always `https://`,
|
|
64
|
+
and is loaded only when the login runs as `variant="page"`, which setup
|
|
65
|
+
generates only when it creates a Next.js or Nuxt app itself, in an empty
|
|
66
|
+
directory. Keep exactly one descriptor in
|
|
55
67
|
`.zitadel/branding/` — extra `*.json` files there fail the scan.
|
|
56
68
|
Server-provisioned defaults remain a fallback for non-CLI project
|
|
57
69
|
creation, but CLI-created projects are authored from local files first. Flows are
|
|
58
70
|
revisioned like branding: an edit plans as a `revise` and `apply` publishes a new
|
|
59
|
-
immutable flow revision
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
immutable flow revision. A flow names its schema by `objectType` in
|
|
72
|
+
`user_schema` and runs against the schema's newest revision, so a schema revise
|
|
73
|
+
needs no change to `user_schema`; one that removes or renames a property a step
|
|
74
|
+
collects needs that step's `fields` updated, and `plan` checks only the flows it
|
|
75
|
+
uploads. A login pinned by `flow-name` serves that flow's newest active
|
|
76
|
+
revision; an unpinned login serves the newest active unscoped revision for its
|
|
77
|
+
purpose in the project, whatever its flow's name. Older revisions stay active,
|
|
78
|
+
so an `audience` added after a flow was applied without one doesn't take that
|
|
79
|
+
earlier revision out of the running. Removing a flow file does not retire the
|
|
63
80
|
flow. Managed files carry a marker comment; `eject` removes only
|
|
64
81
|
files that still carry it, preserving anything the user replaced. For app-local
|
|
65
82
|
development, `--server local` resolves through `.zitadel/local/runtime.json` and
|
|
66
83
|
requires a healthy
|
|
67
|
-
`npx @zitadel/cli@alpha start` runtime.
|
|
68
|
-
into the directory
|
|
69
|
-
scaffolds
|
|
84
|
+
`npx @zitadel/cli@alpha start` runtime. The `.zitadel/local/` that `start`
|
|
85
|
+
writes into the directory still counts as empty, so a same-directory `setup`
|
|
86
|
+
scaffolds without `--force` (this is exactly what the golden path does).
|
|
70
87
|
`setup` installs dependencies
|
|
71
88
|
with the detected package manager by default; pass `--skip-install` when the
|
|
72
89
|
agent or host workflow will install dependencies separately.
|
package/dist/groups-CbWm8kCm.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//#region src/lib/oclif/groups.ts
|
|
2
|
-
/**
|
|
3
|
-
* The groups the root help lists commands under, declared in print order: the
|
|
4
|
-
* journey runs from setting up a project, to running the local server, to
|
|
5
|
-
* managing its configuration, to acting on the resources inside it. Every command declares its own group
|
|
6
|
-
* (`static group` on the class) so nothing has to be registered centrally; a
|
|
7
|
-
* command without one lands in the trailing {@link ADDITIONAL_COMMANDS_GROUP}
|
|
8
|
-
* with oclif's own utilities.
|
|
9
|
-
*/
|
|
10
|
-
const CommandGroups = {
|
|
11
|
-
project: "Project commands",
|
|
12
|
-
localServer: "Local server commands",
|
|
13
|
-
configuration: "Configuration commands",
|
|
14
|
-
resources: "Resource commands"
|
|
15
|
-
};
|
|
16
|
-
const COMMAND_GROUPS = Object.values(CommandGroups);
|
|
17
|
-
/** Where ungrouped commands (oclif's `autocomplete`, `search`, …) are listed. */
|
|
18
|
-
const ADDITIONAL_COMMANDS_GROUP = "Additional commands";
|
|
19
|
-
//#endregion
|
|
20
|
-
export { COMMAND_GROUPS as n, CommandGroups as r, ADDITIONAL_COMMANDS_GROUP as t };
|
|
21
|
-
|
|
22
|
-
//# sourceMappingURL=groups-CbWm8kCm.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"groups-CbWm8kCm.mjs","names":[],"sources":["../src/lib/oclif/groups.ts"],"sourcesContent":["/**\n * The groups the root help lists commands under, declared in print order: the\n * journey runs from setting up a project, to running the local server, to\n * managing its configuration, to acting on the resources inside it. Every command declares its own group\n * (`static group` on the class) so nothing has to be registered centrally; a\n * command without one lands in the trailing {@link ADDITIONAL_COMMANDS_GROUP}\n * with oclif's own utilities.\n */\nexport const CommandGroups = {\n project: \"Project commands\",\n localServer: \"Local server commands\",\n configuration: \"Configuration commands\",\n resources: \"Resource commands\",\n} as const;\n\nexport type CommandGroup = (typeof CommandGroups)[keyof typeof CommandGroups];\n\nexport const COMMAND_GROUPS: readonly CommandGroup[] = Object.values(CommandGroups);\n\n/** Where ungrouped commands (oclif's `autocomplete`, `search`, …) are listed. */\nexport const ADDITIONAL_COMMANDS_GROUP = \"Additional commands\";\n"],"mappings":";;;;;;;;;AAQA,MAAa,gBAAgB;CAC3B,SAAS;CACT,aAAa;CACb,eAAe;CACf,WAAW;AACb;AAIA,MAAa,iBAA0C,OAAO,OAAO,aAAa;;AAGlF,MAAa,4BAA4B"}
|