@zitadel/cli 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zitadel/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Agent-friendly Zitadel CLI",
5
5
  "homepage": "https://github.com/zitadel/nextgen/tree/main/apps/cli#readme",
6
6
  "bugs": {
@@ -106,7 +106,7 @@
106
106
  "description": "View login flows."
107
107
  },
108
108
  "policies": {
109
- "description": "View policies."
109
+ "description": "View and test policies."
110
110
  },
111
111
  "env": {
112
112
  "description": "Show and bind environments."
@@ -127,9 +127,9 @@
127
127
  "@oclif/plugin-search": "^1.2.50",
128
128
  "@oclif/plugin-version": "^2.2.46",
129
129
  "@oclif/plugin-which": "^3.2.55",
130
- "@zitadel/api": "0.2.0",
131
- "@zitadel/config": "0.2.0",
132
- "@zitadel/server": "0.2.0",
130
+ "@zitadel/api": "0.3.0",
131
+ "@zitadel/config": "0.3.0",
132
+ "@zitadel/server": "0.3.0",
133
133
  "ajv": "^8.20.0",
134
134
  "consola": "^3.4.2",
135
135
  "magicast": "^0.5.3",
@@ -148,7 +148,8 @@
148
148
  "@types/wrap-ansi": "^3.0.0",
149
149
  "@vitest/coverage-v8": "^4.1.11",
150
150
  "@zitadel/api-mock": "0.0.0",
151
- "@zitadel/sdk-next": "0.2.0",
151
+ "@zitadel/sdk-next": "0.3.0",
152
+ "@zitadel/vitest-config": "0.0.0",
152
153
  "msw": "^2.14.6",
153
154
  "oclif": "^4.17.46",
154
155
  "tsdown": "^0.23.0",
@@ -71,7 +71,10 @@ upgrade, so upgrade the app and rerun rather than retrying.
71
71
  `--help` output is bounded too — read it in full rather than `head`-ing it, or
72
72
  you will miss flags further down.
73
73
  - **Working directory.** Add `--cwd <path>` when operating outside the current
74
- working directory.
74
+ working directory. A relative `--env-file` path is still read from the
75
+ current directory, not from `--cwd` (`--cwd app --env-file app/.env.ci`):
76
+ Node reads `--env-file` itself before the CLI starts and exits 9 with
77
+ `node: <path>: not found`, and no envelope, when the file is not there.
75
78
  - **Server and project.** A command that talks to a project reads
76
79
  `ZITADEL_URL`, `ZITADEL_PROJECT_ID` and `ZITADEL_PROJECT_SECRET`, each from the
77
80
  first source that has it: `--server` (the URL only), `--env-file <path>`, the
@@ -198,6 +201,11 @@ over reading `<resource> --help` one at a time. A `list` verb's envelope carries
198
201
  you pass `--all`, so a "how many …?" question is one `list --all --json` call:
199
202
  read the count, do not page and tally.
200
203
 
204
+ To find the users still on an older revision of a schema, filter on the
205
+ schema's object type and exclude the newest revision's URL:
206
+ `users list --filter schema_object_type=equals:<type> --filter
207
+ schema=not_equals:<newest-url> --all --json`.
208
+
201
209
  ## Reading the envelope
202
210
 
203
211
  Each invocation prints one JSON object:
@@ -236,6 +244,12 @@ Each invocation prints one JSON object:
236
244
  Users keep their schema revision and attributes: a rollback does not migrate
237
245
  them back. Without `data.pointers`, a warning says the release could not be
238
246
  read.
247
+ - `deploy --dry-run` and `deploy` emit `data.diff`, the git diff the terminal
248
+ shows, against the live release's commit (`diff.against`): `diff.files` holds
249
+ one `{path, status, previous_path?, patch}` per changed file (`status` is
250
+ `added`, `modified`, `deleted`, `renamed` or `copied`; `patch` is its unified
251
+ diff). Review it before you deploy. `files` is `[]` when nothing changed and
252
+ `null` when there is nothing to diff against, with `diff.note` saying why.
239
253
  - A write verb's `--dry-run` reports what it would send without calling the
240
254
  platform, so you can preview a mutation before making it.
241
255
  - `api` emits the response body as `data`, exactly as the API reference
@@ -360,12 +374,38 @@ npx @zitadel/cli@latest doctor --non-interactive --json
360
374
  npx @zitadel/cli@latest deploy -m "<why this release changes>" --non-interactive --json
361
375
  ```
362
376
 
377
+ `setup` commits the project it scaffolds: `git init` first when the directory
378
+ is not yet a repository, then one commit, `chore: scaffold the project with
379
+ zitadel setup`. A release records the commit it was built from and `deploy`
380
+ diffs `.zitadel/` against it, so without this the first release carries no
381
+ commit and the next deploy reports no diff.
382
+
383
+ Setup refuses with `E_CONFLICT` when the repository already has uncommitted
384
+ work, untracked files included, which `details.untracked` lists separately
385
+ from `details.modified`. The commit covers the project directory, so it can
386
+ only tell its own files from yours when the tree starts clean. Commit or stash
387
+ first, then rerun. Only what `start` leaves is exempt: `.zitadel/local/` and
388
+ the `.gitignore` line that ignores it. A connection under `.zitadel/idps/` is
389
+ yours and is not exempt.
390
+
391
+ Setup deploys nothing, and it does not need to: a project with no release
392
+ resolves the newest revisions, which are the ones setup just uploaded, so
393
+ sign-in already runs on `.zitadel/`. Deploying pins them into a release, which
394
+ is what the server will require once that fallback goes (#1616). The publish
395
+ step says so and names the command. `data.git` reports what setup did
396
+ (`initialized`, and the `commit`, or null). `--no-git` skips both the refusal
397
+ and the commit, and nothing prompts, so this is the same interactively and in
398
+ CI.
399
+
363
400
  `setup` scaffolds into an empty directory, or patches an existing app project
364
401
  where it detects a framework. What `start` leaves in a directory —
365
402
  `.zitadel/local/` and the `.gitignore` line that ignores it — still counts as
366
403
  empty, so the golden path runs `setup` right after `start` in the same
367
- directory. Any other non-empty directory stops setup with a hint to pass
368
- `--force`. Pass it only for a directory whose contents may be replaced: files
404
+ directory. A `--cwd` that does not exist yet counts as empty too: setup creates
405
+ it with the app, and removes it again when setup fails before the app is kept.
406
+ A `--cwd` that is a file fails with `E_VALIDATION`. Any other non-empty
407
+ directory stops setup with a hint to pass `--force`. Pass it only for a
408
+ directory whose contents may be replaced: files
369
409
  the new app also has, such as `package.json`, are overwritten. Without a
370
410
  terminal `setup` cannot ask which framework to scaffold, so pass `--framework`;
371
411
  the error lists the choices in `details.frameworks`. `setup --dry-run` creates
@@ -401,7 +441,11 @@ server and its port, but runs its project checks in the working directory, so ru
401
441
  it from the app. When that server is unhealthy it suggests `start` and
402
442
  `reset --force` with `--cwd` set to the directory that holds it (when that path needs
403
443
  shell quoting the commands are left out, the hint names the directory, and
404
- `doctor --json` returns the argument lists in `details.suggested_args` to run as they are). A
444
+ `doctor --json` returns the argument lists in `details.suggested_args` to run as they are).
445
+ The hint says the server is the parent's and that `reset --force` deletes the data in that
446
+ directory, and it adds a plain `start`, which gives the working directory a server of its own
447
+ because `start` does not look in parents; a healthy parent server is reported in the `runtime`
448
+ check as started in the parent folder. A
405
449
  local server is healthy once its `/readyz` answers, which takes its database
406
450
  answering too: `start` waits for that, and the commands that read a server
407
451
  treat one whose database does not answer as unhealthy. `stop`,
@@ -535,4 +579,4 @@ Load on demand:
535
579
 
536
580
  - [`references/driving-login-ui.md`](references/driving-login-ui.md) — driving the
537
581
  `<zitadel-login>` component in a browser, and the authoritative repo-config
538
- workflow (schemas, flows, branding, policies).
582
+ workflow (schemas, flows, branding, policies and their tests).
@@ -94,7 +94,22 @@ which applies the next time a password is set. A setting left out is off, and
94
94
  the deployed release carries, so deploying without the file switches it off
95
95
  there; a password set through the API, or before the first deploy, uses the
96
96
  newest revision, which only `"config": {}` switches off. `policies list` and
97
- `policies get <id|operation>` read them back. `setup` writes and publishes
97
+ `policies get <id|operation>` read them back. A policy's cases live beside it
98
+ in `<operation>.test.json` (`.zitadel/meta/policy-test.json`): each names an
99
+ `input` in the operation's terms (`{"password": "…"}`), optional `facts` the
100
+ operation would look up (`self_service`, `history_matches`), and the expected
101
+ decision (`allowed`, optionally `code` and exactly the `violations`). The
102
+ decision and rules hold in the login too; `code` is the API's answer, and a
103
+ flow shows each rule as `error.x-auth-methods#password_<rule>` instead.
104
+ `policies test [operation]` evaluates every case on the server against the
105
+ sibling policy file, or with `--release <id>` against the revision that
106
+ release pins; a missing policy is tested as none. It fails with `E_VALIDATION`
107
+ (exit 3) when a case does not hold, `data`/`details` carrying `source`,
108
+ `operations[].cases[]` (`name`, `passed`, `expected`, `actual`), `passed` and
109
+ `failed`; with no test files it is `skipped` (`no-policy-tests`). `deploy`
110
+ never carries test files. Until #2331, a release that pins no flow is tested
111
+ with a warning: its sign-ins use the newest revisions instead. Write cases from
112
+ what the user wants enforced; never invent expectations for them. `setup` writes and publishes
98
113
  the password policy with a `min_length` of 15; pass `--password-min-length <n>`
99
114
  only when the user asks for another value (`0` sets none). Managed files carry
100
115
  a marker comment; `eject` removes only