@ornncompute/cli 0.2.24 → 1.0.34

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 (90) hide show
  1. package/README.md +351 -426
  2. package/package.json +12 -6
  3. package/src/admin-capacity-reservations.mjs +305 -0
  4. package/src/admin-command-handlers.mjs +57 -0
  5. package/src/admin-enrollment.mjs +681 -0
  6. package/src/admin-mutations.mjs +187 -0
  7. package/src/admin-node-diagnostics.mjs +412 -0
  8. package/src/admin-node-lifecycle.mjs +905 -0
  9. package/src/admin-shell.mjs +456 -0
  10. package/src/api-client.mjs +81 -28
  11. package/src/atomic-output.mjs +112 -0
  12. package/src/auth-store.mjs +182 -11
  13. package/src/capability-catalog.mjs +7 -0
  14. package/src/catalog-shell.mjs +1363 -0
  15. package/src/cli.mjs +123 -10266
  16. package/src/connect-mode-handlers.mjs +170 -0
  17. package/src/device-auth.mjs +179 -62
  18. package/src/evidence-commands.mjs +1354 -0
  19. package/src/external-bucket-commands.mjs +1374 -0
  20. package/src/gpu-catalog.mjs +21 -0
  21. package/src/identity-file.mjs +28 -0
  22. package/src/interaction-runtime.mjs +310 -0
  23. package/src/kubernetes-commands.mjs +2235 -0
  24. package/src/launch-mode-handlers.mjs +119 -0
  25. package/src/machine-reference.mjs +285 -0
  26. package/src/mount-commands.mjs +1148 -0
  27. package/src/session-commands.mjs +565 -0
  28. package/src/slurm-commands.mjs +274 -0
  29. package/src/startup.mjs +34 -11
  30. package/src/storage-commands.mjs +1164 -0
  31. package/src/update.mjs +172 -24
  32. package/src/vm-commands.mjs +4308 -0
  33. package/src/vpn-secret-output.mjs +150 -0
  34. package/src/wait-runtime.mjs +231 -0
  35. package/vendor/capabilities/capabilities/admin-capacity-reservations.js +96 -0
  36. package/vendor/capabilities/capabilities/admin-enrollment.js +321 -0
  37. package/vendor/capabilities/capabilities/admin-node-diagnostics.js +88 -0
  38. package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +235 -0
  39. package/vendor/capabilities/capabilities/admin.js +89 -0
  40. package/vendor/capabilities/capabilities/cli.js +156 -0
  41. package/vendor/capabilities/capabilities/clusters.js +150 -1
  42. package/vendor/capabilities/capabilities/commerce-market.js +330 -0
  43. package/vendor/capabilities/capabilities/compute.js +522 -0
  44. package/vendor/capabilities/capabilities/evidence.js +145 -0
  45. package/vendor/capabilities/capabilities/external-buckets.js +191 -0
  46. package/vendor/capabilities/capabilities/fleet.js +77 -25
  47. package/vendor/capabilities/capabilities/identity.js +114 -3
  48. package/vendor/capabilities/capabilities/listings.js +141 -144
  49. package/vendor/capabilities/capabilities/market-shared.js +44 -0
  50. package/vendor/capabilities/capabilities/markets.js +449 -0
  51. package/vendor/capabilities/capabilities/mounts.js +176 -0
  52. package/vendor/capabilities/capabilities/networks.js +1264 -0
  53. package/vendor/capabilities/capabilities/observability.js +38 -8
  54. package/vendor/capabilities/capabilities/tokens.js +32 -17
  55. package/vendor/capabilities/capabilities/volumes.js +178 -0
  56. package/vendor/capabilities/capability.js +21 -14
  57. package/vendor/capabilities/cli-catalog.js +67 -0
  58. package/vendor/capabilities/cli-migrations.js +261 -0
  59. package/vendor/capabilities/cli.js +7 -0
  60. package/vendor/capabilities/software-catalog.js +36 -0
  61. package/vendor/capabilities/spec-catalog.js +28 -5
  62. package/vendor/capabilities/supplier-directory.js +20 -0
  63. package/src/catalog-dispatch.mjs +0 -605
  64. package/src/color.mjs +0 -71
  65. package/vendor/capabilities/capabilities/clusters.d.ts +0 -2
  66. package/vendor/capabilities/capabilities/fleet.d.ts +0 -8
  67. package/vendor/capabilities/capabilities/identity.d.ts +0 -3
  68. package/vendor/capabilities/capabilities/listings.d.ts +0 -51
  69. package/vendor/capabilities/capabilities/observability.d.ts +0 -5
  70. package/vendor/capabilities/capabilities/staff-access.d.ts +0 -29
  71. package/vendor/capabilities/capabilities/staff-access.js +0 -278
  72. package/vendor/capabilities/capabilities/staff-commerce.d.ts +0 -160
  73. package/vendor/capabilities/capabilities/staff-commerce.js +0 -689
  74. package/vendor/capabilities/capabilities/staff-fleet.d.ts +0 -140
  75. package/vendor/capabilities/capabilities/staff-fleet.js +0 -538
  76. package/vendor/capabilities/capabilities/staff-gtm.d.ts +0 -142
  77. package/vendor/capabilities/capabilities/staff-gtm.js +0 -521
  78. package/vendor/capabilities/capabilities/staff-shared.d.ts +0 -47
  79. package/vendor/capabilities/capabilities/staff-shared.js +0 -98
  80. package/vendor/capabilities/capabilities/tokens.d.ts +0 -10
  81. package/vendor/capabilities/capabilities/users.d.ts +0 -2
  82. package/vendor/capabilities/capability.d.ts +0 -93
  83. package/vendor/capabilities/catalog.d.ts +0 -3
  84. package/vendor/capabilities/catalog.js +0 -26
  85. package/vendor/capabilities/index.d.ts +0 -16
  86. package/vendor/capabilities/index.js +0 -16
  87. package/vendor/capabilities/names.d.ts +0 -6
  88. package/vendor/capabilities/role.d.ts +0 -6
  89. package/vendor/capabilities/role.js +0 -17
  90. package/vendor/capabilities/spec-catalog.d.ts +0 -78
package/README.md CHANGED
@@ -1,453 +1,378 @@
1
1
  # Ornn CLI
2
2
 
3
- Command-line access for Ornn compute workflows: browse Listings, buy capacity,
4
- bid in Exchange, manage GPU reservations, launch VM or Bare Metal machines,
5
- create Kubernetes or Slurm clusters, manage private networks and storage
6
- volumes, attach SSH keys, SSH into launched machines, watch machine health
7
- metrics, and view billing readouts.
3
+ `@ornncompute/cli` installs the `ornn` command. The CLI is a catalog-backed
4
+ client for customer compute journeys and the explicit staff namespace. It
5
+ sends browser and CLI traffic only through the API gateway.
8
6
 
9
- For the end-user install, browser-login, command, and troubleshooting guide, see
10
- the [`docs/cli.md`](../../docs/cli.md) guide.
7
+ For the customer install and usage guide, see [`docs/cli.md`](../../docs/cli.md).
8
+ The shared capability catalog in `packages/capabilities` is the authority for
9
+ command identity, role visibility, input schemas, help, and resource discovery.
10
+ The CLI imports `@ornn/capabilities/cli`; packaging includes only that entrypoint's
11
+ dependencies, excluding staff commerce and CRM handlers.
11
12
 
12
- ## 0.2.24 storage compatibility update
13
+ For GCS imports, start with the [source-bucket permissions and version-specific CLI guide](https://docs.ornn.com/cli#gcs-imports-and-storage-transfer-service).
14
+ It documents the current CLI 1.x GCS verification limitation. Scoped
15
+ `ornn help external-buckets connect`, `verify`, and `import` help links to the
16
+ same guide.
13
17
 
14
- Version 0.2.24 restores file uploads against the current Ornn API, including
15
- completion and cancellation. Run `ornn update`, then use the existing command:
18
+ ## Install and sign in
19
+
20
+ Node.js 20 or newer is required.
16
21
 
17
22
  ```bash
18
- ornn storage files upload <drive-id> ./data.json --destination datasets/data.json
23
+ npm install -g @ornncompute/cli
24
+ ornn login
25
+ ornn context
26
+ ```
27
+
28
+ `ornn login` uses the browser device flow. A fresh npm install defaults to
29
+ `https://compute.ornn.com` for browser authorization and `https://api.ornn.com`
30
+ for API requests. Use `ORNN_AUTH_BASE_URL` and `ORNN_API_BASE_URL` for explicit
31
+ local or staging endpoints. Login links must use HTTP(S) on the configured
32
+ authentication origin. Use `--no-browser` when the CLI must print the URL instead of opening it. Session and endpoint configuration remains
33
+ in `~/.config/ornn`; the gateway re-derives organization and role scope from the
34
+ bearer on every request.
35
+
36
+ ## Command map
37
+
38
+ The three primary customer journeys are:
39
+
40
+ ```text
41
+ ornn launch # launch VM, Bare Metal, Kubernetes, or Slurm
42
+ ornn connect # derive SSH, kubeconfig, or Slurm-native access
43
+ ornn check # lifecycle, health, reachability, metrics, and logs
44
+ ```
45
+
46
+ Session and platform commands are:
47
+
48
+ ```text
49
+ ornn login
50
+ ornn context
51
+ ornn logout
52
+ ornn status
53
+ ornn version
54
+ ornn update [--major]
55
+ ornn completion <bash|fish|zsh> --format human
56
+ ornn resources
57
+ ```
58
+
59
+ Advanced customer resources are registered under one noun and one verb:
60
+
61
+ ```text
62
+ capacity-offers list | show | relist | update | delist
63
+ reservations list | show | invoices
64
+ fees show
65
+ spot books | book | trades | bid | orders | cancel
66
+ schedules list | show | buy
67
+ offers list | post | accept | cancel
68
+ machines list | show | wait | switch | reboot | reset | metrics | logs
69
+ clusters list | show | wait | eligible-machines | add-node | remove-node | teardown | metrics | logs
70
+ ssh-keys list | add | delete
71
+ ssh-keys assignments list | assign | sync | status
72
+ private-networks list | show | create | update | delete
73
+ vpn-connections list | configure | disconnect
74
+ volumes list | show | create | refresh | clear | delete
75
+ volumes files list | upload | download | delete
76
+ volumes folders delete
77
+ volume-mounts candidates | show | attach | wait | detach
78
+ external-buckets list | show | connect | update-credentials | verify | import | disconnect
79
+ filesystems deploy | show | wait | delete
19
80
  ```
20
81
 
21
- Uploads update the Ornn-managed volume. Connected external source buckets are
22
- not modified.
82
+ `ssh-keys list` uses backend cursors; see [pagination](../../docs/cli.md#advanced-customer-resources).
83
+
84
+ Market commands call one gateway route each and print that route's JSON.
85
+ `capacity-offers` reads Commerce listings (`/commerce/listings`) and relists a
86
+ schedule reservation you hold, or a primary listing you own, as a secondary
87
+ listing with an asking price, its only price: buyers buy its windows at that
88
+ price with no acceptance. `reservations` reads Commerce
89
+ reservations, schedule and spot alike. `spot`, `schedules`, and `offers` call
90
+ Markets (`/v1/markets`): place 1-8 GPU spot bids (one node each), buy a
91
+ secondary window at its asking price (`schedules buy`), post offers on a
92
+ primary listing's schedule, and accept or cancel offers on primaries you own.
93
+ Prices are integer micro-USD per GPU-hour (`1000000` is $1.00). Every write
94
+ reviews its terms and needs default-no consent, or `--yes` with
95
+ `--format json`; writes accept `--idempotency-key`. Payment methods and
96
+ invoices are managed in the web app. Launch consumes already allocated
97
+ capacity; internal reservation lookups remain necessary for access and
98
+ ownership.
99
+
100
+ Only admins can create primary listings or reservations through
101
+ `ornn admin capacity-offers create` and `ornn admin reservations create`.
102
+ They post to the role-aware `POST /commerce/listings` and
103
+ `POST /commerce/reservations` with the admin's own session; Commerce enforces
104
+ the admin role. Both commands retain explicit commercial-term validation and
105
+ default-no human confirmation. A new primary listing reaches the market once
106
+ staff attach its nodes.
107
+
108
+ All staff discovery and execution starts at `ornn admin`. A fresh staff preflight
109
+ runs before the catalog is shown. The seven roots are:
110
+
111
+ ```text
112
+ ornn admin users
113
+ ornn admin suppliers
114
+ ornn admin facilities
115
+ ornn admin nodes
116
+ ornn admin enrollment-tokens
117
+ ornn admin capacity-offers
118
+ ornn admin reservations
119
+ ```
23
120
 
24
- ## Install
121
+ Every `ornn admin` command, read or mutation, requires an admin session.
122
+ `ornn admin nodes --help` lists the authorized node commands. Node health
123
+ returns the node detail object; metrics preserve the owner `tier` and `windows`;
124
+ logs return `data.logs` and an opaque continuation cursor in `page.next_cursor`.
125
+ The cursor preserves the node, stream, count, time window, and owner position;
126
+ pass it unchanged with the same node ID. The human `Next` command includes that
127
+ node ID. Changing filters requires a new first-page request. Legacy raw owner
128
+ cursors require the original `--before` value and filters.
129
+ Metrics and logs use node-scoped staff gateway routes. Exported private keys
130
+ include the final newline required by OpenSSH, both in files and with `--print`.
131
+ `ornn admin nodes enroll` takes optional `--filter COMPARTMENT_IDS`
132
+ (omit to run every compartment step); the retired `--mode` flag is gone. The
133
+ gateway, not CLI metadata, authoritatively enforces the admin role.
134
+ Suppliers are Authorization supplier organizations: `ornn admin suppliers list`
135
+ returns their `id` and `name`, and `--supplier UUID` on `facilities list`,
136
+ `nodes list`, `enrollment-tokens create`, and `nodes enroll` takes that
137
+ organization ID.
138
+
139
+ Token revocation looks up the token by ID, including tokens outside the newest
140
+ 500-row list. Creation-time checks and safe retries still apply.
141
+
142
+ ## Catalog-generated discovery
25
143
 
26
144
  ```bash
27
- curl -fsSL https://compute.ornn.com/cli/install | sh
145
+ ornn
146
+ ornn help
147
+ ornn help machines
148
+ ornn machines --help
149
+ ornn help machines reset
150
+ ornn resources --format json
151
+ ornn completion bash --format human > ~/.local/share/bash-completion/completions/ornn
152
+ ornn admin
28
153
  ```
29
154
 
30
- The installer requires Node.js 20 or newer and npm. It installs `@ornncompute/cli`
31
- globally, exposes the `ornn` binary, adds the npm global bin directory to the
32
- user's shell profile when needed, and records the web browser handoff as
33
- `authBaseUrl` plus the API gateway as `apiBaseUrl` in
34
- `~/.config/ornn/config.json`. The
35
- installer prints a short Ornn Compute welcome banner and next steps; set
36
- `ORNN_INSTALL_BANNER=0` to skip it or `ORNN_INSTALL_ANIMATION=0` to keep it
37
- static.
38
-
39
- `ornn whoami`, `ornn logout`, and `ornn status` call the API gateway's
40
- `/v1/cli/session` and `/v1/cli/status` contracts. The gateway resolves the CLI
41
- bearer itself; it never trusts caller-supplied identity or authorization-admin
42
- headers. Logout asks the gateway to revoke the remote credential, then always
43
- clears the local bearer. If revocation cannot be confirmed, the CLI reports
44
- that the remote credential may remain active. Updated legacy installs that
45
- saved only a deployed web/auth
46
- origin map that known Ornn origin to its API gateway automatically; custom and
47
- localhost combined endpoints are left unchanged.
48
-
49
- ## First machine
155
+ Root help, scoped help, suggestions, and the advanced-resource index are
156
+ rendered from the same catalog bindings used for dispatch. Customer discovery
157
+ never contains admin children. There is no second parser or command registry.
158
+
159
+ ## Interaction contract
160
+
161
+ An eligible human context requires TTY stdin and TTY stdout and no JSON/NDJSON
162
+ format. Human commands may guide selection, render a normalized review, and ask
163
+ default-no `[y/N]` consent. Empty input, EOF, and refusal submit nothing.
164
+
165
+ Automation supplies complete semantic inputs and an explicit format:
50
166
 
51
167
  ```bash
52
- ornn login
53
- ornn listings forecast
54
- ornn buy <listing-id>
55
- # Complete checkout in the browser, then:
56
- ornn gpus list
57
- ornn nodes launch --interactive --wait
58
- ornn nodes list
59
- ornn ssh <machine-hostname>
168
+ ornn status --format json
169
+ ornn machines list --limit 100 --format ndjson
170
+ ornn launch RESERVATION_ID --mode vm --yes \
171
+ --idempotency-key caller-stable-key --format json
60
172
  ```
61
173
 
62
- Use `ornn exchange create --interactive` instead of `ornn buy` to place a bid.
63
- Guided creation is explicit and TTY-only; flag-based commands remain canonical
64
- for scripts.
174
+ Redirected commands require `--format human`, `--format json`, or
175
+ `--format ndjson`. The retired `--json` alias is rejected. Machine mode never
176
+ prompts or launches a browser. Inputs missing for a safe decision fail before
177
+ network, browser, or process I/O.
178
+
179
+ Global interaction modifiers are `--format`, `--guided`, `--yes`, `--wait`,
180
+ `--no-wait`, `--timeout`, `--no-browser`, `--overwrite`, and
181
+ `--idempotency-key`. Mutations that create or increase spend, erase data, tear
182
+ down resources, or reduce access require consent. Machine retries require a
183
+ caller-stable idempotency key and reconcile against durable owner state.
184
+
185
+ Permanent deletion and teardown requests never fire without consent. Private
186
+ networks, detached volumes, filesystem deployments, and Kubernetes or Slurm
187
+ clusters accept `--yes` for automation or ask an eligible human for default-no
188
+ confirmation. Clearing a volume or deleting nested content is live-terminal
189
+ only and always asks, even when `--yes` is present.
190
+
191
+ List commands use bounded `--limit` values and opaque `--cursor` values. Waits
192
+ poll only retryable transitional states, honor the caller deadline and
193
+ cancellation, and return the last observed state on timeout. Durable Bare Metal
194
+ workspace flows persist local recovery pointers for `launch --resume`.
195
+ Browser handoff is limited to login and organization authorization. Secret
196
+ bytes are written only by an explicit export command.
197
+
198
+ Human waits report throttled progress on stderr; NDJSON waits emit versioned
199
+ progress records, and JSON stays a single terminal envelope.
200
+
201
+ Eligible human output uses color when the output stream supports it.
202
+ `NO_COLOR` (including an empty value), `FORCE_COLOR`, and the global
203
+ `--no-color` flag are respected. JSON and NDJSON never contain ANSI escapes.
204
+
205
+ Exact unique machine hostnames are accepted anywhere a machine reference is
206
+ advertised, including JSON and NDJSON. The CLI resolves them through the
207
+ bounded owned-machine list and sends only the canonical machine ID to the
208
+ machine owner route. Bare `connect` discovers VM, Bare Metal,
209
+ Kubernetes, and Slurm targets before making one safe-fact choice across the
210
+ combined set. An unresolved target fails with
211
+ `connect_target_not_found` before any private-network or VPN setup.
212
+ `connect --print` renders a native direct-access command; raw
213
+ secret `--print` rejects every explicit `--format`. Direct human `connect`
214
+ announces the native command and explains that Ctrl-C ends only local SSH while
215
+ the remote machine keeps running before it starts the session. Human metrics
216
+ and logs output includes returned sample rows, not only source availability.
217
+
218
+ ## Machine output and exit status
219
+
220
+ JSON and NDJSON use schema `ornn.cli/v1`. A terminal record contains:
221
+
222
+ ```json
223
+ {
224
+ "schema": "ornn.cli/v1",
225
+ "type": "result",
226
+ "command": "machines show",
227
+ "outcome": { "class": "ready", "phase": "ready" },
228
+ "data": {},
229
+ "action": null,
230
+ "page": null,
231
+ "errors": [],
232
+ "resume": null
233
+ }
234
+ ```
65
235
 
66
- ## Commands
236
+ NDJSON emits zero or more progress records and exactly one terminal result or
237
+ error record. Progress is additive and contains no secret or supplier identity.
238
+
239
+ | Exit | Meaning |
240
+ | ---: | ------------------------------------------------- |
241
+ | 0 | Requested terminal goal reached |
242
+ | 1 | Failed, declined, or terminal negative outcome |
243
+ | 2 | Usage or validation error |
244
+ | 3 | Durable external action is required |
245
+ | 4 | Useful partial result with explicit source errors |
246
+ | 5 | Authentication or authorization failure |
247
+ | 6 | Service unavailable or retryable owner failure |
248
+ | 124 | Deadline expired; last observed state returned |
249
+ | 130 | Interrupted |
250
+
251
+ ## Migrating to vNext
252
+
253
+ vNext is a clean cutover. Retired forms are never aliases: each fails before I/O
254
+ with one replacement and <https://docs.ornn.com/cli#migrating-to-vnext>.
255
+
256
+ | Retired form | Replacement |
257
+ | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
258
+ | `ornn account`, `ornn whoami` | `ornn context` |
259
+ | `ornn catalog search`, `gpu-types`, `availability *`, `listing *`, `listings` read leaves | matching `ornn capacity-offers` leaf |
260
+ | `ornn listings create` | `ornn admin capacity-offers create` |
261
+ | `ornn buy` | Use the Ornn web app. |
262
+ | `ornn bid create`, `exchange create` | Use the Ornn web app. |
263
+ | `ornn bid` or `exchange` list, show, update, withdraw | Use the Ornn web app. |
264
+ | `ornn gpu` or `gpus` list, show | Use the Ornn web app. |
265
+ | `ornn gpu` or `gpus` checkout, `reservations checkout` | Use the Ornn web app. |
266
+ | `ornn nodes launch` | `ornn launch` |
267
+ | `ornn nodes` list, show, wait, switch, reboot, hard-reset | matching `ornn machines` leaf; reset needs erase flag |
268
+ | `ornn ssh`, `nodes ssh-command` | `ornn connect` |
269
+ | `ornn metrics`, `telemetry`, `logs` | `ornn check`, `machines metrics`, or `machines logs` |
270
+ | `ornn clusters create`, `kubernetes launch`, `slurm launch` | `ornn launch --mode kubernetes` or `ornn launch --mode slurm` |
271
+ | Kubernetes or Slurm status, credentials, SSH, teardown | `ornn clusters show`, `connect`, or `clusters teardown` |
272
+ | `ornn network *`, `networks *` | `ornn private-networks <verb>` |
273
+ | `ornn access *`, `keys` | exact `ornn machines` or `ornn ssh-keys` leaf printed |
274
+ | `ornn storage volumes *` | `ornn volumes <verb>` |
275
+ | `ornn storage files *` | `ornn volumes files <verb>` |
276
+ | `ornn storage buckets *` | `ornn external-buckets <verb>` |
277
+ | Storage targets, deploy, status, detach, filesystem | exact `ornn volume-mounts` or `ornn filesystems` leaf printed |
278
+ | `ornn billing` | Use the Ornn web app. |
279
+ | customer-root `facilities`, `tokens`, `users`, `node`, or staff `reservations *` | exact `ornn admin ...` command printed by the error |
280
+ | `ornn api`, `commerce`, `orchestrator`, `cache purge` | `ornn resources`; no generic replacement exists |
281
+ | `--json` | `--format json` |
282
+ | `--interactive` | `--guided` |
283
+
284
+ Changed behavior is intentional: waits are deadline-bound, consent is semantic
285
+ and default-no, pagination is bounded and cursor-based, machine output is always
286
+ enveloped, and exit statuses are semantic. Old help, completion entries,
287
+ fixtures, staff roots, and owner-route spellings are not shipped.
288
+
289
+ `0.2.10` is the configured final legacy release (`legacyVersion`, dated
290
+ `2026-09-04T00:00:00Z`). The configured vNext artifact is `@ornncompute/cli`
291
+ at the version in `packages/config/cli-release.json` `vnextVersion`, on the
292
+ same binary and Node 20 minimum; `minimumVersion` for legacy tombstones
293
+ remains `1.0.0`. Publication is allowed as soon as release validation and
294
+ approvals pass; npm `latest` selects the approved production release. The
295
+ legacy support schedule remains anchored to `2026-10-05T00:00:00Z`, after
296
+ the required 30-day migration-notice interval. That date does not block npm
297
+ publication.
298
+
299
+ `ornn update` stays within the installed major. Crossing into vNext requires
300
+ `ornn update --major`. Through day 90 (ending immediately before
301
+ `2027-01-04T00:00:00Z`), rollback is available by reinstalling the pinned final
302
+ legacy package:
67
303
 
68
304
  ```bash
69
- ornn help [command]
70
- ornn login [--auth-base <url>] [--no-browser] [--timeout <seconds>]
71
- ornn update
72
- ornn whoami [--json]
73
- ornn status [--json]
74
- ornn listings list [--gpu-type <type>] [--facility <name>] [--json]
75
- ornn listings forecast [--limit <1-500>] [--cursor <opaque>] [--json]
76
- ornn listings show <listing-id> [--open] [--json]
77
- ornn listings create [--gpu-type <type>] [--node-count <n>] [--yes] [--json]
78
- ornn buy <listing-id> [--no-open] [--json]
79
- ornn exchange create <listing-id> --node-count <n> [--min-node-count <n>] --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd> [--no-open] [--json]
80
- ornn exchange create [<listing-id>] --interactive [--node-count <n>] [--min-node-count <n>] [--start-date <yyyy-mm-dd>] [--end-date <yyyy-mm-dd>] [--price <usd>] [--no-open]
81
- ornn exchange list [--limit <1-500>] [--cursor <cursor>] [--json]
82
- ornn exchange show <exchange-id> [--open] [--json]
83
- ornn exchange update <exchange-id> --node-count <n> --min-node-count <n> --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd>
84
- ornn exchange withdraw <exchange-id>
85
-
86
- Bid create/update prefer `--node-count` and `--min-node-count`. Legacy
87
- `--gpu-count` and `--min-gpu-count` remain available; they convert using the
88
- listing's GPUs per node before the gateway translates the request to the
89
- Commerce bid contract.
90
-
91
- ornn gpus list [--status <status>] [--limit <1-500>] [--cursor <cursor>] [--json]
92
- ornn gpus show <gpu-id> [--open] [--json]
93
- ornn gpus checkout <gpu-id> [--no-open] [--json]
94
- ornn nodes list [--json]
95
- ornn nodes show <node-id-or-hostname> [--json]
96
- ornn nodes launch <reservation-id> --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--network public|private] [--storage-load-drive-id <id>] [--storage-save-drive-id <id>] [--wait] [--json]
97
- ornn nodes launch [<reservation-id>] --interactive [--key <path|id|label>] [--mode bare-metal|vm] [--username <name>] [--network public|private] [--storage-load-drive-id <id>] [--storage-save-drive-id <id>] [--wait]
98
- ornn nodes switch <reservation-id> --network public|private --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--wait] [--json]
99
- ornn nodes wait <node-or-reservation-id-or-hostname> [--timeout <seconds>] [--json]
100
- ornn nodes reboot <node-id> [--json]
101
- ornn nodes hard-reset <node-id> [--json]
102
- ornn nodes ssh-command <node-or-reservation-id-or-hostname> [--json]
103
- ornn nodes keys attach <node-id> --key <path|id|label> [--json]
104
- ornn nodes keys list <node-id> [--json]
105
- ornn node health <node-id> [--json]
106
- ornn node diagnose <node-id> [--json]
107
- ornn node list [--operator <id-or-slug>] [--facility <id>] [--email <email>] [--json]
108
- ornn node reboot <node-id> [--json]
109
- ornn node hard-reset <node-id> [--json]
110
- ornn node off-grid <node-id> [--reason <text>] [--yes] [--json]
111
- ornn node on-grid <node-id> [--yes] [--json]
112
- ornn node exec <node-id> --command <shell> --timeout-seconds <n> [--json]
113
- ornn node terminate <node-id> [--reason <text>] [--force] [--yes] [--json]
114
- ornn node admin-key <node-id> [--generate] [--json]
115
- ornn reservations commerce list --tenant <email-or-id> [--listing <listing-id>] [--json]
116
- ornn reservations commerce create --tenant <email> --listing <listing-id> [--node-count <n>] [--node <node-id>] [--start-at <timestamp>] [--end-at <timestamp>] [--price-per-gpu-hour <rate>] [--json]
117
- ornn reservations deploy <node-id> --target-tenant <id> --commerce-reservation <id> [--target-user <id>] [--network public|private] [--json]
118
- ornn ssh <node-or-reservation-id-or-hostname> [--print] [--identity-file <path>] [--user <name>] [--json]
119
- ornn metrics nodes [--json]
120
- ornn metrics node <node-id-or-hostname> [--json]
121
- ornn metrics history <node-id-or-hostname> [--start <iso>] [--end <iso>] [--max-points <n>] [--json]
122
- ornn metrics watch <node-id-or-hostname> [--interval <seconds>] [--count <n>] [--timeout <seconds>] [--json]
123
- ornn clusters list [--json]
124
- ornn clusters reservations [--json]
125
- ornn clusters eligible-nodes <reservation-id> [--type kubernetes|slurm] [--network public|private] [--json]
126
- ornn clusters create <reservation-id> --type kubernetes|slurm [--network public|private] [--node <node-id>] [--node-count <n>] [--wait] [--json]
127
- ornn clusters create [<reservation-id>] --interactive [--type kubernetes|slurm] [--network public|private] [--node <node-id>] [--node-count <n>] [--wait]
128
- ornn clusters show <reservation-id> [--type kubernetes|slurm] [--json]
129
- ornn clusters wait <reservation-id> [--type kubernetes|slurm] [--timeout <seconds>] [--json]
130
- ornn clusters credentials <reservation-id> [--type kubernetes|slurm] [--json]
131
- ornn clusters kubeconfig <reservation-id> [--output <path>] [--json]
132
- ornn clusters ssh-command <reservation-id> [--identity-file <path>] [--user <name>] [--json]
133
- ornn clusters ssh <reservation-id> [--print] [--identity-file <path>] [--user <name>] [--json]
134
- ornn clusters add-node <reservation-id> --node <node-id> [--json]
135
- ornn clusters remove-node <reservation-id> --node <node-id> [--json]
136
- ornn clusters teardown <reservation-id> [--yes] [--type kubernetes|slurm] [--json]
137
- ornn slurm launch <reservation-id> [--network public|private] [--node <node-id>] [--node-count <n>] [--wait] [--wait-timeout <seconds>] [--json]
138
- ornn slurm teardown <reservation-id> [--yes] [--json]
139
- ornn slurm status <reservation-id> [--json]
140
- ornn slurm credentials <reservation-id> [--json]
141
- ornn slurm ssh <reservation-id> [--print] [--identity-file <path>] [--user <name>] [--json]
142
- ornn kubernetes launch <reservation-id> [--network public|private] [--node <node-id>] [--node-count <n>] [--wait] [--wait-timeout <seconds>] [--json]
143
- ornn kubernetes teardown <reservation-id> [--yes] [--json]
144
- ornn kubernetes status <reservation-id> [--json]
145
- ornn kubernetes credentials <reservation-id> [--json]
146
- ornn kubernetes kubeconfig <reservation-id> [--output <path>] [--json]
147
- ornn networks list [--json]
148
- ornn networks show <network-id> [--json]
149
- ornn networks create --name <name> [--cidr <cidr>] [--description <text>] [--json]
150
- ornn networks update <network-id> [--name <name>] [--description <text>] [--clear-description] [--json]
151
- ornn networks delete <network-id> [--yes] [--json]
152
- ornn storage volumes list [--json]
153
- ornn storage volumes show <drive-id> [--json]
154
- ornn storage volumes create --name <name> [--source <drive-id>] [--json]
155
- ornn storage volumes refresh <drive-id> [--json]
156
- ornn storage volumes clear <drive-id> [--yes] [--json]
157
- ornn storage volumes delete <drive-id> [--yes] [--json]
158
- ornn storage files ls <drive-id> [--prefix <path>] [--json]
159
- ornn storage files upload <drive-id> <local-file> [--destination <path>] [--content-type <type>] [--json]
160
- ornn storage files download <drive-id> <remote-path> [--output <path>] [--json]
161
- ornn storage targets [--json]
162
- ornn storage deploy <drive-id> --reservation <reservation-id> [--all-nodes] [--read-only|--read-write] [--json]
163
- ornn storage status --reservation <reservation-id> [--watch] [--interval <seconds>] [--timeout <seconds>] [--json]
164
- ornn storage detach --reservation <reservation-id> [--json]
165
- ornn storage buckets list [--json]
166
- ornn storage buckets show <drive-id> [--json]
167
- ornn storage buckets connect gcs|s3|r2 --bucket <bucket>|--url <url> [--name <name>] [--prefix <prefix>] [--region <region>] [--account-id <id>|--endpoint-url <url>] [--access-key-id <id> --secret-access-key-file <path>] [--read-only|--read-write] [--verify] [--json]
168
- ornn storage buckets update-credentials <drive-id> --access-key-id <id> --secret-access-key-file <path> [--json]
169
- ornn storage buckets verify <drive-id> [--json]
170
- ornn storage buckets disconnect <drive-id> [--json]
171
- ornn storage filesystem deploy --reservation <reservation-id> [--performance-tier <tier>] [--capacity-gib <gib>] [--json]
172
- ornn storage filesystem status --reservation <reservation-id> [--json]
173
- ornn storage filesystem delete --reservation <reservation-id> [--yes] [--json]
174
- ornn telemetry latest <node-id> [--span 15m] [--start <iso>] [--end <iso>] [--max-points <n>] [--json]
175
- ornn telemetry tail <node-id> [--duration <seconds>] [--json]
176
- ornn logs latest <node-id> [--stream kernel] [--count <n>] [--before <iso>] [--cursor <token>] [--json]
177
- ornn logs tail <node-id> [--stream kernel] [--duration <seconds>] [--json]
178
- ornn users query [--name <name>] [--email <email>] [--organization <name>] [--max <n>]
179
- ornn keys list [--json]
180
- ornn keys add [<public-key-file>] --label <label> [--public-key <key>] [--json]
181
- ornn keys delete <key-id> [--json]
182
- ornn access show <reservation-id> [--json]
183
- ornn access activate <reservation-id> --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--network public|private] [--storage-load-drive-id <id>] [--storage-save-drive-id <id>] [--wait] [--no-open] [--json]
184
- ornn access switch <reservation-id> --network public|private --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--wait] [--json]
185
- ornn access push-keys <reservation-id> --ssh-key-id <id> [--json]
186
- ornn access keys list <reservation-id> [--json]
187
- ornn access keys add <reservation-id> --public-key <key> --label <label> [--json]
188
- ornn access keys add <reservation-id> --public-key-file <path> --label <label> [--json]
189
- ornn access keys push <reservation-id> --ssh-key-id <id> [--json]
190
- ornn access keys status <reservation-id> [--json]
191
- ornn ssh-keys list [--json]
192
- ornn ssh-keys add --public-key <key> --label <label> [--json]
193
- ornn ssh-keys add --public-key-file <path> --label <label> [--json]
194
- ornn ssh-keys delete <key-id> [--json]
195
- ornn billing summary [--json]
196
- ornn billing invoices [--limit <1-500>] [--cursor <opaque>] [--json]
197
- ornn billing showback --start <yyyy-mm-dd> --end <yyyy-mm-dd> [--json]
198
- ornn billing open [--no-open] [--json]
199
- ornn api <get|post|patch|put|delete> <allowlisted-path> [--data <json>] [--raw]
200
- ornn logout
305
+ npm install -g @ornncompute/cli@0.2.10
201
306
  ```
202
307
 
203
- `ornn access keys add` is safe before or after launch. When the reservation has
204
- active VM or Bare Metal machines, adding the key automatically queues the
205
- current user's complete reservation key set on those machines. Use
206
- `ornn access keys push` to explicitly re-sync keys that are already attached.
207
-
208
- `ornn storage status` prints reconciled object and byte progress once the
209
- managed transfer has reported progress, plus the number of target nodes that
210
- have acknowledged the mount. Internal placement bucket details are not shown.
211
- AWS S3 and external GCS sources use the managed transfer path. Cloudflare R2
212
- buckets can be connected and verified, but deployment support is coming soon.
213
- The mount path is always `/home/tenant/volume`; node agents resolve `tenant` to the
214
- machine's real Linux user at mount time.
215
-
216
- `ornn storage status --watch` polls the same status endpoint on an interval
217
- (10 seconds by default) instead of returning after a single check, re-printing
218
- the human summary on each poll. It exits 0 once the attachment is attached and
219
- every scoped node has mounted, exits 1 with an error on stderr if the
220
- attachment detaches before that happens, and exits 1 with a timeout message on
221
- stderr after 1800 seconds (or the value passed to `--timeout`) without
222
- success. Use `--interval <seconds>` to change the poll cadence. `--interval`
223
- and `--timeout` require `--watch`. Combined with `--json`, only a single JSON
224
- payload is printed, at the end, instead of a stream of per-poll output.
225
-
226
- `ornn storage detach` detaches the drive from the reservation's storage
227
- attachment. Detach is origin-aware: if your reservation individually joined a
228
- drive that another reservation already had attached, detach releases only
229
- your reservation's own mount and leaves the rest of the attachment alone. If
230
- your reservation started the attachment, or it is the last member still
231
- joined, detach flushes and unmounts every node before releasing the whole
232
- attachment. A node that fails to unmount is left in a retryable state with
233
- the reported error; run `ornn storage detach` again with the same
234
- `--reservation` to retry it. A reservation that detached from a shared drive
235
- can rejoin it later by running `ornn storage deploy` again. Mounted state is
236
- tracked per node, not by attachment membership, so `ornn storage status`
237
- can show one node as unmounted while the rest of the attachment
238
- stays mounted.
239
-
240
- `ornn storage files upload` adds a file to the drive's current colocated copy.
241
- You can upload while a direct FUSE mount is active; every mounted node sees the
242
- file on its next lookup without a remount. A direct FUSE drive attaches to one
243
- reservation by default; pass `--all-nodes` on `ornn storage deploy` to fan the
244
- same mount out across every compatible node in the node group. Avoid writing
245
- the same file path concurrently from multiple nodes because object storage is
246
- not a POSIX shared filesystem.
247
-
248
- `ornn storage files download` streams a single object from the drive straight
249
- to disk. Pass `--output <path>` to control where it's written; without it, the
250
- file is saved under the remote path's basename in the current directory.
251
-
252
- For a connected bucket, deploy once before uploading. The first deploy imports
253
- the source into an Ornn-managed colocated working copy. That copy remains the
254
- drive's durable data when you unmount, detach, or mount it elsewhere. Ornn
255
- does not write changes back to the original connected bucket.
256
-
257
- UI aliases are first-class in the CLI: `listings` maps to the older
258
- `availability` command, `exchange` maps to `bid`, `gpus` maps to
259
- `reservations`. The older command names remain available for scripts.
260
- Bid and reservation list commands return a bounded page (500 rows by default);
261
- use `--limit`, `--json`, and the response's opaque `next_cursor` to traverse
262
- older history. Replay that cursor exactly; it is not an item ID. `show` and `checkout`
263
- use exact tenant-owned item lookups, so they are not limited to the current page.
264
-
265
- `listings forecast` is a Commerce-owned view of the next 48 one-hour
266
- availability windows. It includes capacity that is unavailable now but frees
267
- up during the horizon. The CLI makes one gateway request; it does not probe
268
- each hour independently.
269
-
270
- `exchange create`, `nodes launch`, and `clusters create` accept
271
- `--interactive`. Supplied flags prefill the guided answers. The mode requires
272
- TTY stdin and stdout, rejects `--json`, prints the complete request, and
273
- submits only after an explicit default-no confirmation.
274
-
275
- Machine UUIDs remain canonical. `ornn ssh`, `nodes show`, `nodes wait`, and
276
- tenant metrics also accept a case-insensitive exact hostname when it uniquely
277
- matches one active machine; ambiguous hostnames fail and print the matching
278
- full IDs.
279
-
280
- ## Operator commands
281
-
282
- The `ornn node` commands are for Ornn operators and reviewers, not tenants. They
283
- wrap internal-reviewer-gated endpoints. Run `ornn login` as an
284
- internal-allowed staff user. The CLI calls `/v1/cli/operator/*`; the gateway
285
- resolves the user bearer and applies staff authorization without downloading a
286
- review or service secret to the laptop. There is no direct-service break-glass
287
- path.
288
-
289
- - `ornn node health <node-id>` shows launch readiness (ready/blocked plus
290
- reasons), passive fault reasons, and the last validation status.
291
- - `ornn node diagnose <node-id>` queues a manual node validation test.
292
- - `ornn node list [--operator <id-or-slug>] [--facility <id>] [--email <email>]` lists GPU nodes.
293
- Orchestrator applies facility id and an operator UUID. Non-UUID `--operator`
294
- slugs and `--email` are forwarded today and do not filter the fleet.
295
- - `ornn node reboot <node-id>` queues an OS reboot of the node's resolved
296
- instance (its host for bare-metal, its VM for a virtual-machine instance id;
297
- storage and SSH keys preserved).
298
- - `ornn node hard-reset <node-id>` wipes tenant storage/users and reboots, then
299
- re-pushes the tenant's keys on reconnect. The tenant keeps ownership of the
300
- instance.
301
- - `ornn node off-grid <node-id> [--reason <text>] [--yes]` takes a node off-grid
302
- (remove Ornn agent management, leave the host powered on). Asks y/N unless `--yes`.
303
- - `ornn node on-grid <node-id> [--yes]` re-enrolls an off-grid host: orchestrator
304
- SSHs with the stored admin key and re-runs the installer. Asks y/N unless `--yes`.
305
- - `ornn node exec <node-id> --command <shell> --timeout-seconds <n>` runs
306
- one unrestricted command over orchestrator SSH with the stored admin key. Not
307
- an interactive shell (`ornn ssh`). Runs immediately; no y/N.
308
- - `ornn node terminate <node-id> [--reason <text>] [--force] [--yes]` best-effort
309
- cleans the host, removes the Ornn agent, and hard-deletes the node record.
310
- It does not return the host to a tenant. Asks y/N unless `--yes`. There is no
311
- `deenroll` verb; use terminate.
312
- - `ornn node admin-key <node-id> [--generate]` prints the Ornn admin SSH keypair
313
- for the node (including the private key) so an operator can SSH into the host.
314
- `--generate` always mints a new pair, stores it, and installs the public key
315
- on the live host. Treat the output as a secret.
316
-
317
- The operator resource commands share the same reviewer auth:
318
-
319
- - `ornn operator list [--json]` lists operators from the capabilities
320
- catalog (staff). Distinct from `ornn operators list`.
321
- - `ornn operators list` lists enrolled provisioning operators
322
- (`GET /provisioning/operators`).
323
- - `ornn facilities list [--operator <id-or-slug>]` lists facilities, optionally
324
- filtered to one operator.
325
- - `ornn tokens list` lists enrollment tokens.
326
- - `ornn tokens create --operator <id> [--facility <id>]
327
- [--expires-in <seconds>] [--ip <addr>] [--host <ip>]
328
- [--identity-file <path>] [--yes]` mints an enrollment token and prints a
329
- `curl … | sudo bash` install command. With `--host` and `--identity-file`,
330
- orchestrator SSHs and runs that curl (same as Bulk Enroll). Asks y/N unless `--yes`.
331
- - `ornn tokens revoke <token-id>` revokes an enrollment token.
332
-
333
- Staff Commerce reservations are listing-backed, not fleet-backed:
334
-
335
- - `reservations commerce create --tenant <email> --listing <listing-id>
336
- [--node-count <n>] [--node <node-id>]` creates and activates the tenant's
337
- Commerce reservation. Node count defaults to the listing capacity; start,
338
- end, and hourly rate default from the listing. Optional `--node` values pin
339
- specific catalog ids. Start and end overrides must remain inside the
340
- listing's allowed window; the hourly rate can also be overridden explicitly.
341
- - `reservations commerce list --tenant <email-or-id> [--listing <listing-id>]`
342
- lists active reservations in their live window, optionally filtered to one
343
- listing.
344
-
345
- Reservation lifecycle verbs also run under the operator surface:
346
-
347
- - `ornn reservations commerce create|list` creates or discovers a validated
348
- Commerce reservation from a listing. These actions require a staff
349
- `ornn login` session; the gateway `/v1/cli/operator/*` allowlist enforces
350
- staff authorization — there is no review-secret break-glass that bypasses
351
- that gate.
352
- - `ornn reservations transfer <reservation-id> --target-tenant <id>
353
- [--target-user <id>] [--node <id>] [--strategy reject|park] [--confirm]`
354
- transfers a reservation to another tenant.
355
- - `ornn reservations deploy <node-id> --target-tenant <id>
356
- --commerce-reservation <id> [--target-user <id>] [--network public|private]`
357
- deploys one node only after the gateway operator contract verifies that the
358
- live tenant-owned Commerce reservation and listing match that node.
359
-
360
- The tenant `ornn reservations list|show|checkout` verbs use the tenant CLI
361
- login and `/v1/cli/compute` gateway contract. Staff Commerce actions use the
362
- gateway operator contract; `transfer|deploy` retain the operator path above.
363
-
364
- Staff happy path:
365
-
366
- - `ORNN_AUTH_BASE_URL` — web/browser handoff origin
367
- - `ORNN_API_BASE_URL` — API gateway origin
368
- - `ornn login` as a user allowed by `INTERNAL_ALLOWED_*` on that environment
369
-
370
- Optional installer gateway base for `ornn tokens create` install one-liners:
371
-
372
- - `ORNN_INSTALLER_URL` - base serving `enrollment/install` (for deployed
373
- gateways, `https://<gateway>/v1/orchestrator`), falling back to
374
- `NEXT_PUBLIC_INSTALLER_URL`. Unset prints the token without an install command.
375
-
376
- Without a staff login session, operator commands fail with a clear error before
377
- making a network request.
378
-
379
- Commands print concise human-readable output by default. Customer list
380
- commands use aligned tables when stdout is a TTY and retain their existing
381
- line-oriented shape when piped or redirected. Use `--json` on
382
- read/show/list commands and transaction handoffs for the supported structured
383
- stdout contract. JSON never contains tables, progress, next-step hints, color,
384
- or ANSI sequences. Errors and login/browser progress go to stderr. Under
385
- `--json` an error is written to stderr as one object, `{"error": "<message>",
386
- "status": <http-status>}` (`status` only when the API supplied one); stdout
387
- stays empty and the exit code is unchanged.
388
-
389
- `ornn login` opens a browser to the Ornn auth origin, lets the user sign in
390
- with the normal web account flow, and then completes automatically in the
391
- terminal once the browser session approves the CLI device request. If the CLI
392
- cannot open a browser, copy the printed URL into any browser and sign in there;
393
- the terminal keeps polling until the login is approved or expires.
394
-
395
- Run `ornn --help` for the full command list and `ornn api` for the
396
- allowlisted gateway API escape hatch.
397
-
398
- WireGuard client configs use the current tenant-scoped `/nodes` routes:
308
+ Both directions reuse valid `auth.json`, `config.json`, and
309
+ `update-check.json`. `selectedOrganizationId` is an untrusted hint; the gateway
310
+ revalidates membership. Neither direction rewrites credentials or configured
311
+ endpoints. Rollback is unsupported from day 91. From day 91 through day 180,
312
+ legacy compatibility calls return a non-forwarding `426 Upgrade Required`
313
+ tombstone with `cli_version_unsupported`, minimum version `1.0.0`, and the
314
+ migration URL. The legacy route surface is absent from day 181
315
+ (`2027-04-04T00:00:00Z`).
316
+
317
+ `ornn --version` and `ornn -v` print the semantic package version. `ornn
318
+ version` also reports machine schema and update channel.
319
+
320
+ ## Development
321
+
322
+ The exported `run(argv, io)` seam accepts injected streams, fetch, browser,
323
+ process, clock, sleep, and cancellation dependencies. The packaged binary uses
324
+ the same seam. Capability code preserves existing MCP and Slack identities;
325
+ only canonical `cli.vnext` bindings are dispatchable by the CLI.
326
+
327
+ ### Packaged journey and release evidence
328
+
329
+ The permanent package gate vendors the capability catalog, creates one npm
330
+ archive, installs that exact archive under a clean temporary prefix, and tests
331
+ only its installed `ornn` entrypoint against a deterministic loopback gateway:
399
332
 
400
333
  ```bash
401
- ornn api get /nodes/reservations/<reservation-id>/vpn/peers --raw
402
- ornn api post /nodes/reservations/<reservation-id>/vpn/peers \
403
- --data '{"public_key":"<wireguard-public-key>","label":"Laptop"}' --raw
404
- ornn api delete /nodes/reservations/<reservation-id>/vpn/peers/<peer-id> --raw
334
+ rm -rf /tmp/ornn-vnext-artifacts
335
+ mkdir -p /tmp/ornn-vnext-artifacts
336
+ npm run acceptance:packaged --workspace @ornncompute/cli -- \
337
+ --artifact-dir /tmp/ornn-vnext-artifacts \
338
+ --evidence /tmp/ornn-vnext-packaged-gate.json
405
339
  ```
406
340
 
407
- The legacy `/standalone-vms/*` prefix is not exposed through the gateway
408
- `/v1/cli/*` allowlist.
409
- Deleting a peer is the supported way to replace its key; switching a node
410
- between Public and Private VPN preserves the peer.
411
-
412
- ## Updating
413
-
414
- Interactive global installations check for new releases in the background,
415
- using a daily interval. When a newer release has been discovered, Ornn
416
- installs it before your next eligible command and then runs that command
417
- with the updated CLI. The first check has a one-day grace period.
418
-
419
- Automatic updates are skipped in CI, with redirected input or output,
420
- for machine-readable output, and for help or version commands. Project
421
- dependencies, development checkouts, and package-runner invocations do
422
- not update automatically. Run `ornn update` to check and update immediately.
423
-
424
- If an installation fails, Ornn continues only when it can verify that
425
- the remaining CLI loads successfully. Otherwise it prints reinstall
426
- instructions. If another update is running, retry after it finishes.
427
-
428
- Updates publish an initialized `update-install-*.lock` directory in the Ornn
429
- config directory. Its unique owner file prevents competing processes from
430
- removing a replacement lock during recovery or release. Directory locks from
431
- processes that exit before installation are reclaimed on the next update
432
- attempt; live or inaccessible PIDs and malformed metadata remain locked. Legacy regular-file locks require
433
- manual cleanup after confirming that no updater is running: deleting them
434
- automatically could remove a live lock created by an older CLI. PID reuse can
435
- also require manual cleanup. An installation marker keeps the lock held if the
436
- CLI is killed during installation, because its package installer may still be
437
- running. Confirm that installer has stopped before removing the lock. Repeated
438
- Ctrl+C or SIGTERM releases the lock after installer teardown. An interrupted
439
- package installation may still require reinstalling the CLI if the package
440
- manager has already removed the previous version.
441
-
442
- On POSIX, SIGHUP and SIGQUIT are forwarded to the package installer so it can
443
- exit before the update lock is released.
444
-
445
- ## Deployment
446
-
447
- `deploy-cli-pipeline.yml` publishes `@ornncompute/cli` from `main`. Staging
448
- publishes the package.json version to the npm `next` dist-tag; production then
449
- promotes that same version to `latest`. Manual rolls use
450
- `deploy-cli-service.yml`. Runtime changes under `apps/cli` or
451
- `packages/capabilities` must bump `apps/cli/package.json` so npm receives a
452
- new release. Re-running the pipeline is idempotent when that version is
453
- already published.
341
+ The real gateway smoke and unassisted participant pass are separate release
342
+ evidence; the deterministic fixture must never be presented as either one.
343
+ The participant recorder installs the retained archive itself and owns the
344
+ interactive shell used for the journey, with that installation first in
345
+ `PATH`; it does not attest a session run in another terminal.
346
+ Production and shared staging are refused by the smoke runner. See
347
+ [`docs/packaged-vnext-release-gate.md`](docs/packaged-vnext-release-gate.md) for
348
+ the non-production inputs, redacted evidence schemas, participant checklist,
349
+ pass criteria, and exact commands.
350
+
351
+ Private networks and VPN peers belong to the selected organization. There is no
352
+ per-reservation network attachment step. Durable Bare Metal workspaces use
353
+ `--network shared --volume <volume-id> --mount-access read-only|read-write`;
354
+ private Kubernetes and Slurm launches continue to use `--network private`.
355
+
356
+ ### Storage list pages
357
+
358
+ Ornn CLI 1.0.22 and later request storage lists one page at a time.
359
+ `ornn volumes list` and `ornn external-buckets list` accept `--limit 1` through
360
+ `--limit 100` (default 25), ordered by last updated. Pass the returned
361
+ `page.next_cursor` to `--cursor` for the next page; null means the end.
362
+ Refresh from the first page after changes. Older CLI versions receive an
363
+ upgrade error for storage lists. File-list pagination is unchanged.
364
+
365
+ ### Reliable retries and discovery
366
+
367
+ CLI 1.0.28 forwards staff facility/node `--cursor` and `--limit` to the owner
368
+ and preserves filters in the printed next-page command. A repeated owner cursor
369
+ fails explicitly. Volume mount discovery uses the authenticated
370
+ `/v1/orchestrator/storage-targets` route.
371
+
372
+ File uploads include a SHA-256 request fingerprint. Reusing `--idempotency-key`
373
+ with the same volume, path, bytes, and content type reuses the upload; a completed
374
+ replay returns its original upload ID without sending bytes again. A changed
375
+ request conflicts, and an expired incomplete request requires a new key.
376
+ `ornn volumes refresh <volume>` reconciles recorded usage against stored files.
377
+ The upload replay contract requires the matching gateway/orchestrator release;
378
+ see [the service contract](../../services/orchestrator/README.md#file-upload-replay-and-usage).