@ornncompute/cli 1.0.72 → 1.0.97

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 (59) hide show
  1. package/README.md +55 -24
  2. package/package.json +4 -2
  3. package/src/admin-capacity-reservations.mjs +6 -13
  4. package/src/admin-command-handlers.mjs +2 -1
  5. package/src/admin-credits.mjs +1 -2
  6. package/src/admin-enrollment.mjs +22 -30
  7. package/src/admin-mutations.mjs +6 -56
  8. package/src/admin-node-diagnostics.mjs +3 -41
  9. package/src/admin-node-lifecycle.mjs +40 -160
  10. package/src/admin-node-sanitize.mjs +243 -0
  11. package/src/admin-shell.mjs +39 -32
  12. package/src/catalog-shell.mjs +6 -6
  13. package/src/evidence-commands.mjs +4 -6
  14. package/src/external-bucket-commands.mjs +76 -96
  15. package/src/interaction-runtime.mjs +5 -37
  16. package/src/kubernetes-commands.mjs +25 -183
  17. package/src/launch-mode-handlers.mjs +0 -1
  18. package/src/machine-reference.mjs +33 -56
  19. package/src/mount-commands.mjs +25 -131
  20. package/src/slurm-commands.mjs +13 -2
  21. package/src/storage-commands.mjs +2 -87
  22. package/src/vm-commands.mjs +48 -101
  23. package/vendor/api-client/commerce.js +743 -0
  24. package/vendor/capabilities/cli.js +7688 -7
  25. package/vendor/capabilities/capabilities/admin-capacity-reservations.js +0 -101
  26. package/vendor/capabilities/capabilities/admin-enrollment.js +0 -321
  27. package/vendor/capabilities/capabilities/admin-node-diagnostics.js +0 -88
  28. package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +0 -235
  29. package/vendor/capabilities/capabilities/admin.js +0 -91
  30. package/vendor/capabilities/capabilities/cli.js +0 -156
  31. package/vendor/capabilities/capabilities/clusters.js +0 -248
  32. package/vendor/capabilities/capabilities/commerce-market.js +0 -405
  33. package/vendor/capabilities/capabilities/compute.js +0 -523
  34. package/vendor/capabilities/capabilities/credits.js +0 -78
  35. package/vendor/capabilities/capabilities/evidence.js +0 -145
  36. package/vendor/capabilities/capabilities/external-buckets.js +0 -191
  37. package/vendor/capabilities/capabilities/fleet.js +0 -306
  38. package/vendor/capabilities/capabilities/identity.js +0 -129
  39. package/vendor/capabilities/capabilities/listings.js +0 -398
  40. package/vendor/capabilities/capabilities/locality.js +0 -42
  41. package/vendor/capabilities/capabilities/market-shared.js +0 -46
  42. package/vendor/capabilities/capabilities/markets.js +0 -482
  43. package/vendor/capabilities/capabilities/mounts.js +0 -176
  44. package/vendor/capabilities/capabilities/native-listing.js +0 -99
  45. package/vendor/capabilities/capabilities/networks.js +0 -1264
  46. package/vendor/capabilities/capabilities/observability.js +0 -218
  47. package/vendor/capabilities/capabilities/organization-invites.js +0 -53
  48. package/vendor/capabilities/capabilities/reservation-list.js +0 -68
  49. package/vendor/capabilities/capabilities/staff-shared.js +0 -64
  50. package/vendor/capabilities/capabilities/tokens.js +0 -165
  51. package/vendor/capabilities/capabilities/users.js +0 -159
  52. package/vendor/capabilities/capabilities/volumes.js +0 -178
  53. package/vendor/capabilities/capability.js +0 -99
  54. package/vendor/capabilities/cli-catalog.js +0 -73
  55. package/vendor/capabilities/cli-migrations.js +0 -264
  56. package/vendor/capabilities/names.js +0 -6
  57. package/vendor/capabilities/software-catalog.js +0 -82
  58. package/vendor/capabilities/spec-catalog.js +0 -151
  59. package/vendor/capabilities/supplier-directory.js +0 -20
@@ -1,1264 +0,0 @@
1
- import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
3
- const CANONICAL_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4
- const DEFAULT_LIMIT = 50;
5
- const unknownRecordSchema = z.record(z.string(), z.unknown());
6
- const MAX_LIMIT = 500;
7
- const NETWORKS_PATH = "/v1/workflows/compute/networks";
8
- const globalInput = {
9
- $positionals: z.array(z.string()).optional(),
10
- guided: z.boolean().optional(),
11
- idempotencyKey: z.string().optional(),
12
- noBrowser: z.boolean().optional(),
13
- noWait: z.boolean().optional(),
14
- overwrite: z.boolean().optional(),
15
- print: z.boolean().optional(),
16
- wait: z.boolean().optional(),
17
- yes: z.boolean().optional(),
18
- };
19
- const noOptionsInput = z.object(globalInput).strict();
20
- const connectInput = z
21
- .object({
22
- ...globalInput,
23
- identityFile: z.string().optional(),
24
- output: z.string().optional(),
25
- user: z.string().optional(),
26
- })
27
- .strict();
28
- const listInput = z
29
- .object({ ...globalInput, cursor: z.string().optional(), limit: z.string().optional() })
30
- .strict();
31
- const networkCreateInput = z
32
- .object({ ...globalInput, cidr: z.string().optional(), name: z.string().optional() })
33
- .strict();
34
- const networkUpdateInput = z.object({ ...globalInput, name: z.string().optional() }).strict();
35
- const vpnConfigureInput = z
36
- .object({
37
- ...globalInput,
38
- name: z.string().optional(),
39
- output: z.string().optional(),
40
- privateKey: z.string().optional(),
41
- })
42
- .strict();
43
- function responseStatus(error) {
44
- if (!error || typeof error !== "object" || !("status" in error))
45
- return null;
46
- return typeof error.status === "number" ? error.status : null;
47
- }
48
- function interaction(context) {
49
- // The app-owned runtime extends the shared catalog context only for CLI execution.
50
- const cli = context.cli;
51
- const runtime = cli?.interaction;
52
- if (!runtime)
53
- throw new Error("This capability must execute through the Ornn CLI interaction runtime.");
54
- return runtime;
55
- }
56
- function text(value) {
57
- return typeof value === "string" && value.trim() ? value.trim() : null;
58
- }
59
- function shellQuote(value) {
60
- return `'${value.replaceAll("'", "'\\''")}'`;
61
- }
62
- function record(value) {
63
- const parsed = unknownRecordSchema.safeParse(value);
64
- return parsed.success ? parsed.data : {};
65
- }
66
- function integer(value) {
67
- return typeof value === "number" && Number.isInteger(value) ? value : null;
68
- }
69
- function normalizedName(value) {
70
- return value.normalize("NFKC").trim().replace(/\s+/g, " ").toLocaleLowerCase("en-US");
71
- }
72
- function normalizedCidr(value) {
73
- const [address, rawPrefix, ...extra] = value.trim().split("/");
74
- const octets = address?.split(".").map(Number) ?? [];
75
- const prefix = Number(rawPrefix);
76
- if (extra.length ||
77
- octets.length !== 4 ||
78
- octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255) ||
79
- !Number.isInteger(prefix) ||
80
- prefix < 0 ||
81
- prefix > 32) {
82
- return value.trim();
83
- }
84
- const numeric = (((octets[0] * 256 + octets[1]) * 256 + octets[2]) * 256 + octets[3]) >>> 0;
85
- const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
86
- const network = (numeric & mask) >>> 0;
87
- return `${network >>> 24}.${(network >>> 16) & 0xff}.${(network >>> 8) & 0xff}.${network & 0xff}/${prefix}`;
88
- }
89
- function requiredOption(runtime, value, option, usage) {
90
- const parsed = text(value);
91
- if (!parsed)
92
- runtime.usage(`${option} is required.\n${usage}`, { field: option.slice(2) });
93
- return parsed;
94
- }
95
- function exactPositionals(runtime, positionals, count, usage) {
96
- const values = positionals ?? [];
97
- if (values.length !== count || values.some((value) => !value.trim()))
98
- runtime.usage(usage);
99
- return values.map((value) => value.trim());
100
- }
101
- function requireCanonicalTarget(runtime, value) {
102
- if (!CANONICAL_ID.test(value)) {
103
- runtime.usage("Private targets currently require a canonical capacity-reservation identifier so connect cannot select an ambiguous resource.", { code: "canonical_reference_required", field: "target" });
104
- }
105
- return value;
106
- }
107
- function requireMutationKey(runtime, input) {
108
- if (!runtime.machine)
109
- return text(input.idempotencyKey);
110
- const key = text(input.idempotencyKey);
111
- if (!key) {
112
- runtime.usage("Machine mutations require --idempotency-key <caller-stable-key> before API I/O.", {
113
- code: "idempotency_key_required",
114
- field: "idempotencyKey",
115
- });
116
- }
117
- return key;
118
- }
119
- function mutationHeaders(key) {
120
- return key ? { "Idempotency-Key": key } : undefined;
121
- }
122
- function ownerErrorCode(error) {
123
- if (!error || typeof error !== "object" || !("detail" in error))
124
- return null;
125
- const detail = record(error.detail);
126
- const nested = detail.detail ?? detail.error;
127
- if (typeof nested === "string")
128
- return nested;
129
- return text(record(nested).code) ?? text(detail.code);
130
- }
131
- function lifecycle(statusValue) {
132
- const status = text(statusValue)?.toLowerCase() ?? "unknown";
133
- if (["active", "ready", "applied", "connected"].includes(status)) {
134
- return { class: "ready", phase: "available" };
135
- }
136
- if (["failed", "degraded", "error"].includes(status)) {
137
- return { class: "failed", phase: "needs_attention" };
138
- }
139
- if (["deleted", "revoked", "disconnected"].includes(status)) {
140
- return { class: "ended", phase: "disconnected" };
141
- }
142
- if (["deleting", "revoking"].includes(status)) {
143
- return { class: "working", phase: "disconnecting" };
144
- }
145
- return { class: "pending", phase: "configuring" };
146
- }
147
- function reservationTargetLifecycle(statusValue) {
148
- const status = text(statusValue)?.toLowerCase() ?? "unknown";
149
- if (status === "active")
150
- return { class: "ready", phase: "active" };
151
- if (["failed", "payment_failed", "error"].includes(status)) {
152
- return { class: "failed", phase: status };
153
- }
154
- if (["cancelled", "canceled", "completed", "ended", "expired", "rejected", "terminated"].includes(status)) {
155
- return { class: "ended", phase: status };
156
- }
157
- return { class: "pending", phase: status };
158
- }
159
- function projectNetwork(value) {
160
- const source = record(value);
161
- const attachmentIds = Array.isArray(source.attached_reservation_ids)
162
- ? source.attached_reservation_ids
163
- .map((value) => text(value))
164
- .filter((value) => Boolean(value && CANONICAL_ID.test(value)))
165
- : [];
166
- return {
167
- id: text(source.id),
168
- name: text(source.name) ?? "Unnamed private network",
169
- cidr: text(source.cidr),
170
- lifecycle: lifecycle(source.status),
171
- attachment_count: integer(source.attached_reservation_count) ?? attachmentIds.length,
172
- attached_reservation_ids: [...new Set(attachmentIds)],
173
- created_at: text(source.created_at),
174
- updated_at: text(source.updated_at),
175
- };
176
- }
177
- function networkRows(payload) {
178
- const source = record(payload);
179
- const values = Array.isArray(payload)
180
- ? payload
181
- : Array.isArray(source.networks)
182
- ? source.networks
183
- : [];
184
- return values
185
- .flatMap((value) => {
186
- const parsed = unknownRecordSchema.safeParse(value);
187
- return parsed.success ? [parsed.data] : [];
188
- })
189
- .sort((left, right) => {
190
- const byName = normalizedName(text(left.name) ?? "").localeCompare(normalizedName(text(right.name) ?? ""));
191
- return byName || (text(left.id) ?? "").localeCompare(text(right.id) ?? "");
192
- });
193
- }
194
- function networkFromMutation(payload) {
195
- const source = record(payload);
196
- return projectNetwork(source.network ?? source);
197
- }
198
- async function fetchNetworks(context) {
199
- return networkRows(await context.fetch(NETWORKS_PATH));
200
- }
201
- async function resolveNetwork(context, runtime, reference) {
202
- if (CANONICAL_ID.test(reference)) {
203
- return record(await context.fetch(`${NETWORKS_PATH}/${encodeURIComponent(reference)}`));
204
- }
205
- const wanted = normalizedName(reference);
206
- const matches = (await fetchNetworks(context)).filter((candidate) => normalizedName(text(candidate.name) ?? "") === wanted);
207
- if (matches.length === 0) {
208
- runtime.error(`Private network not found: ${reference}.`, {
209
- code: "private_network_not_found",
210
- });
211
- }
212
- if (matches.length > 1) {
213
- runtime.usage(`More than one private network has the exact name "${reference}"; use a canonical identifier.`, {
214
- code: "private_network_ambiguous",
215
- field: "network",
216
- });
217
- }
218
- return matches[0];
219
- }
220
- function encodeCursor(command, offset) {
221
- return encodeURIComponent(JSON.stringify({ command, offset }));
222
- }
223
- function decodeCursor(runtime, command, cursor) {
224
- if (!cursor)
225
- return 0;
226
- try {
227
- const parsed = record(JSON.parse(decodeURIComponent(cursor)));
228
- if (parsed.command === command &&
229
- Number.isInteger(parsed.offset) &&
230
- Number(parsed.offset) >= 0) {
231
- return Number(parsed.offset);
232
- }
233
- }
234
- catch {
235
- // The stable usage error below intentionally hides cursor internals.
236
- }
237
- runtime.usage("The pagination cursor is invalid or belongs to another command.", {
238
- code: "invalid_cursor",
239
- field: "cursor",
240
- });
241
- }
242
- function pageLimit(runtime, raw) {
243
- if (raw === undefined)
244
- return DEFAULT_LIMIT;
245
- const limit = Number(raw);
246
- if (!Number.isInteger(limit) || limit < 1 || limit > MAX_LIMIT) {
247
- runtime.usage(`--limit must be an integer from 1 to ${MAX_LIMIT}.`, { field: "limit" });
248
- }
249
- return limit;
250
- }
251
- function page(runtime, command, rows, input) {
252
- const limit = pageLimit(runtime, input.limit);
253
- const offset = decodeCursor(runtime, command, input.cursor);
254
- const items = rows.slice(offset, offset + limit);
255
- const nextOffset = offset + items.length;
256
- return {
257
- items,
258
- page: {
259
- limit,
260
- returned: items.length,
261
- next_cursor: nextOffset < rows.length ? encodeCursor(command, nextOffset) : null,
262
- },
263
- };
264
- }
265
- function declined(runtime) {
266
- return runtime.result({
267
- data: null,
268
- errors: [{ code: "action_declined", message: "No changes were made.", retryable: false }],
269
- exitCode: 1,
270
- outcome: { class: "ended", phase: "declined" },
271
- presentation: { lines: ["No changes were made."] },
272
- });
273
- }
274
- function networkLines(network) {
275
- const state = record(network.lifecycle);
276
- return [
277
- `${String(network.name)} (${String(network.id ?? "unknown")})`,
278
- ` CIDR: ${String(network.cidr ?? "pending")}`,
279
- ` State: ${state.class} (${state.phase})`,
280
- ];
281
- }
282
- function networkMutationExecution(runtime, network, replayed) {
283
- const state = record(network.lifecycle);
284
- const stateClass = String(state.class);
285
- const ready = stateClass === "ready";
286
- const failed = stateClass === "failed";
287
- const command = ready ? "ornn connect" : `ornn private-networks show ${String(network.id)}`;
288
- return runtime.result({
289
- action: {
290
- command,
291
- description: ready
292
- ? "Continue to an exact compute target."
293
- : "Inspect private-network readiness before attaching or connecting.",
294
- type: "command",
295
- },
296
- data: { private_network: network, replayed },
297
- exitCode: ready ? 0 : failed ? 4 : 3,
298
- outcome: ready
299
- ? { class: "ready", phase: "active" }
300
- : { class: String(state.class), phase: String(state.phase) },
301
- presentation: {
302
- lines: [
303
- ready
304
- ? replayed
305
- ? "Private network already satisfies this request."
306
- : "Private network created."
307
- : failed
308
- ? "Private network exists, but provisioning failed."
309
- : "Private network creation was accepted and is still provisioning.",
310
- ...networkLines(network),
311
- ],
312
- next: command,
313
- },
314
- resume: ready ? null : { kind: "private_network", ref: String(network.id) },
315
- });
316
- }
317
- async function listPrivateNetworks(context, input) {
318
- const runtime = interaction(context);
319
- exactPositionals(runtime, input.$positionals, 0, "Usage: ornn private-networks list [--limit <1-500>] [--cursor <cursor>]");
320
- const rows = (await fetchNetworks(context)).map(projectNetwork);
321
- const selected = page(runtime, "private-networks list", rows, input);
322
- return runtime.result({
323
- data: { private_networks: selected.items },
324
- page: selected.page,
325
- presentation: {
326
- lines: selected.items.length
327
- ? selected.items.flatMap(networkLines)
328
- : ["No private networks found."],
329
- ...(selected.page.next_cursor
330
- ? { next: `ornn private-networks list --cursor ${selected.page.next_cursor}` }
331
- : {}),
332
- },
333
- });
334
- }
335
- async function showPrivateNetwork(context, input) {
336
- const runtime = interaction(context);
337
- const [reference] = exactPositionals(runtime, input.$positionals, 1, "Usage: ornn private-networks show <exact-name-or-id>");
338
- const network = projectNetwork(await resolveNetwork(context, runtime, reference));
339
- return runtime.result({
340
- data: { private_network: network },
341
- presentation: { lines: networkLines(network) },
342
- });
343
- }
344
- async function createPrivateNetwork(context, input) {
345
- const runtime = interaction(context);
346
- const usage = "Usage: ornn private-networks create --name <name> [--cidr <cidr>]";
347
- exactPositionals(runtime, input.$positionals, 0, usage);
348
- if (!text(input.name) && input.guided === true && !runtime.machine) {
349
- input.name = await runtime.ask({ label: "Private network name" });
350
- }
351
- const name = requiredOption(runtime, input.name, "--name", usage)
352
- .normalize("NFKC")
353
- .trim()
354
- .replace(/\s+/g, " ");
355
- const cidr = text(input.cidr) ? normalizedCidr(String(input.cidr)) : null;
356
- const idempotencyKey = requireMutationKey(runtime, input);
357
- const matches = (await fetchNetworks(context)).filter((candidate) => normalizedName(text(candidate.name) ?? "") === normalizedName(name));
358
- if (matches.length > 1) {
359
- runtime.usage(`More than one private network has the exact name "${name}"; use a different name.`, {
360
- code: "private_network_ambiguous",
361
- field: "name",
362
- });
363
- }
364
- if (matches.length === 1) {
365
- const existingCidr = text(matches[0].cidr);
366
- if (cidr && (!existingCidr || normalizedCidr(existingCidr) !== cidr)) {
367
- runtime.usage(`Private network "${name}" already exists with different effective input. Use a new idempotency key and name after review.`, { code: "private_network_replay_conflict", field: "cidr" });
368
- }
369
- return networkMutationExecution(runtime, projectNetwork(matches[0]), true);
370
- }
371
- if (!(await runtime.review({
372
- title: "Create private network",
373
- terms: [
374
- { label: "Name", value: name },
375
- { label: "CIDR", value: cidr ?? "Automatically assigned" },
376
- ],
377
- })))
378
- return declined(runtime);
379
- const created = await context.fetch(NETWORKS_PATH, {
380
- body: { name, ...(cidr ? { cidr } : {}) },
381
- headers: mutationHeaders(idempotencyKey),
382
- method: "POST",
383
- });
384
- return networkMutationExecution(runtime, networkFromMutation(created), false);
385
- }
386
- async function updatePrivateNetwork(context, input) {
387
- const runtime = interaction(context);
388
- const usage = "Usage: ornn private-networks update <exact-name-or-id> --name <new-name>";
389
- const [reference] = exactPositionals(runtime, input.$positionals, 1, usage);
390
- const name = requiredOption(runtime, input.name, "--name", usage)
391
- .normalize("NFKC")
392
- .trim()
393
- .replace(/\s+/g, " ");
394
- const idempotencyKey = requireMutationKey(runtime, input);
395
- const current = await resolveNetwork(context, runtime, reference);
396
- if (normalizedName(text(current.name) ?? "") === normalizedName(name)) {
397
- const network = projectNetwork(current);
398
- return runtime.result({
399
- data: { private_network: network, replayed: true },
400
- presentation: {
401
- lines: ["Private network already has the requested name.", ...networkLines(network)],
402
- },
403
- });
404
- }
405
- if ((await fetchNetworks(context)).some((candidate) => normalizedName(text(candidate.name) ?? "") === normalizedName(name))) {
406
- runtime.usage(`Another private network already has the exact name "${name}".`, {
407
- code: "private_network_name_conflict",
408
- field: "name",
409
- });
410
- }
411
- if (!(await runtime.review({
412
- title: "Update private network",
413
- terms: [
414
- {
415
- label: "Private network",
416
- value: `${text(current.name) ?? reference} (${text(current.id) ?? reference})`,
417
- },
418
- { label: "New name", value: name },
419
- ],
420
- })))
421
- return declined(runtime);
422
- const updated = await context.fetch(`${NETWORKS_PATH}/${encodeURIComponent(String(current.id))}`, {
423
- body: { name },
424
- headers: mutationHeaders(idempotencyKey),
425
- method: "PATCH",
426
- });
427
- const network = networkFromMutation(updated);
428
- return runtime.result({
429
- data: { private_network: network, replayed: false },
430
- presentation: { lines: ["Private network updated.", ...networkLines(network)] },
431
- });
432
- }
433
- async function deletePrivateNetwork(context, input) {
434
- const runtime = interaction(context);
435
- const [reference] = exactPositionals(runtime, input.$positionals, 1, "Usage: ornn private-networks delete <exact-name-or-id>");
436
- const idempotencyKey = requireMutationKey(runtime, input);
437
- const projected = projectNetwork(await resolveNetwork(context, runtime, reference));
438
- if (!(await runtime.review({
439
- title: "Delete private network",
440
- terms: [
441
- { label: "Private network", value: `${String(projected.name)} (${String(projected.id)})` },
442
- {
443
- label: "Consequence",
444
- value: "Permanently delete this organization private network when the owner permits deletion.",
445
- },
446
- ],
447
- prompt: "Delete this private network?",
448
- })))
449
- return declined(runtime);
450
- try {
451
- await context.fetch(`${NETWORKS_PATH}/${encodeURIComponent(String(projected.id))}`, {
452
- headers: mutationHeaders(idempotencyKey),
453
- method: "DELETE",
454
- });
455
- }
456
- catch (error) {
457
- if (ownerErrorCode(error) === "network_in_use") {
458
- throw error;
459
- }
460
- throw error;
461
- }
462
- return runtime.result({
463
- data: { deleted: true, private_network: projected },
464
- outcome: { class: "ended", phase: "deleted" },
465
- presentation: {
466
- lines: [`Private network deleted: ${String(projected.name)} (${String(projected.id)})`],
467
- },
468
- });
469
- }
470
- function vpnPath(reservationId) {
471
- return `/v1/workflows/compute/nodes/reservations/${encodeURIComponent(reservationId)}/vpn/peers`;
472
- }
473
- function vpnPayloadRows(payload) {
474
- const source = record(payload);
475
- const peers = Array.isArray(source.peers) ? source.peers : [];
476
- return peers.flatMap((value) => {
477
- const parsed = unknownRecordSchema.safeParse(value);
478
- return parsed.success ? [parsed.data] : [];
479
- });
480
- }
481
- function vpnPeer(payload) {
482
- const peer = record(payload.peer);
483
- return Object.keys(peer).length ? peer : payload;
484
- }
485
- function projectVpnConnection(payload, reservationId) {
486
- const peer = vpnPeer(payload);
487
- const network = record(payload.network);
488
- return {
489
- id: text(peer.id),
490
- name: text(peer.label) ?? "VPN connection",
491
- reservation_id: reservationId,
492
- private_network_id: text(network.network_id) ?? text(network.id),
493
- assigned_address: text(peer.assigned_ip),
494
- lifecycle: lifecycle(peer.status),
495
- created_at: text(peer.created_at),
496
- };
497
- }
498
- function vpnLines(connection) {
499
- const state = record(connection.lifecycle);
500
- return [
501
- `${String(connection.name)} (${String(connection.id ?? "unknown")})`,
502
- ` Private target: ${String(connection.reservation_id)}`,
503
- ` State: ${state.class} (${state.phase})`,
504
- ];
505
- }
506
- async function listVpnPayloads(context, target) {
507
- return vpnPayloadRows(await context.fetch(vpnPath(target)));
508
- }
509
- async function listVpnConnections(context, input) {
510
- const runtime = interaction(context);
511
- const [rawTarget] = exactPositionals(runtime, input.$positionals, 1, "Usage: ornn vpn-connections list <canonical-reservation-id> [--limit <1-500>] [--cursor <cursor>]");
512
- const target = requireCanonicalTarget(runtime, rawTarget);
513
- const connections = (await listVpnPayloads(context, target))
514
- .map((payload) => projectVpnConnection(payload, target))
515
- .sort((left, right) => normalizedName(String(left.name)).localeCompare(normalizedName(String(right.name))));
516
- const selected = page(runtime, "vpn-connections list", connections, input);
517
- return runtime.result({
518
- data: { vpn_connections: selected.items },
519
- page: selected.page,
520
- presentation: {
521
- lines: selected.items.length
522
- ? selected.items.flatMap(vpnLines)
523
- : [`No VPN connections found for private target ${target}.`],
524
- ...(selected.page.next_cursor
525
- ? { next: `ornn vpn-connections list ${target} --cursor ${selected.page.next_cursor}` }
526
- : {}),
527
- },
528
- });
529
- }
530
- function validateSecretExport(runtime, input) {
531
- const hasOutput = Boolean(text(input.output));
532
- const shouldPrint = input.print === true;
533
- if (hasOutput === shouldPrint) {
534
- runtime.usage("Choose exactly one explicit VPN configuration destination: --print or --output <path>.", {
535
- code: "secret_destination_required",
536
- field: "output",
537
- });
538
- }
539
- if (shouldPrint && runtime.formatProvided) {
540
- runtime.usage("--print is incompatible with an explicit --format.", {
541
- code: "secret_print_format_conflict",
542
- field: "format",
543
- });
544
- }
545
- if (runtime.machine && shouldPrint) {
546
- runtime.usage("Machine mode cannot mix secret bytes with a result envelope; use --output <path>.", {
547
- code: "secret_print_unsupported_in_machine_mode",
548
- field: "print",
549
- });
550
- }
551
- if (!runtime.exportSecret ||
552
- !runtime.prepareSecretExport ||
553
- !runtime.wireGuardPublicKeyFromFile) {
554
- runtime.error("The CLI secret-output service is unavailable.", {
555
- code: "secret_output_unavailable",
556
- exitCode: 6,
557
- retryable: true,
558
- });
559
- }
560
- }
561
- async function prepareVpnExport(runtime, input) {
562
- try {
563
- await runtime.prepareSecretExport({
564
- outputPath: text(input.output) ?? undefined,
565
- overwrite: input.overwrite === true,
566
- print: input.print === true,
567
- });
568
- }
569
- catch (error) {
570
- const code = error && typeof error === "object" && "code" in error ? text(error.code) : null;
571
- const message = error instanceof Error && error.message
572
- ? error.message
573
- : "Could not prepare the VPN configuration destination.";
574
- runtime.error(message, { code: code ?? "vpn_configuration_export_failed" });
575
- }
576
- }
577
- async function exportVpnConfig(runtime, input, content, privateKeyPath, publicKey) {
578
- const config = typeof content === "string" && content.length > 0 ? content : null;
579
- if (!config) {
580
- runtime.error("Ornn did not return a usable VPN configuration.", {
581
- code: "vpn_configuration_unavailable",
582
- exitCode: 6,
583
- retryable: true,
584
- });
585
- }
586
- try {
587
- return await runtime.exportSecret({
588
- content: config,
589
- outputPath: text(input.output) ?? undefined,
590
- overwrite: input.overwrite === true,
591
- print: input.print === true,
592
- privateKeyPath,
593
- publicKey,
594
- });
595
- }
596
- catch (error) {
597
- const code = error && typeof error === "object" && "code" in error ? text(error.code) : null;
598
- const message = error instanceof Error && error.message
599
- ? error.message
600
- : "Could not export the VPN configuration.";
601
- runtime.error(message, { code: code ?? "vpn_configuration_export_failed" });
602
- }
603
- }
604
- function vpnConfigureExecution(runtime, target, connection, exported, replayed) {
605
- const state = record(connection.lifecycle);
606
- const stateClass = String(state.class);
607
- const ready = stateClass === "ready";
608
- const failed = stateClass === "failed";
609
- const activationCommand = exported.path
610
- ? `sudo wg-quick up ${shellQuote(exported.path)}`
611
- : "sudo wg-quick up <saved-configuration-path>";
612
- const action = ready
613
- ? {
614
- command: activationCommand,
615
- description: "Activate the completed local WireGuard configuration before connecting.",
616
- type: "command",
617
- }
618
- : {
619
- command: `ornn vpn-connections configure ${target} --guided`,
620
- description: failed
621
- ? "Retry applying this exact VPN peer with its original private key."
622
- : "Reapply this pending VPN peer after gateway readiness is restored.",
623
- type: "command",
624
- };
625
- return runtime.result({
626
- action,
627
- data: { export: exported, replayed, vpn_connection: connection },
628
- exitCode: ready ? 3 : failed ? 4 : 3,
629
- outcome: ready
630
- ? { class: "action_required", phase: "local_vpn_activation_required" }
631
- : { class: String(state.class), phase: String(state.phase) },
632
- presentation: {
633
- lines: [
634
- ready
635
- ? replayed
636
- ? "VPN configuration exported again; local tunnel activation is still required."
637
- : "VPN peer is active and the complete local configuration was exported."
638
- : failed
639
- ? "VPN connection was saved, but the gateway rejected or could not apply it."
640
- : "VPN connection was saved and is waiting for gateway application.",
641
- ...vpnLines(connection),
642
- `Configuration fingerprint: ${exported.fingerprint}`,
643
- ...(exported.path ? [`Configuration written to ${exported.path} (${exported.mode}).`] : []),
644
- ],
645
- next: action.command,
646
- },
647
- resume: ready
648
- ? { kind: "connect", ref: target }
649
- : { kind: "vpn_connection", ref: String(connection.id) },
650
- });
651
- }
652
- async function configureVpnConnection(context, input) {
653
- const runtime = interaction(context);
654
- const usage = "Usage: ornn vpn-connections configure <canonical-reservation-id> --name <name> --private-key <path> (--print | --output <path>)";
655
- const [rawTarget] = exactPositionals(runtime, input.$positionals, 1, usage);
656
- const target = requireCanonicalTarget(runtime, rawTarget);
657
- if (input.guided === true && !runtime.machine) {
658
- input.name ??= await runtime.ask({ label: "VPN connection name" });
659
- input.privateKey ??= await runtime.ask({ label: "WireGuard private-key path" });
660
- if (input.print !== true && !text(input.output)) {
661
- input.output = await runtime.ask({ label: "VPN configuration output path" });
662
- }
663
- }
664
- const name = requiredOption(runtime, input.name, "--name", usage)
665
- .normalize("NFKC")
666
- .trim()
667
- .replace(/\s+/g, " ");
668
- const privateKeyPath = requiredOption(runtime, input.privateKey, "--private-key", usage);
669
- validateSecretExport(runtime, input);
670
- await prepareVpnExport(runtime, input);
671
- let publicKey = "";
672
- try {
673
- publicKey = await runtime.wireGuardPublicKeyFromFile(privateKeyPath);
674
- }
675
- catch (error) {
676
- const code = error && typeof error === "object" && "code" in error ? text(error.code) : null;
677
- const message = error instanceof Error && error.message
678
- ? error.message
679
- : "Could not read the WireGuard private key.";
680
- runtime.error(message, { code: code ?? "invalid_wireguard_private_key", field: "privateKey" });
681
- }
682
- const idempotencyKey = requireMutationKey(runtime, input);
683
- const existing = await listVpnPayloads(context, target);
684
- const sameKey = existing.find((payload) => text(vpnPeer(payload).public_key) === publicKey);
685
- let effectiveName = name;
686
- if (sameKey) {
687
- const existingName = text(vpnPeer(sameKey).label) ?? "VPN connection";
688
- effectiveName = existingName;
689
- if (normalizedName(existingName) !== normalizedName(name)) {
690
- runtime.usage("This public key already identifies a VPN connection with a different name. Use the original effective input or a new key after review.", { code: "vpn_connection_replay_conflict", field: "name" });
691
- }
692
- }
693
- else if (existing.some((payload) => normalizedName(text(vpnPeer(payload).label) ?? "VPN connection") === normalizedName(name))) {
694
- runtime.usage(`A VPN connection named "${name}" already exists with different key material.`, {
695
- code: "vpn_connection_name_conflict",
696
- field: "name",
697
- });
698
- }
699
- if (sameKey && lifecycle(text(vpnPeer(sameKey).status)).class === "ready") {
700
- const exported = await exportVpnConfig(runtime, input, sameKey.config, privateKeyPath, publicKey);
701
- return vpnConfigureExecution(runtime, target, projectVpnConnection(sameKey, target), exported, true);
702
- }
703
- if (!(await runtime.review({
704
- title: sameKey ? "Retry VPN connection" : "Configure VPN connection",
705
- terms: [
706
- { label: "Private target", value: target },
707
- { label: "VPN connection", value: name },
708
- { label: "WireGuard public key", value: publicKey },
709
- {
710
- label: "Configuration destination",
711
- value: input.print ? "Terminal (explicit --print)" : String(input.output),
712
- },
713
- ],
714
- })))
715
- return declined(runtime);
716
- const applied = record(await context.fetch(vpnPath(target), {
717
- body: { label: effectiveName, public_key: publicKey },
718
- headers: mutationHeaders(idempotencyKey),
719
- method: "POST",
720
- }));
721
- const exported = await exportVpnConfig(runtime, input, applied.config, privateKeyPath, publicKey);
722
- const connection = projectVpnConnection(applied, target);
723
- return vpnConfigureExecution(runtime, target, connection, exported, Boolean(sameKey));
724
- }
725
- async function disconnectVpnConnection(context, input) {
726
- const runtime = interaction(context);
727
- const [rawTarget, reference] = exactPositionals(runtime, input.$positionals, 2, "Usage: ornn vpn-connections disconnect <canonical-reservation-id> <exact-name-or-id>");
728
- const target = requireCanonicalTarget(runtime, rawTarget);
729
- const idempotencyKey = requireMutationKey(runtime, input);
730
- const matches = (await listVpnPayloads(context, target)).filter((payload) => {
731
- const peer = vpnPeer(payload);
732
- return CANONICAL_ID.test(reference)
733
- ? text(peer.id) === reference
734
- : normalizedName(text(peer.label) ?? "VPN connection") === normalizedName(reference);
735
- });
736
- if (matches.length === 0)
737
- runtime.error(`VPN connection not found: ${reference}.`, { code: "vpn_connection_not_found" });
738
- if (matches.length > 1) {
739
- runtime.usage(`More than one VPN connection has the exact name "${reference}"; use a canonical identifier.`, {
740
- code: "vpn_connection_ambiguous",
741
- field: "connection",
742
- });
743
- }
744
- const connection = projectVpnConnection(matches[0], target);
745
- if (!(await runtime.review({
746
- title: "Disconnect VPN connection",
747
- terms: [
748
- { label: "Private target", value: target },
749
- { label: "VPN connection", value: `${String(connection.name)} (${String(connection.id)})` },
750
- {
751
- label: "Consequence",
752
- value: "Private access through this VPN connection ends; the private network remains.",
753
- },
754
- ],
755
- })))
756
- return declined(runtime);
757
- await context.fetch(`${vpnPath(target)}/${encodeURIComponent(String(connection.id))}`, {
758
- headers: mutationHeaders(idempotencyKey),
759
- method: "DELETE",
760
- });
761
- return runtime.result({
762
- data: { disconnected: true, vpn_connection: connection },
763
- outcome: { class: "ended", phase: "disconnected" },
764
- presentation: {
765
- lines: [`VPN connection disconnected: ${String(connection.name)} (${String(connection.id)})`],
766
- },
767
- });
768
- }
769
- function normalizedConnectAccessMode(value) {
770
- const mode = text(value)?.toLowerCase();
771
- return mode === "virtual-machine" ? "vm" : (mode ?? null);
772
- }
773
- function validateKnownConnectMode(runtime, input, mode) {
774
- if (mode === "vm" || mode === "bare-metal" || mode === "slurm") {
775
- if (input.output || input.overwrite) {
776
- runtime.usage(`${mode === "slurm" ? "Slurm" : mode === "vm" ? "VM" : "Bare Metal"} connect uses native SSH and does not write an output file.`, {
777
- code: mode === "slurm" ? "slurm_output_unsupported" : "direct_machine_output_unsupported",
778
- field: input.output ? "output" : "overwrite",
779
- });
780
- }
781
- return;
782
- }
783
- if (mode === "kubernetes" && (input.identityFile || input.user || input.print)) {
784
- runtime.usage("Kubernetes connect writes a kubeconfig and does not accept SSH identity, user, or print options.", {
785
- code: input.print ? "kubeconfig_output_required" : "kubernetes_ssh_options_unsupported",
786
- field: input.identityFile ? "identityFile" : input.user ? "user" : "output",
787
- });
788
- }
789
- }
790
- function blockedPrivateTransport(runtime, lifecycleValue, action, data, reservationId) {
791
- const state = record(lifecycleValue);
792
- const outcome = {
793
- class: text(state.class) ?? "pending",
794
- phase: text(state.phase) ?? "configuring",
795
- };
796
- return runtime.result({
797
- action,
798
- data,
799
- exitCode: ["failed", "ended"].includes(outcome.class) ? 1 : 3,
800
- outcome,
801
- resume: { kind: "connect", ref: reservationId },
802
- });
803
- }
804
- function compareVpnConnections(left, right) {
805
- return ((text(left.created_at) ?? "").localeCompare(text(right.created_at) ?? "") ||
806
- (text(left.id) ?? "").localeCompare(text(right.id) ?? "") ||
807
- normalizedName(text(left.name) ?? "").localeCompare(normalizedName(text(right.name) ?? "")));
808
- }
809
- async function connectPrivateTarget(context, input) {
810
- const runtime = interaction(context);
811
- const values = input.$positionals ?? [];
812
- if (values.length > 1) {
813
- runtime.usage("Usage: ornn connect [<exact-hostname-or-canonical-machine-id>]", {
814
- code: "usage_error",
815
- });
816
- }
817
- const rawTarget = text(values[0]);
818
- let resolved = null;
819
- let target = rawTarget;
820
- if (runtime.resolveConnectTarget) {
821
- resolved = await runtime.resolveConnectTarget({
822
- context,
823
- input,
824
- interaction: runtime,
825
- reference: rawTarget,
826
- });
827
- if (resolved) {
828
- validateKnownConnectMode(runtime, input, normalizedConnectAccessMode(resolved.mode));
829
- }
830
- if (resolved && resolved.privateTransportRequired !== true && runtime.continueConnect) {
831
- const direct = await runtime.continueConnect(resolved);
832
- if (direct)
833
- return runtime.result(direct);
834
- }
835
- if (resolved)
836
- target = resolved.reservationId;
837
- }
838
- if (!resolved && rawTarget && CANONICAL_ID.test(rawTarget)) {
839
- try {
840
- const reservation = record(await context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(rawTarget)}`));
841
- const reservationId = text(reservation.id);
842
- if (reservationId && reservationId !== rawTarget) {
843
- runtime.error("The gateway returned a different capacity reservation.", {
844
- code: "reservation_correlation_changed",
845
- });
846
- }
847
- const status = text(reservation.status)?.toLowerCase() ?? "unknown";
848
- if (status !== "active") {
849
- const state = reservationTargetLifecycle(status);
850
- const waiting = state.class === "pending" || state.class === "working";
851
- return runtime.result({
852
- action: waiting
853
- ? {
854
- command: `ornn reservations show ${reservationId ?? rawTarget}`,
855
- description: "Wait for the capacity reservation to become active before launching native compute.",
856
- type: "command",
857
- }
858
- : null,
859
- data: {
860
- capacity_reservation: {
861
- id: reservationId ?? rawTarget,
862
- access_mode: normalizedConnectAccessMode(reservation.access_mode ?? reservation.accessMode),
863
- lifecycle: state,
864
- },
865
- },
866
- exitCode: waiting ? 3 : 1,
867
- outcome: state,
868
- presentation: {
869
- lines: [
870
- waiting
871
- ? `Capacity reservation ${reservationId ?? rawTarget} is not active yet; it has no native-access target.`
872
- : `Capacity reservation ${reservationId ?? rawTarget} is ${state.phase}; it has no launchable native-access target.`,
873
- ],
874
- },
875
- resume: waiting ? { kind: "reservation", ref: reservationId ?? rawTarget } : null,
876
- });
877
- }
878
- const mode = normalizedConnectAccessMode(reservation.access_mode ?? reservation.accessMode);
879
- validateKnownConnectMode(runtime, input, mode);
880
- return runtime.actionRequired({
881
- action: {
882
- command: "ornn launch",
883
- description: "Launch compute for this capacity reservation before requesting native access.",
884
- type: "command",
885
- },
886
- data: {
887
- capacity_reservation: {
888
- id: reservationId ?? rawTarget,
889
- access_mode: mode,
890
- },
891
- },
892
- resume: { kind: "reservation", ref: reservationId ?? rawTarget },
893
- });
894
- }
895
- catch (error) {
896
- if (![400, 404, 422].includes(responseStatus(error) ?? 0))
897
- throw error;
898
- }
899
- }
900
- const privateTarget = target ?? "";
901
- if (!privateTarget || !CANONICAL_ID.test(privateTarget)) {
902
- runtime.usage("Connect requires an exact unique hostname, canonical machine ID, or eligible guided choice.", {
903
- code: "invalid_reference",
904
- field: "machine",
905
- });
906
- }
907
- // A UUID and an organization network do not prove that this target exists.
908
- // Only a resolved native target may continue into private transport setup.
909
- if (!resolved) {
910
- runtime.error("No accessible machine, cluster, or capacity reservation matches this target.", {
911
- code: "connect_target_not_found",
912
- });
913
- }
914
- const shared = record(await context.fetch(`${NETWORKS_PATH}/shared?overlay=true`));
915
- const privateNetwork = projectNetwork({
916
- ...record(shared.network),
917
- id: "shared",
918
- name: "Organization private network",
919
- });
920
- const networkState = record(privateNetwork.lifecycle);
921
- if (networkState.class !== "ready") {
922
- const recoverable = ["failed", "ended"].includes(String(networkState.class));
923
- return blockedPrivateTransport(runtime, networkState, {
924
- command: `ornn vpn-connections list ${privateTarget}`,
925
- description: recoverable
926
- ? "Inspect organization VPN connectivity before retrying."
927
- : "Wait for organization networking to become ready, then retry connect.",
928
- type: "command",
929
- }, {
930
- private_network: privateNetwork,
931
- private_target: { reservation_id: privateTarget },
932
- vpn_connection: null,
933
- }, privateTarget);
934
- }
935
- const connections = (await listVpnPayloads(context, privateTarget))
936
- .map((payload) => projectVpnConnection(payload, privateTarget))
937
- .sort(compareVpnConnections);
938
- if (connections.length === 0) {
939
- return runtime.actionRequired({
940
- action: {
941
- command: `ornn vpn-connections configure ${privateTarget} --guided`,
942
- description: "Provide one VPN peer and explicit configuration destination, then retry connect.",
943
- type: "command",
944
- },
945
- data: {
946
- private_network: privateNetwork,
947
- private_target: { reservation_id: privateTarget },
948
- vpn_connection: null,
949
- },
950
- resume: { kind: "connect", ref: privateTarget },
951
- });
952
- }
953
- const readyConnections = connections.filter((connection) => record(connection.lifecycle).class === "ready");
954
- if (readyConnections.length === 0) {
955
- const connection = connections.find((candidate) => ["pending", "working"].includes(String(record(candidate.lifecycle).class))) ??
956
- connections.find((candidate) => record(candidate.lifecycle).class === "failed") ??
957
- connections[0];
958
- const state = record(connection.lifecycle);
959
- const stateClass = String(state.class);
960
- const id = text(connection.id);
961
- const failed = stateClass === "failed";
962
- const ended = stateClass === "ended";
963
- const action = failed && id
964
- ? {
965
- command: `ornn vpn-connections disconnect ${privateTarget} ${id}`,
966
- description: "Remove the failed VPN connection before configuring a replacement.",
967
- type: "command",
968
- }
969
- : ended
970
- ? {
971
- command: `ornn vpn-connections configure ${privateTarget} --guided`,
972
- description: "Configure a new VPN connection, then retry connect.",
973
- type: "command",
974
- }
975
- : {
976
- command: `ornn vpn-connections configure ${privateTarget} --guided`,
977
- description: "Reapply the pending VPN connection, then retry connect.",
978
- type: "command",
979
- };
980
- return blockedPrivateTransport(runtime, state, action, {
981
- private_network: privateNetwork,
982
- private_target: { reservation_id: privateTarget },
983
- vpn_connection: connection,
984
- }, privateTarget);
985
- }
986
- const connection = readyConnections.find((candidate) => {
987
- const address = text(candidate.assigned_address);
988
- return Boolean(address && runtime.hasLocalNetworkAddress?.(address) === true);
989
- }) ?? readyConnections[0];
990
- const assignedAddress = text(connection.assigned_address);
991
- if (!assignedAddress || runtime.hasLocalNetworkAddress?.(assignedAddress) !== true) {
992
- return runtime.actionRequired({
993
- action: {
994
- command: `ornn vpn-connections configure ${privateTarget} --guided`,
995
- description: "Export a complete WireGuard configuration, activate it locally, then retry connect.",
996
- type: "command",
997
- },
998
- data: {
999
- private_network: privateNetwork,
1000
- private_target: { reservation_id: privateTarget },
1001
- vpn_connection: connection,
1002
- },
1003
- resume: { kind: "connect", ref: privateTarget },
1004
- });
1005
- }
1006
- if (runtime.continueConnect) {
1007
- const continuation = await runtime.continueConnect({
1008
- ...(resolved ?? {}),
1009
- privateNetwork,
1010
- reservationId: privateTarget,
1011
- vpnConnection: connection,
1012
- });
1013
- if (continuation)
1014
- return runtime.result(continuation);
1015
- }
1016
- return runtime.result({
1017
- data: {
1018
- private_network: privateNetwork,
1019
- private_target: { reservation_id: privateTarget },
1020
- vpn_connection: connection,
1021
- },
1022
- outcome: { class: "ready", phase: "private_transport_ready" },
1023
- presentation: {
1024
- lines: ["VPN connection is ready for private access.", ...vpnLines(connection)],
1025
- },
1026
- });
1027
- }
1028
- function customerResource(specification) {
1029
- return defineCapability({ ...specification, mcp: false, slack: false });
1030
- }
1031
- export const privateNetworkListCapability = customerResource({
1032
- id: "networks.list",
1033
- domain: "networks",
1034
- roles: ["user"],
1035
- mutation: "read",
1036
- input: listInput,
1037
- description: "List customer private networks with bounded pagination.",
1038
- cli: {
1039
- command: ["private-networks", "list"],
1040
- vnext: {
1041
- arguments: "semantic",
1042
- audience: "customer",
1043
- category: "resource",
1044
- order: 500,
1045
- outcome: "List private networks without exposing owner or supplier details.",
1046
- human: "ornn private-networks list [--limit <1-500>] [--cursor <cursor>]",
1047
- automation: "ornn private-networks list --format json [--limit <1-500>] [--cursor <cursor>]",
1048
- related: ["private-networks show"],
1049
- },
1050
- },
1051
- execute: listPrivateNetworks,
1052
- });
1053
- export const privateNetworkShowCapability = customerResource({
1054
- id: "networks.show",
1055
- domain: "networks",
1056
- roles: ["user"],
1057
- mutation: "read",
1058
- input: noOptionsInput,
1059
- description: "Show one exact customer private network.",
1060
- cli: {
1061
- command: ["private-networks", "show"],
1062
- vnext: {
1063
- arguments: "semantic",
1064
- audience: "customer",
1065
- category: "resource",
1066
- order: 501,
1067
- outcome: "Inspect one exact private network and its readiness.",
1068
- human: "ornn private-networks show <exact-name-or-id>",
1069
- automation: "ornn private-networks show <exact-name-or-id> --format json",
1070
- acceptedReferences: ["canonical private-network ID", "exact unique private-network name"],
1071
- related: ["private-networks list"],
1072
- },
1073
- },
1074
- execute: showPrivateNetwork,
1075
- });
1076
- export const privateNetworkCreateCapability = customerResource({
1077
- id: "networks.create",
1078
- domain: "networks",
1079
- roles: ["user"],
1080
- mutation: "preview-confirm",
1081
- input: networkCreateInput,
1082
- description: "Create or safely replay a named customer private network.",
1083
- cli: {
1084
- command: ["private-networks", "create"],
1085
- vnext: {
1086
- arguments: "semantic",
1087
- audience: "customer",
1088
- category: "resource",
1089
- order: 502,
1090
- outcome: "Create one reviewed private network with name-based durable replay.",
1091
- human: "ornn private-networks create --name <name> [--cidr <cidr>]",
1092
- automation: "ornn private-networks create --name <name> [--cidr <cidr>] --yes --idempotency-key <key> --format json",
1093
- review: "Review the normalized name and CIDR before creation.",
1094
- resumableStates: ["ready"],
1095
- related: ["private-networks list"],
1096
- },
1097
- },
1098
- execute: createPrivateNetwork,
1099
- });
1100
- export const privateNetworkUpdateCapability = customerResource({
1101
- id: "networks.update",
1102
- domain: "networks",
1103
- roles: ["user"],
1104
- mutation: "preview-confirm",
1105
- input: networkUpdateInput,
1106
- description: "Rename one exact customer private network.",
1107
- cli: {
1108
- command: ["private-networks", "update"],
1109
- vnext: {
1110
- arguments: "semantic",
1111
- audience: "customer",
1112
- category: "resource",
1113
- order: 503,
1114
- outcome: "Apply one reviewed private-network name goal.",
1115
- human: "ornn private-networks update <exact-name-or-id> --name <new-name>",
1116
- automation: "ornn private-networks update <exact-name-or-id> --name <new-name> --yes --idempotency-key <key> --format json",
1117
- acceptedReferences: ["canonical private-network ID", "exact unique private-network name"],
1118
- review: "Review the exact private network and normalized new name.",
1119
- related: ["private-networks show"],
1120
- },
1121
- },
1122
- execute: updatePrivateNetwork,
1123
- });
1124
- export const privateNetworkDeleteCapability = customerResource({
1125
- id: "networks.delete",
1126
- domain: "networks",
1127
- roles: ["user"],
1128
- mutation: "preview-confirm",
1129
- input: noOptionsInput,
1130
- description: "Delete an unattached customer private network.",
1131
- cli: {
1132
- command: ["private-networks", "delete"],
1133
- vnext: {
1134
- arguments: "semantic",
1135
- audience: "customer",
1136
- category: "resource",
1137
- order: 504,
1138
- outcome: "Delete a private network when the owner permits deletion.",
1139
- human: "ornn private-networks delete <exact-name-or-id>",
1140
- automation: "ornn private-networks delete <exact-name-or-id> --yes --idempotency-key <key> --format json",
1141
- acceptedReferences: ["canonical private-network ID", "exact unique private-network name"],
1142
- review: "Review the exact organization network before permanent deletion.",
1143
- related: ["private-networks list"],
1144
- },
1145
- },
1146
- execute: deletePrivateNetwork,
1147
- });
1148
- export const vpnConnectionListCapability = customerResource({
1149
- id: "vpn.connections.list",
1150
- domain: "vpn",
1151
- roles: ["user"],
1152
- mutation: "read",
1153
- input: listInput,
1154
- description: "List named VPN connections for one exact private target.",
1155
- cli: {
1156
- command: ["vpn-connections", "list"],
1157
- vnext: {
1158
- arguments: "semantic",
1159
- audience: "customer",
1160
- category: "resource",
1161
- order: 520,
1162
- outcome: "List safe VPN-connection metadata without configuration bytes or backend terminology.",
1163
- human: "ornn vpn-connections list <canonical-reservation-id> [--limit <1-500>] [--cursor <cursor>]",
1164
- automation: "ornn vpn-connections list <canonical-reservation-id> --format json [--limit <1-500>] [--cursor <cursor>]",
1165
- acceptedReferences: ["canonical capacity-reservation ID"],
1166
- related: ["vpn-connections configure", "connect"],
1167
- },
1168
- },
1169
- execute: listVpnConnections,
1170
- });
1171
- export const vpnConnectionConfigureCapability = customerResource({
1172
- id: "vpn.connections.configure",
1173
- domain: "vpn",
1174
- roles: ["user"],
1175
- mutation: "preview-confirm",
1176
- input: vpnConfigureInput,
1177
- description: "Configure and explicitly export one named VPN connection.",
1178
- cli: {
1179
- command: ["vpn-connections", "configure"],
1180
- vnext: {
1181
- arguments: "semantic",
1182
- audience: "customer",
1183
- category: "resource",
1184
- order: 521,
1185
- outcome: "Configure or replay one VPN connection and explicitly export its secret configuration.",
1186
- human: "ornn vpn-connections configure <canonical-reservation-id> --name <name> --private-key <path> (--print | --output <path>)",
1187
- automation: "ornn vpn-connections configure <canonical-reservation-id> --name <name> --private-key <path> --output <path> --yes --idempotency-key <key> --format json",
1188
- acceptedReferences: ["canonical capacity-reservation ID"],
1189
- review: "Review the exact private target, locally derived WireGuard public key, connection name, and explicit secret destination.",
1190
- resumableStates: ["ready"],
1191
- related: ["connect", "vpn-connections disconnect"],
1192
- },
1193
- },
1194
- execute: configureVpnConnection,
1195
- });
1196
- export const vpnConnectionDisconnectCapability = customerResource({
1197
- id: "vpn.connections.disconnect",
1198
- domain: "vpn",
1199
- roles: ["user"],
1200
- mutation: "preview-confirm",
1201
- input: noOptionsInput,
1202
- description: "Disconnect one exact named VPN connection.",
1203
- cli: {
1204
- command: ["vpn-connections", "disconnect"],
1205
- vnext: {
1206
- arguments: "semantic",
1207
- audience: "customer",
1208
- category: "resource",
1209
- order: 522,
1210
- outcome: "Disconnect one VPN connection without deleting its private network.",
1211
- human: "ornn vpn-connections disconnect <canonical-reservation-id> <exact-name-or-id>",
1212
- automation: "ornn vpn-connections disconnect <canonical-reservation-id> <exact-name-or-id> --yes --idempotency-key <key> --format json",
1213
- acceptedReferences: [
1214
- "canonical capacity-reservation ID",
1215
- "canonical or exact unique VPN-connection reference",
1216
- ],
1217
- review: "Review the exact VPN connection before ending private access.",
1218
- resumableStates: ["ended"],
1219
- related: ["vpn-connections configure"],
1220
- },
1221
- },
1222
- execute: disconnectVpnConnection,
1223
- });
1224
- export const connectCapability = customerResource({
1225
- id: "vpn.connect",
1226
- domain: "vpn",
1227
- roles: ["user"],
1228
- mutation: "read",
1229
- input: connectInput,
1230
- description: "Connect to one exact native machine or cluster target through recoverable private transport when required.",
1231
- cli: {
1232
- command: ["connect"],
1233
- vnext: {
1234
- arguments: "semantic",
1235
- audience: "customer",
1236
- category: "journey",
1237
- order: 80,
1238
- outcome: "Open or render native access from exact machine, cluster, or reservation facts.",
1239
- human: "ornn connect [<exact-hostname-or-canonical-machine-id-or-cluster-id-or-reservation-id>] [--identity-file <path>] [--user <login>] [--output <path>] [--print] [--overwrite]",
1240
- automation: "ornn connect <canonical-machine-or-cluster-id> [--identity-file <path>] [--user <login>] [--output <path>] [--print] [--overwrite] --format json",
1241
- acceptedReferences: [
1242
- "canonical machine ID",
1243
- "canonical cluster ID",
1244
- "exact unique hostname",
1245
- "canonical capacity-reservation ID",
1246
- "invocation-local cluster choice from reservation, location, access mode, hardware, and node facts",
1247
- ],
1248
- resumableStates: ["action_required", "working", "ready"],
1249
- related: ["launch", "vpn-connections configure", "clusters show"],
1250
- },
1251
- },
1252
- execute: connectPrivateTarget,
1253
- });
1254
- export const networkCapabilities = [
1255
- privateNetworkListCapability,
1256
- privateNetworkShowCapability,
1257
- privateNetworkCreateCapability,
1258
- privateNetworkUpdateCapability,
1259
- privateNetworkDeleteCapability,
1260
- vpnConnectionListCapability,
1261
- vpnConnectionConfigureCapability,
1262
- vpnConnectionDisconnectCapability,
1263
- connectCapability,
1264
- ];