@ornncompute/cli 0.1.9 → 0.2.1

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
@@ -17,13 +17,23 @@ curl -fsSL https://compute.ornn.com/cli/install | sh
17
17
 
18
18
  The installer requires Node.js 20 or newer and npm. It installs `@ornncompute/cli`
19
19
  globally, exposes the `ornn` binary, adds the npm global bin directory to the
20
- user's shell profile when needed, and records the Ornn host that served it as
21
- `authBaseUrl` in `~/.config/ornn/config.json`, so `ornn login` reaches the right
22
- host from the shell that ran the installer. The
20
+ user's shell profile when needed, and records the web browser handoff as
21
+ `authBaseUrl` plus the API gateway as `apiBaseUrl` in
22
+ `~/.config/ornn/config.json`. The
23
23
  installer prints a short Ornn Compute welcome banner and next steps; set
24
24
  `ORNN_INSTALL_BANNER=0` to skip it or `ORNN_INSTALL_ANIMATION=0` to keep it
25
25
  static.
26
26
 
27
+ `ornn whoami`, `ornn logout`, and `ornn status` call the API gateway's
28
+ `/v1/cli/session` and `/v1/cli/status` contracts. The gateway resolves the CLI
29
+ bearer itself; it never trusts caller-supplied identity or authorization-admin
30
+ headers. Logout asks the gateway to revoke the remote credential, then always
31
+ clears the local bearer. If revocation cannot be confirmed, the CLI reports
32
+ that the remote credential may remain active. Updated legacy installs that
33
+ saved only a deployed web/auth
34
+ origin map that known Ornn origin to its API gateway automatically; custom and
35
+ localhost combined endpoints are left unchanged.
36
+
27
37
  ## Commands
28
38
 
29
39
  ```bash
@@ -35,14 +45,20 @@ ornn status [--json]
35
45
  ornn listings list [--gpu-type <type>] [--facility <name>] [--operator <name>] [--json]
36
46
  ornn listings show <listing-id> [--open] [--json]
37
47
  ornn buy <listing-id> [--no-open] [--json]
38
- ornn exchange create <listing-id> --gpu-count <n> --min-gpu-count <n> --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd> [--no-open] [--json]
48
+ 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]
39
49
  ornn exchange list [--limit <1-500>] [--cursor <last-id>] [--json]
40
- ornn exchange show <bid-id> [--open] [--json]
41
- ornn exchange update <bid-id> --gpu-count <n> --min-gpu-count <n> --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd>
42
- ornn exchange withdraw <bid-id>
50
+ ornn exchange show <exchange-id> [--open] [--json]
51
+ ornn exchange update <exchange-id> --node-count <n> --min-node-count <n> --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd>
52
+ ornn exchange withdraw <exchange-id>
53
+
54
+ Bid create/update prefer `--node-count` and `--min-node-count`. Legacy
55
+ `--gpu-count` and `--min-gpu-count` remain available; they convert using the
56
+ listing's GPUs per node before the gateway translates the request to the
57
+ Commerce bid contract.
58
+
43
59
  ornn gpus list [--status <status>] [--limit <1-500>] [--cursor <last-id>] [--json]
44
- ornn gpus show <reservation-id> [--open] [--json]
45
- ornn gpus checkout <reservation-id> [--no-open] [--json]
60
+ ornn gpus show <gpu-id> [--open] [--json]
61
+ ornn gpus checkout <gpu-id> [--no-open] [--json]
46
62
  ornn nodes list [--json]
47
63
  ornn nodes show <node-id> [--json]
48
64
  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]
@@ -55,15 +71,17 @@ ornn nodes keys attach <node-id> --key <path|id|label> [--json]
55
71
  ornn nodes keys list <node-id> [--json]
56
72
  ornn node health <node-id> [--json]
57
73
  ornn node diagnose <node-id> [--json]
74
+ ornn node list [--operator <id-or-slug>] [--facility <id>] [--json]
75
+ ornn node reboot <node-id> [--json]
76
+ ornn node hard-reset <node-id> [--json]
77
+ ornn node off-grid <node-id> [--json]
78
+ ornn node on-grid <node-id> [--json]
79
+ ornn node terminate <node-id> [--reason <text>] [--force] [--json]
80
+ ornn node admin-key <node-id> [--generate] [--json]
58
81
  ornn node deenroll <node-id> [--reason <text>] [--keep-record] [--json]
59
- ornn fleet clean <ip>... --operator <id-or-slug> --ib-island <name> --identity-file <path> --dry-run [--policy <path>] [--policy-out <path>] [--ssh-user <non-root-linux-user>] [--json]
60
- ornn fleet clean <fleet-id> --identity-file <path> --dry-run [--policy <path>] [--policy-out <path>] [--json]
61
- ornn fleet clean <fleet-id> --identity-file <path> --confirm-clean <plan-hash> [--json]
62
- ornn fleet enroll <fleet-id> --identity-file <path> [--confirm-takeover <ip[,ip...]>] [--json]
63
- ornn fleet delete <fleet-id> --confirm-delete <fleet-id> [--json]
64
- ornn reservations commerce list --tenant <email-or-id> [--fleet <fleet-id>] [--json]
65
- ornn reservations commerce create --tenant <email> --listing <listing-id> --fleet <fleet-id> [--start-at <timestamp>] [--end-at <timestamp>] [--price-per-gpu-hour <rate>] [--json]
66
- ornn fleet deploy <fleet-id> --tenant <contact-email> [--user <email-or-id>] --commerce-reservation <id> [--network public|private] [--json]
82
+ ornn reservations commerce list --tenant <email-or-id> [--listing <listing-id>] [--json]
83
+ 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]
84
+ ornn reservations deploy <node-id> --target-tenant <id> --commerce-reservation <id> [--target-user <id>] [--network public|private] [--json]
67
85
  ornn ssh <node-or-reservation-id> [--print] [--identity-file <path>] [--user <name>] [--json]
68
86
  ornn metrics nodes [--json]
69
87
  ornn metrics node <node-id> [--json]
@@ -106,10 +124,13 @@ ornn storage volumes create --name <name> [--source <drive-id>] [--json]
106
124
  ornn storage volumes refresh <drive-id> [--json]
107
125
  ornn storage volumes clear <drive-id> [--json]
108
126
  ornn storage volumes delete <drive-id> [--json]
127
+ ornn storage files ls <drive-id> [--prefix <path>] [--json]
109
128
  ornn storage files upload <drive-id> <local-file> [--destination <path>] [--content-type <type>] [--json]
110
- ornn storage deploy <drive-id> --reservation <reservation-id> [--all-nodes] [--mount-path <path>] [--read-only|--read-write] [--json]
111
- ornn storage deploy status --reservation <reservation-id> [--json]
112
- ornn storage undeploy --reservation <reservation-id> [--json]
129
+ ornn storage files download <drive-id> <remote-path> [--output <path>] [--json]
130
+ ornn storage targets [--json]
131
+ ornn storage deploy <drive-id> --reservation <reservation-id> [--all-nodes] [--read-only|--read-write] [--json]
132
+ ornn storage status --reservation <reservation-id> [--watch] [--interval <seconds>] [--timeout <seconds>] [--json]
133
+ ornn storage detach --reservation <reservation-id> [--json]
113
134
  ornn storage buckets list [--json]
114
135
  ornn storage buckets show <drive-id> [--json]
115
136
  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]
@@ -117,26 +138,26 @@ ornn storage buckets update-credentials <drive-id> --access-key-id <id> --secret
117
138
  ornn storage buckets verify <drive-id> [--json]
118
139
  ornn storage buckets disconnect <drive-id> [--json]
119
140
  ornn keys list [--json]
120
- ornn keys add [<public-key-file>] [--public-key <key>] [--label <label>] [--json]
141
+ ornn keys add [<public-key-file>] --label <label> [--public-key <key>] [--json]
121
142
  ornn keys delete <key-id> [--json]
122
143
  ornn access show <reservation-id> [--json]
123
144
  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]
124
145
  ornn access switch <reservation-id> --network public|private --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--wait] [--json]
125
146
  ornn access push-keys <reservation-id> --ssh-key-id <id> [--json]
126
147
  ornn access keys list <reservation-id> [--json]
127
- ornn access keys add <reservation-id> --public-key <key> [--label <label>] [--json]
128
- ornn access keys add <reservation-id> --public-key-file <path> [--label <label>] [--json]
148
+ ornn access keys add <reservation-id> --public-key <key> --label <label> [--json]
149
+ ornn access keys add <reservation-id> --public-key-file <path> --label <label> [--json]
129
150
  ornn access keys push <reservation-id> --ssh-key-id <id> [--json]
130
151
  ornn access keys status <reservation-id> [--json]
131
152
  ornn ssh-keys list [--json]
132
- ornn ssh-keys add --public-key <key> [--label <label>] [--json]
133
- ornn ssh-keys add --public-key-file <path> [--label <label>] [--json]
153
+ ornn ssh-keys add --public-key <key> --label <label> [--json]
154
+ ornn ssh-keys add --public-key-file <path> --label <label> [--json]
134
155
  ornn ssh-keys delete <key-id> [--json]
135
156
  ornn billing summary [--json]
136
157
  ornn billing invoices [--json]
137
158
  ornn billing showback --start <yyyy-mm-dd> --end <yyyy-mm-dd> [--json]
138
159
  ornn billing open [--no-open] [--json]
139
- ornn api <get|post|patch|put|delete> <compute-path> [--data <json>] [--raw]
160
+ ornn api <get|post|patch|put|delete> <allowlisted-path> [--data <json>] [--raw]
140
161
  ornn logout
141
162
  ```
142
163
 
@@ -145,11 +166,37 @@ active VM or Bare Metal machines, adding the key automatically queues the
145
166
  current user's complete reservation key set on those machines. Use
146
167
  `ornn access keys push` to explicitly re-sync keys that are already attached.
147
168
 
148
- `ornn storage deploy status` prints reconciled object and byte progress once the
169
+ `ornn storage status` prints reconciled object and byte progress once the
149
170
  managed transfer has reported progress, plus the number of target nodes that
150
171
  have acknowledged the mount. Internal placement bucket details are not shown.
151
172
  AWS S3 and external GCS sources use the managed transfer path. Cloudflare R2
152
173
  buckets can be connected and verified, but deployment support is coming soon.
174
+ The mount path is always `/home/tenant/volume`; node agents resolve `tenant` to the
175
+ machine's real Linux user at mount time.
176
+
177
+ `ornn storage status --watch` polls the same status endpoint on an interval
178
+ (10 seconds by default) instead of returning after a single check, re-printing
179
+ the human summary on each poll. It exits 0 once the attachment is attached and
180
+ every scoped node has mounted, exits 1 with an error on stderr if the
181
+ attachment detaches before that happens, and exits 1 with a timeout message on
182
+ stderr after 1800 seconds (or the value passed to `--timeout`) without
183
+ success. Use `--interval <seconds>` to change the poll cadence. `--interval`
184
+ and `--timeout` require `--watch`. Combined with `--json`, only a single JSON
185
+ payload is printed, at the end, instead of a stream of per-poll output.
186
+
187
+ `ornn storage detach` detaches the drive from the reservation's storage
188
+ attachment. Detach is origin-aware: if your reservation individually joined a
189
+ drive that another reservation already had attached, detach releases only
190
+ your reservation's own mount and leaves the rest of the attachment alone. If
191
+ your reservation started the attachment, or it is the last member still
192
+ joined, detach flushes and unmounts every node before releasing the whole
193
+ attachment. A node that fails to unmount is left in a retryable state with
194
+ the reported error; run `ornn storage detach` again with the same
195
+ `--reservation` to retry it. A reservation that detached from a shared drive
196
+ can rejoin it later by running `ornn storage deploy` again. Mounted state is
197
+ tracked per node, not by attachment membership, so `ornn storage status`
198
+ can show one node as unmounted while the rest of the attachment
199
+ stays mounted.
153
200
 
154
201
  `ornn storage files upload` adds a file to the drive's current colocated copy.
155
202
  You can upload while a direct FUSE mount is active; every mounted node sees the
@@ -159,27 +206,31 @@ same mount out across every compatible node in the node group. Avoid writing
159
206
  the same file path concurrently from multiple nodes because object storage is
160
207
  not a POSIX shared filesystem.
161
208
 
209
+ `ornn storage files download` streams a single object from the drive straight
210
+ to disk. Pass `--output <path>` to control where it's written; without it, the
211
+ file is saved under the remote path's basename in the current directory.
212
+
162
213
  For a connected bucket, deploy once before uploading. The first deploy imports
163
214
  the source into an Ornn-managed colocated working copy. That copy remains the
164
215
  drive's durable data when you unmount, detach, or mount it elsewhere. Ornn
165
216
  does not write changes back to the original connected bucket.
166
217
 
167
218
  UI aliases are first-class in the CLI: `listings` maps to the older
168
- `availability` command, `exchange` maps to `bid`, and `gpus` maps to
219
+ `availability` command, `exchange` maps to `bid`, `gpus` maps to
169
220
  `reservations`. The older command names remain available for scripts.
170
221
  Bid and reservation list commands return a bounded page (500 rows by default);
171
- use `--limit` and `--cursor` to traverse older history. Pass the final row ID
172
- from one page as the next page's cursor. `show` and `checkout`
222
+ use `--limit`, `--json`, and the response's opaque `next_cursor` to traverse
223
+ older history. Replay that cursor exactly; it is not an item ID. `show` and `checkout`
173
224
  use exact tenant-owned item lookups, so they are not limited to the current page.
174
225
 
175
226
  ## Operator commands
176
227
 
177
228
  The `ornn node` commands are for Ornn operators and reviewers, not tenants. They
178
- wrap internal-reviewer-gated compute endpoints. Prefer `ornn login` as an
179
- internal-allowed staff user (`ORNN_AUTH_BASE_URL`); the CLI calls
180
- `/api/cli/operator/*` and the web server attaches the review secret it never
181
- downloads to the laptop. Optionally set `ORNN_INTERNAL_REVIEW_SECRET` plus
182
- `ORNN_COMPUTE_BASE_URL` for direct compute access (CI / break-glass):
229
+ wrap internal-reviewer-gated endpoints. Run `ornn login` as an
230
+ internal-allowed staff user. The CLI calls `/v1/cli/operator/*`; the gateway
231
+ resolves the user bearer and applies staff authorization without downloading a
232
+ review or service secret to the laptop. There is no direct-service break-glass
233
+ path.
183
234
 
184
235
  - `ornn node health <node-id>` shows launch readiness (ready/blocked plus
185
236
  reasons), passive fault reasons, and the last validation status.
@@ -199,17 +250,16 @@ downloads to the laptop. Optionally set `ORNN_INTERNAL_REVIEW_SECRET` plus
199
250
  - `ornn node terminate <node-id> [--reason <text>] [--force]` best-effort cleans
200
251
  the host, removes the Ornn agent, and hard-deletes the node record from the
201
252
  platform. It does not return the host to a tenant.
202
- - `ornn node admin-key <node-id>` prints the Ornn admin SSH keypair for the node
203
- (including the private key) so an operator can SSH into the host. Treat the
204
- output as a secret.
205
- - `ornn node deenroll <node-id>` removes a node from the environment: it first
206
- gracefully terminates the enrollment (revokes the node claim, retires any
207
- listing, and queues the node-agent self-uninstall packet), then dereferences
208
- (hard-deletes) the `gpu_nodes` record so nothing lingers. Pass `--keep-record`
209
- to stop after termination and leave the row in a `deenrolled` state, or
210
- `--reason <text>` to annotate the audit log. The command is idempotent: an
211
- already-removed node reports success. Terminate is forced by default so a
212
- dead/unreachable node does not block on workload drain.
253
+ - `ornn node admin-key <node-id> [--generate]` prints the Ornn admin SSH keypair
254
+ for the node (including the private key) so an operator can SSH into the host.
255
+ `--generate` always mints a new pair, stores it, and installs the public key
256
+ on the live host. Treat the output as a secret.
257
+ - `ornn node deenroll <node-id>` gracefully terminates the enrollment (revokes
258
+ the node claim, retires any listing, and queues the node-agent self-uninstall
259
+ packet) while retaining the node row as a `deenrolled` audit record. The
260
+ legacy `--keep-record` flag remains accepted but is now a no-op. Pass
261
+ `--reason <text>` to annotate the audit log. The command is idempotent, and
262
+ termination is forced by default so an unreachable node does not block drain.
213
263
 
214
264
  The operator resource commands share the same reviewer auth:
215
265
 
@@ -223,136 +273,51 @@ The operator resource commands share the same reviewer auth:
223
273
  command.
224
274
  - `ornn tokens revoke <token-id>` revokes an enrollment token.
225
275
 
226
- Fleet handoff is an ordered, Compute-backed workflow:
227
-
228
- - Before first contact, independently verify each host key and add it to the
229
- operator's SSH `known_hosts`; fleet SSH uses strict host-key checking and will
230
- not trust a key first presented during cleanup.
231
- - `fleet clean ... --dry-run` tries `ubuntu`, `admin`, then `ornn`, or the
232
- explicit non-root account supplied with `--ssh-user`. It binds the
233
- inventory to the host's hardware identity, records the plan in Compute, and
234
- writes an editable mode-`0600` policy beside the local fleet manifest (or to
235
- `--policy-out`). Inventory covers accounts and orphan homes, authorized SSH
236
- keys, tenant/log/temp/platform paths, workload and listener processes, GPU
237
- consumers, custom systemd services, Docker/Podman objects and bind-mount
238
- dependencies, and every block drive. Each resource advertises its own valid
239
- actions. Suggestions are never applied silently: unresolved choices and
240
- conflicts are recorded as plan data, so edit the policy and re-run the same
241
- fleet with `--policy`; planning is not terminalized just because a choice is
242
- needed. `--source-user` and `--preserve-user` remain legacy user-only
243
- shortcuts and cannot be mixed with a policy file.
244
- Coverage gates also inventory listeners, GPU and container-runtime visibility,
245
- non-block mounts, advanced SSH sources, filesystem scope, root-owned workloads,
246
- network state, groups/sudo, IPC, swap/RAM, and active block stacks. A verified
247
- gate is kept automatically. A present or uninspectable gate must be explicitly
248
- ignored with a reason, so the receipt exposes the excluded scope.
249
- - `fleet clean <fleet-id> ... --confirm-clean <plan-hash>` is shown only after
250
- every choice is resolved. Execution rechecks hardware and resource identity,
251
- runs an idempotent per-resource journal, preserves the management SSH key,
252
- enforces key-only SSH, and returns exact deleted, preserved, exception, and
253
- drive-assurance evidence. `ignore` requires a reason and produces
254
- `clean_with_exceptions`; it is never reported as residue-free deletion.
255
- Kept files and directories are content-hashed; process identity, container
256
- replacement state, and exact drive topology are rechecked. Data-drive actions
257
- are selectable: `logical_clean`, `discard`, `sanitize`, or
258
- `reformat`. The system drive and drives without a unique serial/WWN are
259
- locked to keep/ignore for in-band cleanup. Logical clean is offered only when
260
- every filesystem in the approved topology is mounted and can be emptied and
261
- verified; it never substitutes `wipefs` for data deletion. Discard and NVMe
262
- sanitize require device-reported support, and strong actions refuse active or
263
- unverified block stacks. `sanitize` requires NVMe plus
264
- controller-reported completion. Logical cleanup, discard, and reformat are
265
- not certified physical-media erasure, and the system drive requires an
266
- out-of-band reimage for that assurance.
267
- If the local SSH command times out while a long device operation is still in
268
- progress, the recorded run remains resumable; re-run the same
269
- `--confirm-clean <plan-hash>` command instead of creating a different plan.
270
- Plans created by a pre-v7 runner must be replanned with `--dry-run` before
271
- approval. This keeps newly discovered resources bound to a fresh reviewed
272
- hash instead of adapting a legacy account-only plan during execution.
273
-
274
- In the generated policy, change only `action`, plus `reason` for `ignore` or
275
- `replacement` for `replace`; keep each generated `identity_hash` intact. `keep`
276
- leaves a resource running, `stop_keep` stops but retains it, `stop` terminates a
277
- process, `delete` removes it, `restart` restarts a service, and `replace`
278
- recreates a container from the supplied image/name/network/command/labels/mounts
279
- specification. The generated `suggested_action` is review guidance, not an
280
- automatic decision. Do not put secrets in replacement commands or labels; use
281
- the platform secret manager or a reviewed secret mount.
282
-
283
- - `fleet enroll <fleet-id>` refuses nodes without successful cleanup proof,
284
- live-revalidates each receipt under the current enrollment attempt, then
285
- issues and revokes one cleanup- and attempt-bound token per host, installs the
286
- agent,
287
- assigns the IB island, verifies the same management account still has
288
- key-based SSH and passwordless sudo, and records the resulting GPU node IDs
289
- in Compute. A private executor credential prevents two CLIs from sharing an
290
- active lease. Retries reconcile nodes already registered by the same attempt
291
- before rerunning cleanup or installation. Generic enrollment tokens retain
292
- the legacy enrollment sanitizer.
293
- - `fleet delete <fleet-id> --confirm-delete <fleet-id>` hard-deletes only an
294
- abandoned cleanup plan or an unassigned legacy enrollment record. It saves a
295
- local audit manifest first and refuses any Commerce/tenant/deployment link,
296
- active enrollment, assigned GPU node, or completed/running cleanup evidence.
297
- It never deletes the linked GPU-node records.
276
+ Staff Commerce reservations are listing-backed, not fleet-backed:
277
+
298
278
  - `reservations commerce create --tenant <email> --listing <listing-id>
299
- --fleet <fleet-id>` creates and activates the tenant's Commerce reservation.
300
- GPU count comes from the enrolled fleet; start, end, and hourly rate default
301
- from the listing. Start and end overrides must remain inside the listing's
302
- allowed window; the hourly rate can also be overridden explicitly.
303
- - `reservations commerce list --tenant <email-or-id> [--fleet <fleet-id>]`
304
- lists active reservations in their live window; with `--fleet`, it returns
305
- only reservations whose listing exactly matches that fleet's operator,
306
- facility, GPU model, per-node size, and total GPU count.
307
- - `fleet deploy <fleet-id> --tenant <contact-email>
308
- [--user <email-or-id>] --commerce-reservation <id>` requires a live,
309
- tenant-owned Commerce reservation whose listing exactly matches the fleet.
310
- The user defaults to the tenant's primary administrator. Deployment succeeds
311
- only after that user's SSH access and passwordless sudo are ready on every
312
- node; Commerce is stamped only after the entire fleet reports deployed. A
313
- Commerce reservation can be linked to only one fleet.
314
-
315
- Compute Postgres is authoritative. The mode-0600 files under
316
- `~/.config/ornn/fleets/` include a short-lived enrollment resume credential;
317
- treat them as sensitive and do not copy them into tickets or source control.
318
- Cleanup proves “no
319
- observable residue under the verification scope,” not certified physical-media
320
- erasure. Root is never the preserved management account. `--confirm-takeover`
321
- names only fleet IPs whose existing node claims may be replaced. The IB-island
322
- is a locality label, not cluster creation. Test scheduling remains a separate
323
- control-plane policy.
279
+ [--node-count <n>] [--node <node-id>]` creates and activates the tenant's
280
+ Commerce reservation. Node count defaults to the listing capacity; start,
281
+ end, and hourly rate default from the listing. Optional `--node` values pin
282
+ specific catalog ids. Start and end overrides must remain inside the
283
+ listing's allowed window; the hourly rate can also be overridden explicitly.
284
+ - `reservations commerce list --tenant <email-or-id> [--listing <listing-id>]`
285
+ lists active reservations in their live window, optionally filtered to one
286
+ listing.
324
287
 
325
288
  Reservation lifecycle verbs also run under the operator surface:
326
289
 
327
290
  - `ornn reservations commerce create|list` creates or discovers a validated
328
- Commerce reservation for an enrolled fleet. These actions require a staff
329
- `ornn login`; the direct review-secret path cannot bypass Web validation.
330
- - `ornn reservations withdraw <reservation-id>` withdraws a reservation's
331
- acceptance, returning the node(s) to tenant inventory.
291
+ Commerce reservation from a listing. These actions require a staff
292
+ `ornn login` session; the gateway `/v1/cli/operator/*` allowlist enforces
293
+ staff authorization there is no review-secret break-glass that bypasses
294
+ that gate.
332
295
  - `ornn reservations transfer <reservation-id> --target-tenant <id>
333
296
  [--target-user <id>] [--node <id>] [--strategy reject|park] [--confirm]`
334
297
  transfers a reservation to another tenant.
335
298
  - `ornn reservations deploy <node-id> --target-tenant <id>
336
299
  --commerce-reservation <id> [--target-user <id>] [--network public|private]`
337
- deploys one node only after Web verifies that the live tenant-owned Commerce
338
- reservation and listing match that node.
300
+ deploys one node only after the gateway operator contract verifies that the
301
+ live tenant-owned Commerce reservation and listing match that node.
339
302
 
340
- The tenant `ornn reservations list|show|checkout` verbs still use the tenant CLI
341
- login and `/api/cli` proxy. Staff Commerce actions use the Web operator proxy;
342
- `withdraw|transfer|deploy` retain the operator path above.
303
+ The tenant `ornn reservations list|show|checkout` verbs use the tenant CLI
304
+ login and `/v1/cli/compute` gateway contract. Staff Commerce actions use the
305
+ gateway operator contract; `transfer|deploy` retain the operator path above.
343
306
 
344
307
  Staff happy path:
345
308
 
346
- - `ORNN_AUTH_BASE_URL` — web/auth origin
309
+ - `ORNN_AUTH_BASE_URL` — web/browser handoff origin
310
+ - `ORNN_API_BASE_URL` — API gateway origin
347
311
  - `ornn login` as a user allowed by `INTERNAL_ALLOWED_*` on that environment
348
312
 
349
- Optional direct compute override:
313
+ Optional installer gateway base for `ornn tokens create` install one-liners:
350
314
 
351
- - `ORNN_COMPUTE_BASE_URL` compute origin (for example `http://localhost:8000`)
352
- - `ORNN_INTERNAL_REVIEW_SECRET` reviewer secret (`X-Internal-Review-Secret`)
315
+ - `ORNN_INSTALLER_URL` - base serving `enrollment/install` (for deployed
316
+ gateways, `https://<gateway>/v1/orchestrator`), falling back to
317
+ `NEXT_PUBLIC_INSTALLER_URL`. Unset prints the token without an install command.
353
318
 
354
- Without a staff login session or the review-secret pair, operator commands fail
355
- with a clear error before making a network request.
319
+ Without a staff login session, operator commands fail with a clear error before
320
+ making a network request.
356
321
 
357
322
  Commands print concise human-readable output by default. Use `--json` on
358
323
  read/show/list commands and transaction handoffs when you need structured
@@ -365,7 +330,7 @@ cannot open a browser, copy the printed URL into any browser and sign in there;
365
330
  the terminal keeps polling until the login is approved or expires.
366
331
 
367
332
  Run `ornn --help` for the full command list and `ornn api` for the
368
- allowlisted compute API escape hatch.
333
+ allowlisted gateway API escape hatch.
369
334
 
370
335
  WireGuard client configs use the current tenant-scoped `/nodes` routes:
371
336
 
@@ -376,10 +341,21 @@ ornn api post /nodes/reservations/<reservation-id>/vpn/peers \
376
341
  ornn api delete /nodes/reservations/<reservation-id>/vpn/peers/<peer-id> --raw
377
342
  ```
378
343
 
379
- The legacy `/standalone-vms/*` prefix is not exposed through the CLI proxy.
344
+ The legacy `/standalone-vms/*` prefix is not exposed through the gateway
345
+ `/v1/cli/*` allowlist.
380
346
  Deleting a peer is the supported way to replace its key; switching a node
381
347
  between Public and Private VPN preserves the peer.
382
348
 
383
349
  ## Updating
384
350
 
385
351
  The CLI checks the npm registry for a newer version at most once per day and prints a one-line notice on stderr when one exists. Run `ornn update` to install it (the command detects npm, pnpm, yarn, or bun installs). The check is skipped in CI and non-interactive shells.
352
+
353
+ ## Deployment
354
+
355
+ `deploy-cli-pipeline.yml` publishes `@ornncompute/cli` from `main`. Staging
356
+ publishes the package.json version to the npm `next` dist-tag; production then
357
+ promotes that same version to `latest`. Manual rolls use
358
+ `deploy-cli-service.yml`. Runtime changes under `apps/cli` or
359
+ `packages/capabilities` must bump `apps/cli/package.json` so npm receives a
360
+ new release. Re-running the pipeline is idempotent when that version is
361
+ already published.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ornncompute/cli",
3
- "version": "0.1.9",
3
+ "version": "0.2.1",
4
4
  "description": "Command-line interface for Ornn compute access workflows.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,6 +9,7 @@
9
9
  "files": [
10
10
  "bin",
11
11
  "src",
12
+ "vendor",
12
13
  "README.md"
13
14
  ],
14
15
  "homepage": "https://compute.ornn.com",
@@ -26,7 +27,11 @@
26
27
  "registry": "https://registry.npmjs.org/"
27
28
  },
28
29
  "scripts": {
29
- "test": "node --test"
30
+ "test": "node --test",
31
+ "prepack": "node scripts/vendor-capabilities.mjs"
32
+ },
33
+ "devDependencies": {
34
+ "@ornn/capabilities": "0.1.0"
30
35
  },
31
36
  "engines": {
32
37
  "node": ">=20"