@capxul/cli 4.20.0-beta.7 → 4.20.0-beta.8

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 CHANGED
@@ -89,6 +89,14 @@ These commands accept `--email`. Without it, they restore the protected current
89
89
  session. Organization reads accept `--org` or its alias `--org-id`. Identical
90
90
  repeated IDs are accepted. Different IDs are refused.
91
91
 
92
+ A read without `--org` resolves one exact Organization in this order: the saved
93
+ read default, then the recovery handle this machine recorded for the person's
94
+ Organization journey. A recovery handle can also name an Organization whose
95
+ setup lane still runs, which the own-access list does not carry yet; the read
96
+ reports that exact lane, and it applies the usual current-access rule again once
97
+ the Organization reports ready. The read refuses an Organization it cannot
98
+ reach, and it never substitutes another one.
99
+
92
100
  `org use` requires an explicit Organization ID. It checks current access and
93
101
  saves a protected per-person read default. The default never grants authority.
94
102
  Each read checks current access again. Without an explicit ID or saved default,
@@ -169,8 +177,10 @@ returned view is the authorization-time view of the consent commit
169
177
 
170
178
  `org create` and `org retry` restore the protected current session and start the
171
179
  existing command-scoped browser signer. They never read or write the saved read
172
- default. Local input checks run before any client, browser, or backend work, and
173
- they include the confirmation gate:
180
+ default. `org create` writes the person's Organization recovery handle. That
181
+ handle holds the exact business handle and the exact Organization ID, and it
182
+ holds nothing else. Local input checks run before any client, browser, or
183
+ backend work, and they include the confirmation gate:
174
184
 
175
185
  - A noninteractive or JSON write requires `--confirm`. Without it the command
176
186
  refuses with exit 2 before any client, browser, or mutation work.
@@ -211,6 +221,47 @@ failed lane still reports the Organization it is about. The command returns
211
221
  success only after an exact `org(O).getLifecycle()` read reports `ready`. It
212
222
  never saves a read default and never returns a different ready Organization.
213
223
 
224
+ `org create` continues the Organization journey this machine already prepared.
225
+ Before the first durable write it records the exact business handle as the safe
226
+ recovery handle. It adds the first committed Organization ID to that handle
227
+ before it forwards any founder authorization digest, and it keeps that handle
228
+ after a failure, an interruption, or a ready result. A later create therefore
229
+ resolves exactly one Organization:
230
+
231
+ - The same handle resumes the exact recorded Organization. It calls the SDK
232
+ recovery owner once per attempt and settles the same lifecycle. It never
233
+ submits a second bootstrap, and it never creates a second Organization or
234
+ treasury.
235
+ - A different handle refuses with exit 2 while the recorded Organization is not
236
+ ready. The refusal names the exact Organization.
237
+ - A different handle creates one Organization only after the recorded
238
+ Organization reaches ready.
239
+ - A recorded Organization that is already ready, and still in the person's
240
+ current access, returns unchanged, with no write and no signature. A ready
241
+ result the person can no longer reach refuses, and the committed recovery
242
+ handle stays recorded for exact recovery.
243
+ - A create that continues a recorded handle checks current access before it
244
+ reports success. The committed Organization ID becomes durable first, so a
245
+ refusal or an interruption keeps the exact recovery handle, and a ready
246
+ lifecycle line reaches stderr only after the check resolves.
247
+ - A terminal preview reads the recorded Organization's lifecycle only for the
248
+ handle that continues it. A different handle is a new creation, so an
249
+ unreachable recorded Organization never blocks it.
250
+ - A handle the backend refuses is refused before any Organization write. The
251
+ command releases the prepared handle, so the person can correct the handle and
252
+ create. Every other failure keeps the handle, because its Organization may
253
+ already exist.
254
+
255
+ The recovery line names the exact Organization and the safe handle. JSON mode
256
+ writes it as one newline-delimited progress object:
257
+
258
+ ```json
259
+ { "type": "organization.recovery", "organizationId": "O", "handle": "acme" }
260
+ ```
261
+
262
+ `org retry` stays explicit: `--org` (or its alias `--org-id`) is the one write
263
+ scope, and no read default or recovery handle is consulted.
264
+
214
265
  `org retry` requires an explicit `--org` (or `--org-id`). It validates the ID
215
266
  with the public `toOrgId` constructor, reads that exact Organization's lifecycle
216
267
  for its terminal preview, resumes that same durable setup lane, then settles the
@@ -234,7 +285,7 @@ subscription and the browser bridge.
234
285
  | ------------------------------ | ------------------------------------------------------------------------------------------------------------ |
235
286
  | `CAPXUL_CLI_HOME` | Directory for global CLI settings. Defaults to `$XDG_CONFIG_HOME/capxul/cli`, or `$HOME/.config/capxul/cli`. |
236
287
  | `CAPXUL_PUBLISHABLE_KEY` | Optional developer override for the bundled first-party staging key. |
237
- | `CAPXUL_BOOTSTRAP_URL` | Bootstrap origin. Defaults to `https://site.preview.abuusama.dev`. Convex Cloud origins are rejected. |
288
+ | `CAPXUL_BOOTSTRAP_URL` | Bootstrap origin. Defaults to `https://api.staging.capxul.com`. Convex Cloud origins are rejected. |
238
289
  | `CAPXUL_POSTHOG_HOST` | Optional development override for the built-in public PostHog ingestion origin. |
239
290
  | `CAPXUL_POSTHOG_PROJECT_TOKEN` | Optional development override for the built-in public project ingestion token. |
240
291
  | `CAPXUL_TELEMETRY_DISABLED` | Set to `true` to disable remote observation regardless of the saved preference. |
@@ -348,11 +399,21 @@ stored and tagged as `legacy-native-grant` in status. A profile read asks for an
348
399
  explicit new login; it never exchanges the old grant for a broader session.
349
400
  Logout forgets and attempts to revoke both credential types for the selected email.
350
401
 
351
- For a human, `capxul auth login` prompts for email and a hidden OTP. `auth signup`
352
- also prompts for the current Profile fields: display name, two-letter country
353
- code, and handle. The browser opens only when the shared Core onboarding journey
354
- needs Openfort wallet readiness. It shows wallet status only. It has no email,
355
- OTP, Profile, or approval form.
402
+ `capxul auth login` and `capxul auth signup` stay separate commands. On a
403
+ terminal, each command is a wizard. `auth login` asks for the email and a masked
404
+ OTP. It accepts the code as a paste. It retries an invalid code at most three
405
+ times for one request. After sign-in, an incomplete account gets one offer to
406
+ continue setup in the same command. `auth signup` authenticates first, then asks
407
+ for the Profile fields: display name, two-letter country code, and handle. A
408
+ known value is the prompt default, so Enter keeps it.
409
+
410
+ The browser opens only when the shared Core onboarding journey needs Openfort
411
+ wallet readiness. It shows wallet status only. It has no email, OTP, Profile, or
412
+ approval form.
413
+
414
+ Ctrl+C or Ctrl+D at a wizard prompt cancels the command. The command prints no
415
+ success result and exits 130. A step that already finished keeps its result: a
416
+ completed sign-in keeps its session.
356
417
 
357
418
  For an agent, send and verify in separate processes:
358
419
 
@@ -360,7 +421,6 @@ For an agent, send and verify in separate processes:
360
421
  capxul auth send --email "$TEST_EMAIL" --json
361
422
  # Supply the delivered six-digit OTP through stdin, not a command argument.
362
423
  capxul auth verify --email "$TEST_EMAIL" --otp-stdin --json
363
- capxul auth signup --email "$TEST_EMAIL" --display-name "Test Person" --country GH --handle test_person --json
364
424
  capxul auth profile --email "$TEST_EMAIL" --json
365
425
  # A later process uses the same protected CLI home; no new OTP is required.
366
426
  capxul auth profile --email "$TEST_EMAIL" --json
@@ -368,12 +428,13 @@ capxul auth status --email "$TEST_EMAIL" --json
368
428
  capxul auth logout --email "$TEST_EMAIL" --json
369
429
  ```
370
430
 
371
- `--otp-stdin` reads up to 64 bytes, ending at EOF. Pipe from a secret provider or
372
- use input redirection from a protected file. OTPs are never accepted in argv,
373
- persisted in the continuation, or included in output. Non-interactive commands
374
- without the required input refuse with exit 2 instead of prompting.
431
+ A machine run never prompts. `auth login` with `--otp-stdin` sends the OTP and
432
+ verifies one code from stdin. It returns the tagged result
433
+ `setupState: "setup-required"` when the account needs setup. It does not start
434
+ setup work, so sign-in never becomes signup.
375
435
 
376
- A fresh non-interactive signup can do verification and setup in one command:
436
+ A fresh machine signup does verification and setup in one command. State every
437
+ Profile field; a missing field refuses with exit 2:
377
438
 
378
439
  ```sh
379
440
  # Supply only the delivered OTP through stdin.
@@ -381,6 +442,11 @@ capxul auth signup --email "$TEST_EMAIL" --otp-stdin \
381
442
  --display-name "Test Person" --country GH --handle test_person --json
382
443
  ```
383
444
 
445
+ `--otp-stdin` reads up to 64 bytes, ending at EOF. Pipe from a secret provider or
446
+ use input redirection from a protected file. An invalid value refuses with exit 2. A missing `--otp-stdin` refuses with exit 2 before the command starts client
447
+ work. OTPs are never accepted in argv, persisted in the continuation, or included
448
+ in output.
449
+
384
450
  The local page binds to an OS-selected loopback port. A random launch capability
385
451
  is redeemed once and removed from the URL before Openfort starts. The page receives
386
452
  only the authenticated wallet token and encryption session in memory. Closing it
@@ -388,6 +454,29 @@ ends the current wallet attempt. Re-run `auth signup` with the same CLI home to
388
454
  resume the same Profile and Account without another OTP while the backend session
389
455
  remains valid.
390
456
 
457
+ `auth signup` returns only two readiness results. `setupState: "ready"` is a
458
+ personal Account that the Account readiness owner reads as ready and deployed,
459
+ and its data carries the public identifiers: the Profile, the public wallet
460
+ address (`smartAccount.signerAddress`), the personal Smart Account address
461
+ (`smartAccount.smartAccountAddress`), the Account ID
462
+ (`lifecycle.accountId`), and the ready status. Any other state returns the typed
463
+ recoverable result `setupState: "setup-required"`, with the lifecycle, its
464
+ failure code, and the command that resumes the journey. A ready Account starts
465
+ no wallet work, so a retry keeps the one Profile, wallet, Smart Account, and
466
+ Account. An interruption keeps the stored session and stores no code, so the
467
+ next command resumes the same setup.
468
+
469
+ A ready personal Account continues the same journey into Organization creation
470
+ with `capxul org create --name NAME --handle HANDLE --country CC`. The create
471
+ command records the safe recovery handle for that Organization, so an
472
+ interruption or a restart resumes the exact same Organization.
473
+
474
+ The CLI checks `--display-name`, `--country`, and `--handle` before it opens a
475
+ client, so a malformed value refuses with exit 2 and no code is sent. The handle
476
+ check covers the grammar only: a handle that another person holds, and a reserved
477
+ handle, refuse through the identity owner after sign-in. Both refusals name the
478
+ handle, and neither offers verification-code recovery for a Profile problem.
479
+
391
480
  The version 2 `first-party-session` record stores the opaque provider credential
392
481
  in the existing protected plaintext store. Its scope includes the application
393
482
  key, issuer, environment, and email. Each process validates restoration with the