@cdot65/prisma-airs-cli 3.3.0 → 4.0.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 +26 -2
- package/dist/{chunk-2VIUZRPB.js → chunk-W5YDJS7H.js} +124 -34
- package/dist/cli/index.js +834 -464
- package/dist/index.d.ts +83 -1
- package/dist/index.js +1 -1
- package/package.json +15 -3
package/dist/cli/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
sanitizeFilename,
|
|
21
21
|
validateTopic,
|
|
22
22
|
writeBackupFile
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-W5YDJS7H.js";
|
|
24
24
|
|
|
25
25
|
// src/cli/index.ts
|
|
26
26
|
import "dotenv/config";
|
|
@@ -187,9 +187,15 @@ var SdkAiGatewayService = class {
|
|
|
187
187
|
workspaceSlug,
|
|
188
188
|
days,
|
|
189
189
|
totalCents: raw.data.total,
|
|
190
|
+
totalUsd: raw.data.total / 100,
|
|
190
191
|
avgCents: raw.data.avg,
|
|
192
|
+
avgUsd: raw.data.avg / 100,
|
|
191
193
|
quotaExceeded: raw.data.isQuotaExceeded,
|
|
192
|
-
records: raw.data.records.map((r) => ({
|
|
194
|
+
records: raw.data.records.map((r) => ({
|
|
195
|
+
date: r.x,
|
|
196
|
+
costCents: r.y,
|
|
197
|
+
costUsd: r.y / 100
|
|
198
|
+
}))
|
|
193
199
|
};
|
|
194
200
|
}
|
|
195
201
|
/** Re-read after a write, falling back to the (partial) write response if the get fails. */
|
|
@@ -249,7 +255,11 @@ import { dump as yamlDump } from "js-yaml";
|
|
|
249
255
|
|
|
250
256
|
// src/cli/renderer/common.ts
|
|
251
257
|
import chalk2 from "chalk";
|
|
258
|
+
import { dump } from "js-yaml";
|
|
259
|
+
var CliUsageError = class extends Error {
|
|
260
|
+
};
|
|
252
261
|
function fail(err) {
|
|
262
|
+
if (err instanceof CliUsageError) usageError(err.message);
|
|
253
263
|
const message = err instanceof Error ? err.message : String(err);
|
|
254
264
|
const status = err?.status ?? err?.statusCode;
|
|
255
265
|
console.error(chalk2.red(`
|
|
@@ -267,44 +277,90 @@ function usageError(message) {
|
|
|
267
277
|
`));
|
|
268
278
|
process.exit(2);
|
|
269
279
|
}
|
|
270
|
-
var OUTPUT_FORMATS = [
|
|
280
|
+
var OUTPUT_FORMATS = [
|
|
281
|
+
"pretty",
|
|
282
|
+
"table",
|
|
283
|
+
"markdown",
|
|
284
|
+
"csv",
|
|
285
|
+
"json",
|
|
286
|
+
"yaml"
|
|
287
|
+
];
|
|
288
|
+
async function resolveOutput(command, opts, resolution = {}) {
|
|
289
|
+
const localIsExplicit = command.getOptionValueSource?.("output") === "cli";
|
|
290
|
+
let rootCommand = command;
|
|
291
|
+
while (rootCommand.parent) rootCommand = rootCommand.parent;
|
|
292
|
+
const globalIsExplicit = rootCommand.getOptionValueSource?.("output") === "cli";
|
|
293
|
+
const globalOutput = globalIsExplicit ? rootCommand.opts().output : void 0;
|
|
294
|
+
let configured;
|
|
295
|
+
try {
|
|
296
|
+
configured = (await loadConfig()).defaultOutput;
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (process.env.PANW_CLI_OUTPUT !== void 0) configured = process.env.PANW_CLI_OUTPUT;
|
|
299
|
+
else throw error;
|
|
300
|
+
}
|
|
301
|
+
const candidate = String(
|
|
302
|
+
localIsExplicit ? opts.output : globalOutput ?? configured ?? "pretty"
|
|
303
|
+
);
|
|
304
|
+
if (!OUTPUT_FORMATS.includes(candidate))
|
|
305
|
+
throw new CliUsageError(
|
|
306
|
+
`Invalid output format '${candidate}'. Expected: ${OUTPUT_FORMATS.join(", ")}`
|
|
307
|
+
);
|
|
308
|
+
const format = candidate;
|
|
309
|
+
const allowed = resolution.allowed ?? OUTPUT_FORMATS;
|
|
310
|
+
if (!allowed.includes(format))
|
|
311
|
+
throw new CliUsageError(
|
|
312
|
+
`Output format '${format}' is not supported here. Expected: ${allowed.join(", ")}`
|
|
313
|
+
);
|
|
314
|
+
return format;
|
|
315
|
+
}
|
|
316
|
+
function displayValue(value) {
|
|
317
|
+
if (value == null) return "";
|
|
318
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
319
|
+
}
|
|
320
|
+
function csvCell(value) {
|
|
321
|
+
const text = displayValue(value);
|
|
322
|
+
return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
323
|
+
}
|
|
324
|
+
function markdownCell(value) {
|
|
325
|
+
return displayValue(value).replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r?\n/g, "<br>");
|
|
326
|
+
}
|
|
271
327
|
function formatOutput(rows, columns, format) {
|
|
272
|
-
if (rows.length === 0)
|
|
273
|
-
|
|
328
|
+
if (rows.length === 0) {
|
|
329
|
+
if (format === "json") return "[]";
|
|
330
|
+
if (format === "yaml") return "[]\n";
|
|
331
|
+
return "";
|
|
332
|
+
}
|
|
333
|
+
const projected = rows.map((row) => columns.map((column) => row[column.key]));
|
|
274
334
|
switch (format) {
|
|
275
335
|
case "json":
|
|
276
|
-
return JSON.stringify(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
);
|
|
293
|
-
return [header, ...lines].join("\n");
|
|
294
|
-
}
|
|
295
|
-
case "yaml": {
|
|
296
|
-
return rows.map((r) => columns.map((c) => `${c.key}: ${vals(r, c.key)}`).join("\n")).join("\n---\n");
|
|
336
|
+
return JSON.stringify(rows, null, 2);
|
|
337
|
+
case "yaml":
|
|
338
|
+
return dump(rows, { noRefs: true, lineWidth: -1 }).trimEnd();
|
|
339
|
+
case "csv":
|
|
340
|
+
return [
|
|
341
|
+
columns.map((column) => csvCell(column.label)).join(","),
|
|
342
|
+
...projected.map((values) => values.map(csvCell).join(","))
|
|
343
|
+
].join("\n");
|
|
344
|
+
case "markdown": {
|
|
345
|
+
const header = `| ${columns.map((column) => markdownCell(column.label)).join(" | ")} |`;
|
|
346
|
+
const divider = `| ${columns.map(() => "---").join(" | ")} |`;
|
|
347
|
+
return [
|
|
348
|
+
header,
|
|
349
|
+
divider,
|
|
350
|
+
...projected.map((values) => `| ${values.map(markdownCell).join(" | ")} |`)
|
|
351
|
+
].join("\n");
|
|
297
352
|
}
|
|
298
353
|
case "table": {
|
|
354
|
+
const values = projected.map((row) => row.map(displayValue));
|
|
299
355
|
const widths = columns.map(
|
|
300
|
-
(
|
|
356
|
+
(column, index) => Math.max(column.label.length, ...values.map((row) => row[index].length))
|
|
301
357
|
);
|
|
302
|
-
const
|
|
303
|
-
const header = columns.map((
|
|
304
|
-
const body =
|
|
305
|
-
(
|
|
358
|
+
const separator = widths.map((width) => "\u2500".repeat(width + 2)).join("\u253C");
|
|
359
|
+
const header = columns.map((column, index) => ` ${column.label.padEnd(widths[index])} `).join("\u2502");
|
|
360
|
+
const body = values.map(
|
|
361
|
+
(row) => row.map((value, index) => ` ${value.padEnd(widths[index])} `).join("\u2502")
|
|
306
362
|
);
|
|
307
|
-
return [header,
|
|
363
|
+
return [header, separator, ...body].join("\n");
|
|
308
364
|
}
|
|
309
365
|
default:
|
|
310
366
|
return "";
|
|
@@ -403,6 +459,65 @@ ${INDENT}${chalk3.bold(label)}
|
|
|
403
459
|
}
|
|
404
460
|
};
|
|
405
461
|
|
|
462
|
+
// src/cli/renderer/view.ts
|
|
463
|
+
import { dump as dump2 } from "js-yaml";
|
|
464
|
+
function asRecord(item) {
|
|
465
|
+
return item;
|
|
466
|
+
}
|
|
467
|
+
function project(view, item) {
|
|
468
|
+
const source = asRecord(item);
|
|
469
|
+
return Object.fromEntries(
|
|
470
|
+
view.columns.map((column) => [column.key, column.get ? column.get(item) : source[column.key]])
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
function renderPageStatus(page) {
|
|
474
|
+
if (!page) return;
|
|
475
|
+
if (page.all) ui.status(`Showing all ${page.total ?? page.returned}`);
|
|
476
|
+
else if (page.total !== void 0)
|
|
477
|
+
ui.status(
|
|
478
|
+
`Showing ${page.returned} of ${page.total}${page.next !== void 0 ? ` (next --offset ${page.next})` : ""}`
|
|
479
|
+
);
|
|
480
|
+
else if (page.next !== void 0) ui.status(`Showing ${page.returned} (more available)`);
|
|
481
|
+
else ui.status(`Showing ${page.returned}`);
|
|
482
|
+
}
|
|
483
|
+
function emitList(view, items, format, opts = {}) {
|
|
484
|
+
if (format === "pretty") {
|
|
485
|
+
if (items.length === 0) ui.emptyList(view.name);
|
|
486
|
+
else view.pretty.list(items);
|
|
487
|
+
} else {
|
|
488
|
+
const rows = format === "json" || format === "yaml" ? items.map((item) => view.structured?.(item) ?? asRecord(item)) : items.map((item) => project(view, item));
|
|
489
|
+
const rendered = formatOutput(rows, view.columns, format);
|
|
490
|
+
if (rendered) console.log(rendered);
|
|
491
|
+
}
|
|
492
|
+
renderPageStatus(opts.page);
|
|
493
|
+
}
|
|
494
|
+
function emitDetail(view, item, format) {
|
|
495
|
+
if (format === "pretty") {
|
|
496
|
+
view.pretty.detail(item);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
const structured = view.structured?.(item) ?? asRecord(item);
|
|
500
|
+
if (format === "json") console.log(JSON.stringify(structured, null, 2));
|
|
501
|
+
else if (format === "yaml")
|
|
502
|
+
console.log(dump2(structured, { noRefs: true, lineWidth: -1 }).trimEnd());
|
|
503
|
+
else {
|
|
504
|
+
const rows = Object.entries(structured).map(([key, value]) => ({
|
|
505
|
+
key,
|
|
506
|
+
value: value != null && typeof value === "object" ? JSON.stringify(value) : value
|
|
507
|
+
}));
|
|
508
|
+
console.log(
|
|
509
|
+
formatOutput(
|
|
510
|
+
rows,
|
|
511
|
+
[
|
|
512
|
+
{ key: "key", label: "Key" },
|
|
513
|
+
{ key: "value", label: "Value" }
|
|
514
|
+
],
|
|
515
|
+
format
|
|
516
|
+
)
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
406
521
|
// src/cli/renderer/aigateway.ts
|
|
407
522
|
function renderAiGatewayHeader() {
|
|
408
523
|
ui.header("Prisma AIRS \u2014 AI Gateway", "Gateway workspace operations");
|
|
@@ -498,7 +613,17 @@ function renderWorkspaceDetail(workspace, format = "pretty") {
|
|
|
498
613
|
}
|
|
499
614
|
function renderCostReport(report, format = "pretty") {
|
|
500
615
|
if (format !== "pretty") {
|
|
501
|
-
|
|
616
|
+
emitDetail(
|
|
617
|
+
{
|
|
618
|
+
name: "cost report",
|
|
619
|
+
columns: [],
|
|
620
|
+
pretty: { list() {
|
|
621
|
+
}, detail() {
|
|
622
|
+
} }
|
|
623
|
+
},
|
|
624
|
+
report,
|
|
625
|
+
format
|
|
626
|
+
);
|
|
502
627
|
return;
|
|
503
628
|
}
|
|
504
629
|
const dollars = (cents) => `$${(cents / 100).toFixed(2)}`;
|
|
@@ -597,60 +722,67 @@ function pageMeta(page, returned) {
|
|
|
597
722
|
returned
|
|
598
723
|
};
|
|
599
724
|
}
|
|
600
|
-
function
|
|
601
|
-
|
|
602
|
-
const rows = content.map(toRow);
|
|
603
|
-
if (fmt === "json" || fmt === "yaml") {
|
|
604
|
-
emitStructured({ items: rows, page: pageMeta(page, content.length) }, fmt);
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
if (content.length === 0) {
|
|
608
|
-
ui.emptyList(header.toLowerCase());
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
if (fmt === "pretty") {
|
|
612
|
-
ui.section(`${header}:`);
|
|
613
|
-
for (const item of content) console.log(prettyLine(item));
|
|
614
|
-
const meta = pageMeta(page, content.length);
|
|
615
|
-
console.log();
|
|
616
|
-
ui.dim(
|
|
617
|
-
`page=${meta.number} size=${meta.size} returned=${meta.returned} total=${meta.total ?? "?"}`
|
|
618
|
-
);
|
|
619
|
-
console.log();
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
console.log(formatOutput(rows, columns, fmt));
|
|
725
|
+
function camelKey(key) {
|
|
726
|
+
return key.replace(/[_-]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
623
727
|
}
|
|
624
|
-
function
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
728
|
+
function camelize(value) {
|
|
729
|
+
if (Array.isArray(value)) return value.map(camelize);
|
|
730
|
+
if (value && typeof value === "object") {
|
|
731
|
+
return Object.fromEntries(
|
|
732
|
+
Object.entries(value).map(([key, child]) => [
|
|
733
|
+
camelKey(key),
|
|
734
|
+
camelize(child)
|
|
735
|
+
])
|
|
736
|
+
);
|
|
629
737
|
}
|
|
630
|
-
return
|
|
631
|
-
}
|
|
632
|
-
function toKey(label) {
|
|
633
|
-
return label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
738
|
+
return value;
|
|
634
739
|
}
|
|
635
|
-
function
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
740
|
+
function emitList2(page, fmt, header, toRow, columns, prettyLine) {
|
|
741
|
+
const content = Array.isArray(page?.content) ? page.content : [];
|
|
742
|
+
const meta = pageMeta(page, content.length);
|
|
743
|
+
const view = {
|
|
744
|
+
name: header.toLowerCase(),
|
|
745
|
+
columns: columns.map((column) => ({
|
|
746
|
+
...column,
|
|
747
|
+
get: (item) => toRow(item)[column.key]
|
|
748
|
+
})),
|
|
749
|
+
structured: (item) => camelize(item),
|
|
750
|
+
pretty: {
|
|
751
|
+
list(items) {
|
|
752
|
+
ui.section(`${header}:`);
|
|
753
|
+
for (const item of items) console.log(prettyLine(item));
|
|
754
|
+
console.log();
|
|
755
|
+
},
|
|
756
|
+
detail() {
|
|
757
|
+
}
|
|
646
758
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
759
|
+
};
|
|
760
|
+
const total = typeof meta.total === "number" ? meta.total : void 0;
|
|
761
|
+
const number = Number(meta.number ?? 0);
|
|
762
|
+
const size = Number(meta.size ?? content.length);
|
|
763
|
+
const next = total !== void 0 && (number + 1) * size < total ? (number + 1) * size : void 0;
|
|
764
|
+
emitList(view, content, fmt, { page: { returned: content.length, total, next } });
|
|
765
|
+
}
|
|
766
|
+
function emitDetail2(item, fmt, fields, title) {
|
|
767
|
+
const view = {
|
|
768
|
+
name: title.toLowerCase(),
|
|
769
|
+
columns: [],
|
|
770
|
+
structured: (value) => camelize(value),
|
|
771
|
+
pretty: {
|
|
772
|
+
list() {
|
|
773
|
+
},
|
|
774
|
+
detail() {
|
|
775
|
+
ui.section(`${title}:`);
|
|
776
|
+
ui.keyValue(
|
|
777
|
+
fields.filter(
|
|
778
|
+
(field) => field.value !== void 0 && field.value !== null && field.value !== ""
|
|
779
|
+
).map((field) => [field.label, field.value])
|
|
780
|
+
);
|
|
781
|
+
console.log();
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
emitDetail(view, item, fmt);
|
|
654
786
|
}
|
|
655
787
|
function ackObject(verb, item) {
|
|
656
788
|
const out = { action: verb };
|
|
@@ -681,7 +813,7 @@ function emitIdAck(verb, id) {
|
|
|
681
813
|
}
|
|
682
814
|
var dlpFilteringProfiles = {
|
|
683
815
|
renderList(page, fmt) {
|
|
684
|
-
|
|
816
|
+
emitList2(
|
|
685
817
|
page,
|
|
686
818
|
fmt,
|
|
687
819
|
"Data Filtering Profiles",
|
|
@@ -711,7 +843,7 @@ var dlpFilteringProfiles = {
|
|
|
711
843
|
);
|
|
712
844
|
},
|
|
713
845
|
renderGet(item, fmt) {
|
|
714
|
-
|
|
846
|
+
emitDetail2(
|
|
715
847
|
item,
|
|
716
848
|
fmt,
|
|
717
849
|
[
|
|
@@ -740,7 +872,7 @@ var dlpFilteringProfiles = {
|
|
|
740
872
|
};
|
|
741
873
|
var dlpPatterns = {
|
|
742
874
|
renderList(page, fmt) {
|
|
743
|
-
|
|
875
|
+
emitList2(
|
|
744
876
|
page,
|
|
745
877
|
fmt,
|
|
746
878
|
"Data Patterns",
|
|
@@ -769,7 +901,7 @@ var dlpPatterns = {
|
|
|
769
901
|
);
|
|
770
902
|
},
|
|
771
903
|
renderGet(item, fmt) {
|
|
772
|
-
|
|
904
|
+
emitDetail2(
|
|
773
905
|
item,
|
|
774
906
|
fmt,
|
|
775
907
|
[
|
|
@@ -808,7 +940,7 @@ var dlpPatterns = {
|
|
|
808
940
|
};
|
|
809
941
|
var dlpProfiles = {
|
|
810
942
|
renderList(page, fmt) {
|
|
811
|
-
|
|
943
|
+
emitList2(
|
|
812
944
|
page,
|
|
813
945
|
fmt,
|
|
814
946
|
"Data Profiles",
|
|
@@ -837,7 +969,7 @@ var dlpProfiles = {
|
|
|
837
969
|
);
|
|
838
970
|
},
|
|
839
971
|
renderGet(item, fmt) {
|
|
840
|
-
|
|
972
|
+
emitDetail2(
|
|
841
973
|
item,
|
|
842
974
|
fmt,
|
|
843
975
|
[
|
|
@@ -865,7 +997,7 @@ var dlpProfiles = {
|
|
|
865
997
|
};
|
|
866
998
|
var dlpDictionaries = {
|
|
867
999
|
renderList(page, fmt) {
|
|
868
|
-
|
|
1000
|
+
emitList2(
|
|
869
1001
|
page,
|
|
870
1002
|
fmt,
|
|
871
1003
|
"Data Dictionaries",
|
|
@@ -894,7 +1026,7 @@ var dlpDictionaries = {
|
|
|
894
1026
|
);
|
|
895
1027
|
},
|
|
896
1028
|
renderGet(item, fmt) {
|
|
897
|
-
|
|
1029
|
+
emitDetail2(
|
|
898
1030
|
item,
|
|
899
1031
|
fmt,
|
|
900
1032
|
[
|
|
@@ -989,7 +1121,15 @@ function renderEvalTerminal(output) {
|
|
|
989
1121
|
|
|
990
1122
|
// src/cli/renderer/modelsecurity.ts
|
|
991
1123
|
import chalk7 from "chalk";
|
|
992
|
-
|
|
1124
|
+
function resourceView(name, columns, pretty) {
|
|
1125
|
+
return { name, columns, pretty };
|
|
1126
|
+
}
|
|
1127
|
+
function structuredList(name, items, columns, format, pretty) {
|
|
1128
|
+
emitList(resourceView(name, columns, { list: pretty, detail: () => void 0 }), items, format);
|
|
1129
|
+
}
|
|
1130
|
+
function structuredDetail(name, item, format, pretty) {
|
|
1131
|
+
emitDetail(resourceView(name, [], { list: () => void 0, detail: pretty }), item, format);
|
|
1132
|
+
}
|
|
993
1133
|
function renderModelSecurityHeader() {
|
|
994
1134
|
ui.header("Prisma AIRS \u2014 Model Security", "ML model supply chain security");
|
|
995
1135
|
}
|
|
@@ -1012,31 +1152,25 @@ function stateColor(state) {
|
|
|
1012
1152
|
}
|
|
1013
1153
|
}
|
|
1014
1154
|
function renderGroupList(groups, format = "pretty") {
|
|
1015
|
-
if (groups.length === 0) {
|
|
1016
|
-
ui.emptyList("security groups");
|
|
1017
|
-
return;
|
|
1018
|
-
}
|
|
1019
1155
|
if (format !== "pretty") {
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
{ key: "name", label: "Name" },
|
|
1032
|
-
{ key: "state", label: "State" },
|
|
1033
|
-
{ key: "sourceType", label: "Source Type" }
|
|
1034
|
-
],
|
|
1035
|
-
format
|
|
1036
|
-
)
|
|
1156
|
+
structuredList(
|
|
1157
|
+
"security groups",
|
|
1158
|
+
groups,
|
|
1159
|
+
[
|
|
1160
|
+
{ key: "uuid", label: "ID" },
|
|
1161
|
+
{ key: "name", label: "Name" },
|
|
1162
|
+
{ key: "state", label: "State" },
|
|
1163
|
+
{ key: "sourceType", label: "Source Type" }
|
|
1164
|
+
],
|
|
1165
|
+
format,
|
|
1166
|
+
() => void 0
|
|
1037
1167
|
);
|
|
1038
1168
|
return;
|
|
1039
1169
|
}
|
|
1170
|
+
if (groups.length === 0) {
|
|
1171
|
+
ui.emptyList("security groups");
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1040
1174
|
ui.section("Security Groups:");
|
|
1041
1175
|
for (const g of groups) {
|
|
1042
1176
|
ui.dim(g.uuid);
|
|
@@ -1046,12 +1180,8 @@ function renderGroupList(groups, format = "pretty") {
|
|
|
1046
1180
|
console.log();
|
|
1047
1181
|
}
|
|
1048
1182
|
function renderGroupDetail(group, format = "pretty") {
|
|
1049
|
-
if (format
|
|
1050
|
-
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1053
|
-
if (format === "yaml") {
|
|
1054
|
-
console.log(yamlDump3(group));
|
|
1183
|
+
if (format !== "pretty") {
|
|
1184
|
+
structuredDetail("security group", group, format, () => void 0);
|
|
1055
1185
|
return;
|
|
1056
1186
|
}
|
|
1057
1187
|
ui.section("Security Group Detail:");
|
|
@@ -1068,33 +1198,30 @@ function renderGroupDetail(group, format = "pretty") {
|
|
|
1068
1198
|
console.log();
|
|
1069
1199
|
}
|
|
1070
1200
|
function renderRuleList(rules, format = "pretty") {
|
|
1071
|
-
if (rules.length === 0) {
|
|
1072
|
-
ui.emptyList("security rules");
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
1201
|
if (format !== "pretty") {
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
],
|
|
1093
|
-
format
|
|
1094
|
-
)
|
|
1202
|
+
structuredList(
|
|
1203
|
+
"security rules",
|
|
1204
|
+
rules,
|
|
1205
|
+
[
|
|
1206
|
+
{ key: "uuid", label: "ID" },
|
|
1207
|
+
{ key: "name", label: "Name" },
|
|
1208
|
+
{ key: "ruleType", label: "Type" },
|
|
1209
|
+
{ key: "defaultState", label: "Default State" },
|
|
1210
|
+
{
|
|
1211
|
+
key: "compatibleSources",
|
|
1212
|
+
label: "Sources",
|
|
1213
|
+
get: (rule) => rule.compatibleSources.join(", ")
|
|
1214
|
+
}
|
|
1215
|
+
],
|
|
1216
|
+
format,
|
|
1217
|
+
() => void 0
|
|
1095
1218
|
);
|
|
1096
1219
|
return;
|
|
1097
1220
|
}
|
|
1221
|
+
if (rules.length === 0) {
|
|
1222
|
+
ui.emptyList("security rules");
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1098
1225
|
ui.section("Security Rules:");
|
|
1099
1226
|
for (const r of rules) {
|
|
1100
1227
|
ui.dim(r.uuid);
|
|
@@ -1106,7 +1233,11 @@ function renderRuleList(rules, format = "pretty") {
|
|
|
1106
1233
|
}
|
|
1107
1234
|
console.log();
|
|
1108
1235
|
}
|
|
1109
|
-
function renderRuleDetail(rule) {
|
|
1236
|
+
function renderRuleDetail(rule, format = "pretty") {
|
|
1237
|
+
if (format !== "pretty") {
|
|
1238
|
+
structuredDetail("security rule", rule, format, () => void 0);
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1110
1241
|
ui.section("Security Rule Detail:");
|
|
1111
1242
|
ui.keyValue([
|
|
1112
1243
|
["UUID", rule.uuid],
|
|
@@ -1137,7 +1268,21 @@ function renderRuleDetail(rule) {
|
|
|
1137
1268
|
}
|
|
1138
1269
|
console.log();
|
|
1139
1270
|
}
|
|
1140
|
-
function renderRuleInstanceList(instances) {
|
|
1271
|
+
function renderRuleInstanceList(instances, format = "pretty") {
|
|
1272
|
+
if (format !== "pretty") {
|
|
1273
|
+
structuredList(
|
|
1274
|
+
"rule instances",
|
|
1275
|
+
instances,
|
|
1276
|
+
[
|
|
1277
|
+
{ key: "uuid", label: "ID" },
|
|
1278
|
+
{ key: "securityRuleUuid", label: "Rule ID" },
|
|
1279
|
+
{ key: "state", label: "State" }
|
|
1280
|
+
],
|
|
1281
|
+
format,
|
|
1282
|
+
() => void 0
|
|
1283
|
+
);
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1141
1286
|
if (instances.length === 0) {
|
|
1142
1287
|
ui.emptyList("rule instances");
|
|
1143
1288
|
return;
|
|
@@ -1150,7 +1295,11 @@ function renderRuleInstanceList(instances) {
|
|
|
1150
1295
|
}
|
|
1151
1296
|
console.log();
|
|
1152
1297
|
}
|
|
1153
|
-
function renderRuleInstanceDetail(instance) {
|
|
1298
|
+
function renderRuleInstanceDetail(instance, format = "pretty") {
|
|
1299
|
+
if (format !== "pretty") {
|
|
1300
|
+
structuredDetail("rule instance", instance, format, () => void 0);
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1154
1303
|
ui.section("Rule Instance Detail:");
|
|
1155
1304
|
const pairs = [
|
|
1156
1305
|
["UUID", instance.uuid],
|
|
@@ -1175,37 +1324,26 @@ function renderRuleInstanceDetail(instance) {
|
|
|
1175
1324
|
console.log();
|
|
1176
1325
|
}
|
|
1177
1326
|
function renderMsScanList(scans, format = "pretty") {
|
|
1178
|
-
if (scans.length === 0) {
|
|
1179
|
-
ui.emptyList("scans");
|
|
1180
|
-
return;
|
|
1181
|
-
}
|
|
1182
1327
|
if (format !== "pretty") {
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
[
|
|
1196
|
-
{ key: "id", label: "ID" },
|
|
1197
|
-
{ key: "outcome", label: "Outcome" },
|
|
1198
|
-
{ key: "origin", label: "Origin" },
|
|
1199
|
-
{ key: "modelUri", label: "Model URI" },
|
|
1200
|
-
{ key: "passed", label: "Passed" },
|
|
1201
|
-
{ key: "failed", label: "Failed" },
|
|
1202
|
-
{ key: "createdAt", label: "Created" }
|
|
1203
|
-
],
|
|
1204
|
-
format
|
|
1205
|
-
)
|
|
1328
|
+
structuredList(
|
|
1329
|
+
"scans",
|
|
1330
|
+
scans,
|
|
1331
|
+
[
|
|
1332
|
+
{ key: "uuid", label: "ID" },
|
|
1333
|
+
{ key: "evalOutcome", label: "Outcome" },
|
|
1334
|
+
{ key: "scanOrigin", label: "Origin" },
|
|
1335
|
+
{ key: "modelUri", label: "Model URI" },
|
|
1336
|
+
{ key: "createdAt", label: "Created" }
|
|
1337
|
+
],
|
|
1338
|
+
format,
|
|
1339
|
+
() => void 0
|
|
1206
1340
|
);
|
|
1207
1341
|
return;
|
|
1208
1342
|
}
|
|
1343
|
+
if (scans.length === 0) {
|
|
1344
|
+
ui.emptyList("scans");
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1209
1347
|
ui.section("Model Security Scans:");
|
|
1210
1348
|
for (const s of scans) {
|
|
1211
1349
|
ui.dim(s.uuid);
|
|
@@ -1222,7 +1360,11 @@ function renderMsScanList(scans, format = "pretty") {
|
|
|
1222
1360
|
}
|
|
1223
1361
|
console.log();
|
|
1224
1362
|
}
|
|
1225
|
-
function renderMsScanDetail(scan) {
|
|
1363
|
+
function renderMsScanDetail(scan, format = "pretty") {
|
|
1364
|
+
if (format !== "pretty") {
|
|
1365
|
+
structuredDetail("scan", scan, format, () => void 0);
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1226
1368
|
ui.section("Scan Detail:");
|
|
1227
1369
|
const pairs = [
|
|
1228
1370
|
["UUID", scan.uuid],
|
|
@@ -1248,7 +1390,22 @@ function renderMsScanDetail(scan) {
|
|
|
1248
1390
|
}
|
|
1249
1391
|
console.log();
|
|
1250
1392
|
}
|
|
1251
|
-
function renderEvaluationList(evaluations) {
|
|
1393
|
+
function renderEvaluationList(evaluations, format = "pretty") {
|
|
1394
|
+
if (format !== "pretty") {
|
|
1395
|
+
structuredList(
|
|
1396
|
+
"evaluations",
|
|
1397
|
+
evaluations,
|
|
1398
|
+
[
|
|
1399
|
+
{ key: "uuid", label: "ID" },
|
|
1400
|
+
{ key: "ruleName", label: "Rule" },
|
|
1401
|
+
{ key: "result", label: "Result" },
|
|
1402
|
+
{ key: "ruleInstanceState", label: "State" }
|
|
1403
|
+
],
|
|
1404
|
+
format,
|
|
1405
|
+
() => void 0
|
|
1406
|
+
);
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1252
1409
|
if (evaluations.length === 0) {
|
|
1253
1410
|
ui.emptyList("evaluations");
|
|
1254
1411
|
return;
|
|
@@ -1262,7 +1419,11 @@ function renderEvaluationList(evaluations) {
|
|
|
1262
1419
|
}
|
|
1263
1420
|
console.log();
|
|
1264
1421
|
}
|
|
1265
|
-
function renderEvaluationDetail(evaluation) {
|
|
1422
|
+
function renderEvaluationDetail(evaluation, format = "pretty") {
|
|
1423
|
+
if (format !== "pretty") {
|
|
1424
|
+
structuredDetail("evaluation", evaluation, format, () => void 0);
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1266
1427
|
ui.section("Evaluation Detail:");
|
|
1267
1428
|
ui.keyValue([
|
|
1268
1429
|
["UUID", evaluation.uuid],
|
|
@@ -1275,7 +1436,22 @@ function renderEvaluationDetail(evaluation) {
|
|
|
1275
1436
|
]);
|
|
1276
1437
|
console.log();
|
|
1277
1438
|
}
|
|
1278
|
-
function renderViolationList(violations) {
|
|
1439
|
+
function renderViolationList(violations, format = "pretty") {
|
|
1440
|
+
if (format !== "pretty") {
|
|
1441
|
+
structuredList(
|
|
1442
|
+
"violations",
|
|
1443
|
+
violations,
|
|
1444
|
+
[
|
|
1445
|
+
{ key: "uuid", label: "ID" },
|
|
1446
|
+
{ key: "ruleName", label: "Rule" },
|
|
1447
|
+
{ key: "file", label: "File" },
|
|
1448
|
+
{ key: "threat", label: "Threat" }
|
|
1449
|
+
],
|
|
1450
|
+
format,
|
|
1451
|
+
() => void 0
|
|
1452
|
+
);
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1279
1455
|
if (violations.length === 0) {
|
|
1280
1456
|
ui.emptyList("violations");
|
|
1281
1457
|
return;
|
|
@@ -1289,7 +1465,11 @@ function renderViolationList(violations) {
|
|
|
1289
1465
|
}
|
|
1290
1466
|
console.log();
|
|
1291
1467
|
}
|
|
1292
|
-
function renderViolationDetail(violation) {
|
|
1468
|
+
function renderViolationDetail(violation, format = "pretty") {
|
|
1469
|
+
if (format !== "pretty") {
|
|
1470
|
+
structuredDetail("violation", violation, format, () => void 0);
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1293
1473
|
ui.section("Violation Detail:");
|
|
1294
1474
|
ui.keyValue([
|
|
1295
1475
|
["UUID", violation.uuid],
|
|
@@ -1302,7 +1482,22 @@ function renderViolationDetail(violation) {
|
|
|
1302
1482
|
]);
|
|
1303
1483
|
console.log();
|
|
1304
1484
|
}
|
|
1305
|
-
function renderFileList(files) {
|
|
1485
|
+
function renderFileList(files, format = "pretty") {
|
|
1486
|
+
if (format !== "pretty") {
|
|
1487
|
+
structuredList(
|
|
1488
|
+
"files",
|
|
1489
|
+
files,
|
|
1490
|
+
[
|
|
1491
|
+
{ key: "uuid", label: "ID" },
|
|
1492
|
+
{ key: "path", label: "Path" },
|
|
1493
|
+
{ key: "type", label: "Type" },
|
|
1494
|
+
{ key: "result", label: "Result" }
|
|
1495
|
+
],
|
|
1496
|
+
format,
|
|
1497
|
+
() => void 0
|
|
1498
|
+
);
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1306
1501
|
if (files.length === 0) {
|
|
1307
1502
|
ui.emptyList("files");
|
|
1308
1503
|
return;
|
|
@@ -1338,33 +1533,30 @@ function renderLabelValues(key, values) {
|
|
|
1338
1533
|
console.log();
|
|
1339
1534
|
}
|
|
1340
1535
|
function renderModelList(models, format = "pretty") {
|
|
1341
|
-
if (models.length === 0) {
|
|
1342
|
-
ui.emptyList("models");
|
|
1343
|
-
return;
|
|
1344
|
-
}
|
|
1345
1536
|
if (format !== "pretty") {
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
],
|
|
1363
|
-
format
|
|
1364
|
-
)
|
|
1537
|
+
structuredList(
|
|
1538
|
+
"models",
|
|
1539
|
+
models,
|
|
1540
|
+
[
|
|
1541
|
+
{ key: "uuid", label: "ID" },
|
|
1542
|
+
{ key: "name", label: "Name" },
|
|
1543
|
+
{ key: "latestVersionOutcome", label: "Outcome" },
|
|
1544
|
+
{
|
|
1545
|
+
key: "latestVersionFormats",
|
|
1546
|
+
label: "Formats",
|
|
1547
|
+
get: (model) => (model.latestVersionFormats ?? []).join(", ")
|
|
1548
|
+
},
|
|
1549
|
+
{ key: "latestVersionScanTime", label: "Last Scan" }
|
|
1550
|
+
],
|
|
1551
|
+
format,
|
|
1552
|
+
() => void 0
|
|
1365
1553
|
);
|
|
1366
1554
|
return;
|
|
1367
1555
|
}
|
|
1556
|
+
if (models.length === 0) {
|
|
1557
|
+
ui.emptyList("models");
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1368
1560
|
ui.section("Models:");
|
|
1369
1561
|
for (const m of models) {
|
|
1370
1562
|
ui.dim(m.uuid);
|
|
@@ -1376,7 +1568,7 @@ function renderModelList(models, format = "pretty") {
|
|
|
1376
1568
|
}
|
|
1377
1569
|
function renderModelDetail(model, format = "pretty") {
|
|
1378
1570
|
if (format !== "pretty") {
|
|
1379
|
-
|
|
1571
|
+
structuredDetail("model", model, format, () => void 0);
|
|
1380
1572
|
return;
|
|
1381
1573
|
}
|
|
1382
1574
|
ui.section("Model Detail:");
|
|
@@ -1403,33 +1595,26 @@ function renderModelDetail(model, format = "pretty") {
|
|
|
1403
1595
|
console.log();
|
|
1404
1596
|
}
|
|
1405
1597
|
function renderModelVersionList(versions, format = "pretty") {
|
|
1406
|
-
if (versions.length === 0) {
|
|
1407
|
-
ui.emptyList("versions");
|
|
1408
|
-
return;
|
|
1409
|
-
}
|
|
1410
1598
|
if (format !== "pretty") {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
{ key: "revision", label: "Revision" },
|
|
1424
|
-
{ key: "files", label: "Files" },
|
|
1425
|
-
{ key: "outcome", label: "Outcome" },
|
|
1426
|
-
{ key: "scanned", label: "Last Scan" }
|
|
1427
|
-
],
|
|
1428
|
-
format
|
|
1429
|
-
)
|
|
1599
|
+
structuredList(
|
|
1600
|
+
"versions",
|
|
1601
|
+
versions,
|
|
1602
|
+
[
|
|
1603
|
+
{ key: "uuid", label: "ID" },
|
|
1604
|
+
{ key: "revision", label: "Revision" },
|
|
1605
|
+
{ key: "fileCount", label: "Files" },
|
|
1606
|
+
{ key: "lastEvalOutcome", label: "Outcome" },
|
|
1607
|
+
{ key: "latestScanTime", label: "Last Scan" }
|
|
1608
|
+
],
|
|
1609
|
+
format,
|
|
1610
|
+
() => void 0
|
|
1430
1611
|
);
|
|
1431
1612
|
return;
|
|
1432
1613
|
}
|
|
1614
|
+
if (versions.length === 0) {
|
|
1615
|
+
ui.emptyList("versions");
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1433
1618
|
ui.section("Model Versions:");
|
|
1434
1619
|
for (const v of versions) {
|
|
1435
1620
|
ui.dim(v.uuid);
|
|
@@ -1441,7 +1626,7 @@ function renderModelVersionList(versions, format = "pretty") {
|
|
|
1441
1626
|
}
|
|
1442
1627
|
function renderModelVersionDetail(version, format = "pretty") {
|
|
1443
1628
|
if (format !== "pretty") {
|
|
1444
|
-
|
|
1629
|
+
structuredDetail("model version", version, format, () => void 0);
|
|
1445
1630
|
return;
|
|
1446
1631
|
}
|
|
1447
1632
|
ui.section("Model Version Detail:");
|
|
@@ -1473,31 +1658,12 @@ function renderModelVersionDetail(version, format = "pretty") {
|
|
|
1473
1658
|
console.log();
|
|
1474
1659
|
}
|
|
1475
1660
|
function renderModelFileList(files, format = "pretty") {
|
|
1476
|
-
if (
|
|
1477
|
-
|
|
1661
|
+
if (format !== "pretty") {
|
|
1662
|
+
renderFileList(files, format);
|
|
1478
1663
|
return;
|
|
1479
1664
|
}
|
|
1480
|
-
if (
|
|
1481
|
-
|
|
1482
|
-
id: f.uuid,
|
|
1483
|
-
path: f.path,
|
|
1484
|
-
type: f.type,
|
|
1485
|
-
formats: f.formats.join(", "),
|
|
1486
|
-
result: f.result
|
|
1487
|
-
}));
|
|
1488
|
-
console.log(
|
|
1489
|
-
formatOutput(
|
|
1490
|
-
rows,
|
|
1491
|
-
[
|
|
1492
|
-
{ key: "id", label: "ID" },
|
|
1493
|
-
{ key: "path", label: "Path" },
|
|
1494
|
-
{ key: "type", label: "Type" },
|
|
1495
|
-
{ key: "formats", label: "Formats" },
|
|
1496
|
-
{ key: "result", label: "Result" }
|
|
1497
|
-
],
|
|
1498
|
-
format
|
|
1499
|
-
)
|
|
1500
|
-
);
|
|
1665
|
+
if (files.length === 0) {
|
|
1666
|
+
ui.emptyList("files");
|
|
1501
1667
|
return;
|
|
1502
1668
|
}
|
|
1503
1669
|
renderFileList(files);
|
|
@@ -1505,7 +1671,7 @@ function renderModelFileList(files, format = "pretty") {
|
|
|
1505
1671
|
|
|
1506
1672
|
// src/cli/renderer/redteam.ts
|
|
1507
1673
|
import chalk8 from "chalk";
|
|
1508
|
-
import { dump as
|
|
1674
|
+
import { dump as yamlDump3 } from "js-yaml";
|
|
1509
1675
|
function renderRedteamHeader() {
|
|
1510
1676
|
ui.header("Prisma AIRS \u2014 AI Red Team", "Adversarial scan operations");
|
|
1511
1677
|
}
|
|
@@ -1825,7 +1991,7 @@ function renderTargetDetail(target, format = "pretty") {
|
|
|
1825
1991
|
if (format === "json") {
|
|
1826
1992
|
console.log(JSON.stringify(target, null, 2));
|
|
1827
1993
|
} else if (format === "yaml") {
|
|
1828
|
-
console.log(
|
|
1994
|
+
console.log(yamlDump3(target));
|
|
1829
1995
|
}
|
|
1830
1996
|
return;
|
|
1831
1997
|
}
|
|
@@ -1857,7 +2023,7 @@ function renderPromptSetDetail(ps, format = "pretty", info) {
|
|
|
1857
2023
|
if (format === "json") {
|
|
1858
2024
|
console.log(JSON.stringify(payload, null, 2));
|
|
1859
2025
|
} else if (format === "yaml") {
|
|
1860
|
-
console.log(
|
|
2026
|
+
console.log(yamlDump3(payload));
|
|
1861
2027
|
}
|
|
1862
2028
|
return;
|
|
1863
2029
|
}
|
|
@@ -1894,7 +2060,7 @@ function renderPromptList(prompts, format = "pretty") {
|
|
|
1894
2060
|
if (format === "json") {
|
|
1895
2061
|
console.log(JSON.stringify(prompts, null, 2));
|
|
1896
2062
|
} else if (format === "yaml") {
|
|
1897
|
-
console.log(
|
|
2063
|
+
console.log(yamlDump3(prompts));
|
|
1898
2064
|
}
|
|
1899
2065
|
return;
|
|
1900
2066
|
}
|
|
@@ -1917,7 +2083,7 @@ function renderPromptDetail(p, format = "pretty") {
|
|
|
1917
2083
|
if (format === "json") {
|
|
1918
2084
|
console.log(JSON.stringify(p, null, 2));
|
|
1919
2085
|
} else if (format === "yaml") {
|
|
1920
|
-
console.log(
|
|
2086
|
+
console.log(yamlDump3(p));
|
|
1921
2087
|
}
|
|
1922
2088
|
return;
|
|
1923
2089
|
}
|
|
@@ -1937,7 +2103,7 @@ function renderPropertyNames(names, format = "pretty") {
|
|
|
1937
2103
|
if (format === "json") {
|
|
1938
2104
|
console.log(JSON.stringify(names, null, 2));
|
|
1939
2105
|
} else if (format === "yaml") {
|
|
1940
|
-
console.log(
|
|
2106
|
+
console.log(yamlDump3(names));
|
|
1941
2107
|
} else {
|
|
1942
2108
|
const rows = names.map((n) => ({ name: n }));
|
|
1943
2109
|
console.log(formatOutput(rows, [{ key: "name", label: "Name" }], format));
|
|
@@ -1992,7 +2158,7 @@ function renderPropertyValues(payload, format = "pretty") {
|
|
|
1992
2158
|
if (format === "json") {
|
|
1993
2159
|
console.log(JSON.stringify(payload, null, 2));
|
|
1994
2160
|
} else if (format === "yaml") {
|
|
1995
|
-
console.log(
|
|
2161
|
+
console.log(yamlDump3(payload));
|
|
1996
2162
|
}
|
|
1997
2163
|
return;
|
|
1998
2164
|
}
|
|
@@ -2023,7 +2189,7 @@ function renderInstanceDetail(inst, format = "pretty") {
|
|
|
2023
2189
|
if (format === "json") {
|
|
2024
2190
|
console.log(JSON.stringify(inst, null, 2));
|
|
2025
2191
|
} else if (format === "yaml") {
|
|
2026
|
-
console.log(
|
|
2192
|
+
console.log(yamlDump3(inst));
|
|
2027
2193
|
}
|
|
2028
2194
|
return;
|
|
2029
2195
|
}
|
|
@@ -2041,7 +2207,7 @@ function renderRegistryCredentials(creds, format = "pretty") {
|
|
|
2041
2207
|
if (format === "json") {
|
|
2042
2208
|
console.log(JSON.stringify(creds, null, 2));
|
|
2043
2209
|
} else if (format === "yaml") {
|
|
2044
|
-
console.log(
|
|
2210
|
+
console.log(yamlDump3(creds));
|
|
2045
2211
|
}
|
|
2046
2212
|
return;
|
|
2047
2213
|
}
|
|
@@ -2103,7 +2269,7 @@ function renderChannelList(channels, format = "pretty") {
|
|
|
2103
2269
|
}
|
|
2104
2270
|
function renderChannelDetail(channel, format = "pretty") {
|
|
2105
2271
|
if (format !== "pretty") {
|
|
2106
|
-
console.log(format === "json" ? JSON.stringify(channel, null, 2) :
|
|
2272
|
+
console.log(format === "json" ? JSON.stringify(channel, null, 2) : yamlDump3(channel));
|
|
2107
2273
|
return;
|
|
2108
2274
|
}
|
|
2109
2275
|
ui.section("Channel Detail:");
|
|
@@ -2129,7 +2295,7 @@ function renderChannelDetail(channel, format = "pretty") {
|
|
|
2129
2295
|
}
|
|
2130
2296
|
function renderChannelStats(stats, format = "pretty") {
|
|
2131
2297
|
if (format !== "pretty") {
|
|
2132
|
-
console.log(format === "json" ? JSON.stringify(stats, null, 2) :
|
|
2298
|
+
console.log(format === "json" ? JSON.stringify(stats, null, 2) : yamlDump3(stats));
|
|
2133
2299
|
return;
|
|
2134
2300
|
}
|
|
2135
2301
|
ui.section("Network Broker Stats:");
|
|
@@ -2147,7 +2313,7 @@ function renderChannelStats(stats, format = "pretty") {
|
|
|
2147
2313
|
function renderLanguages(data, format = "pretty") {
|
|
2148
2314
|
if (format !== "pretty") {
|
|
2149
2315
|
if (format === "json" || format === "yaml") {
|
|
2150
|
-
console.log(format === "json" ? JSON.stringify(data, null, 2) :
|
|
2316
|
+
console.log(format === "json" ? JSON.stringify(data, null, 2) : yamlDump3(data));
|
|
2151
2317
|
return;
|
|
2152
2318
|
}
|
|
2153
2319
|
console.log(
|
|
@@ -2256,7 +2422,7 @@ function renderAdapterList(adapters, format = "pretty", totalItems) {
|
|
|
2256
2422
|
}
|
|
2257
2423
|
function renderAdapterDetail(adapter, format = "pretty") {
|
|
2258
2424
|
if (format !== "pretty") {
|
|
2259
|
-
console.log(format === "json" ? JSON.stringify(adapter, null, 2) :
|
|
2425
|
+
console.log(format === "json" ? JSON.stringify(adapter, null, 2) : yamlDump3(adapter));
|
|
2260
2426
|
return;
|
|
2261
2427
|
}
|
|
2262
2428
|
ui.section("Adapter Detail:");
|
|
@@ -2289,7 +2455,7 @@ function renderAdapterDetail(adapter, format = "pretty") {
|
|
|
2289
2455
|
}
|
|
2290
2456
|
function renderAdapterValidation(result, format = "pretty") {
|
|
2291
2457
|
if (format !== "pretty") {
|
|
2292
|
-
console.log(format === "json" ? JSON.stringify(result, null, 2) :
|
|
2458
|
+
console.log(format === "json" ? JSON.stringify(result, null, 2) : yamlDump3(result));
|
|
2293
2459
|
return;
|
|
2294
2460
|
}
|
|
2295
2461
|
if (result.validated) {
|
|
@@ -2723,7 +2889,8 @@ function renderDeploymentProfileList(profiles, format = "pretty") {
|
|
|
2723
2889
|
}
|
|
2724
2890
|
function renderScanLogList(results, pageToken, format = "pretty") {
|
|
2725
2891
|
if (results.length === 0) {
|
|
2726
|
-
ui.emptyList("scan logs");
|
|
2892
|
+
if (format === "pretty") ui.emptyList("scan logs");
|
|
2893
|
+
else console.log(formatOutput([], [], format));
|
|
2727
2894
|
return;
|
|
2728
2895
|
}
|
|
2729
2896
|
if (format !== "pretty") {
|
|
@@ -2856,7 +3023,7 @@ function scopeNameLooksUnrelated(name, scopeName) {
|
|
|
2856
3023
|
function registerAiGatewayCommand(program) {
|
|
2857
3024
|
const aigateway = program.command("aigateway").description("AI Gateway operations");
|
|
2858
3025
|
const workspace = aigateway.command("workspace").description("Manage AI Gateway workspaces");
|
|
2859
|
-
workspace.command("list").description("List workspaces (default: active workspaces you are scoped to)").option("--plane <plane>", "Plane to read from: data (scoped) or admin (whole tenant)").option("--status <status>", "Filter by lifecycle state: active or archived").option("--all", "Merge active + archived admin-plane reads (whole tenant, both states)").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
3026
|
+
const workspaceList = workspace.command("list").description("List workspaces (default: active workspaces you are scoped to)").option("--plane <plane>", "Plane to read from: data (scoped) or admin (whole tenant)").option("--status <status>", "Filter by lifecycle state: active or archived").option("--all", "Merge active + archived admin-plane reads (whole tenant, both states)").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
2860
3027
|
"after",
|
|
2861
3028
|
examples(
|
|
2862
3029
|
"airs aigateway workspace list",
|
|
@@ -2866,7 +3033,7 @@ function registerAiGatewayCommand(program) {
|
|
|
2866
3033
|
)
|
|
2867
3034
|
).action(async (opts) => {
|
|
2868
3035
|
try {
|
|
2869
|
-
const fmt = opts
|
|
3036
|
+
const fmt = await resolveOutput(workspaceList, opts);
|
|
2870
3037
|
if (fmt === "pretty") renderAiGatewayHeader();
|
|
2871
3038
|
const plane = parsePlane(opts.plane);
|
|
2872
3039
|
const status = parseStatus(opts.status);
|
|
@@ -2887,7 +3054,7 @@ function registerAiGatewayCommand(program) {
|
|
|
2887
3054
|
failWithGrantHint(err);
|
|
2888
3055
|
}
|
|
2889
3056
|
});
|
|
2890
|
-
workspace.command("get <ref>").description("Get one workspace by UUID or slug (includes settings blocks)").option("--plane <plane>", "Plane to read from: data (scoped) or admin (whole tenant)").option("--output <format>", "Output format: pretty, json, yaml"
|
|
3057
|
+
const workspaceGet = workspace.command("get <ref>").description("Get one workspace by UUID or slug (includes settings blocks)").option("--plane <plane>", "Plane to read from: data (scoped) or admin (whole tenant)").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
2891
3058
|
"after",
|
|
2892
3059
|
examples(
|
|
2893
3060
|
"airs aigateway workspace get ws-main-a-349e0e",
|
|
@@ -2895,7 +3062,7 @@ function registerAiGatewayCommand(program) {
|
|
|
2895
3062
|
)
|
|
2896
3063
|
).action(async (ref, opts) => {
|
|
2897
3064
|
try {
|
|
2898
|
-
const fmt = opts
|
|
3065
|
+
const fmt = await resolveOutput(workspaceGet, opts);
|
|
2899
3066
|
if (fmt === "pretty") renderAiGatewayHeader();
|
|
2900
3067
|
const plane = parsePlane(opts.plane);
|
|
2901
3068
|
const service = await createService();
|
|
@@ -2980,9 +3147,9 @@ function registerAiGatewayCommand(program) {
|
|
|
2980
3147
|
}
|
|
2981
3148
|
});
|
|
2982
3149
|
const telemetry = aigateway.command("telemetry").description("AI Gateway runtime telemetry (data plane)");
|
|
2983
|
-
telemetry.command("cost").description(
|
|
3150
|
+
const cost = telemetry.command("cost").description(
|
|
2984
3151
|
"Total and per-day spend for a workspace (API reports cents; pretty output shows dollars)"
|
|
2985
|
-
).requiredOption("--workspace <slug>", "Workspace slug (not UUID), e.g. ws-main-a-349e0e").option("--days <n>", "Rolling window in days, counted back from now", "7").option("--output <format>", "Output format: pretty, json, yaml"
|
|
3152
|
+
).requiredOption("--workspace <slug>", "Workspace slug (not UUID), e.g. ws-main-a-349e0e").option("--days <n>", "Rolling window in days, counted back from now", "7").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
2986
3153
|
"after",
|
|
2987
3154
|
examples(
|
|
2988
3155
|
"airs aigateway telemetry cost --workspace ws-main-a-349e0e",
|
|
@@ -2990,7 +3157,7 @@ function registerAiGatewayCommand(program) {
|
|
|
2990
3157
|
)
|
|
2991
3158
|
).action(async (opts) => {
|
|
2992
3159
|
try {
|
|
2993
|
-
const fmt = opts
|
|
3160
|
+
const fmt = await resolveOutput(cost, opts);
|
|
2994
3161
|
if (fmt === "pretty") renderAiGatewayHeader();
|
|
2995
3162
|
const days = Number.parseInt(opts.days, 10);
|
|
2996
3163
|
if (!Number.isFinite(days) || days <= 0) {
|
|
@@ -3194,13 +3361,6 @@ function assertKnownKey(key) {
|
|
|
3194
3361
|
usageError(`Unknown config key '${key}'. Valid keys: ${CONFIG_KEYS.join(", ")}`);
|
|
3195
3362
|
}
|
|
3196
3363
|
}
|
|
3197
|
-
var LIST_FORMATS = ["pretty", "json", "yaml"];
|
|
3198
|
-
function parseListFormat(value) {
|
|
3199
|
-
if (!LIST_FORMATS.includes(value)) {
|
|
3200
|
-
usageError(`Invalid --output '${value}'. Valid formats: ${LIST_FORMATS.join(", ")}`);
|
|
3201
|
-
}
|
|
3202
|
-
return value;
|
|
3203
|
-
}
|
|
3204
3364
|
var COLUMNS = [
|
|
3205
3365
|
{ key: "key", label: "Key" },
|
|
3206
3366
|
{ key: "value", label: "Value" },
|
|
@@ -3215,9 +3375,9 @@ function registerConfigCommand(program) {
|
|
|
3215
3375
|
"airs config get mgmtTsgId"
|
|
3216
3376
|
)
|
|
3217
3377
|
);
|
|
3218
|
-
config.command("list").description("Show effective configuration with per-key source (env/file/default)").option("--output <format>", "Output format: pretty,
|
|
3378
|
+
const configList = config.command("list").description("Show effective configuration with per-key source (env/file/default)").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").option("--reveal", "Show secret values in full").action(async (opts) => {
|
|
3219
3379
|
try {
|
|
3220
|
-
const fmt =
|
|
3380
|
+
const fmt = await resolveOutput(configList, opts);
|
|
3221
3381
|
const filePath = resolveConfigFilePath();
|
|
3222
3382
|
const rows = buildConfigRows(await inspectConfig(), Boolean(opts.reveal));
|
|
3223
3383
|
if (fmt === "pretty") {
|
|
@@ -3232,12 +3392,18 @@ function registerConfigCommand(program) {
|
|
|
3232
3392
|
fail(err);
|
|
3233
3393
|
}
|
|
3234
3394
|
});
|
|
3235
|
-
config.command("get <key>").description("Print a single effective config value").option("--reveal", "Show the real value of a secret key").action(async (key, opts) => {
|
|
3395
|
+
const configGet = config.command("get <key>").description("Print a single effective config value").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").option("--reveal", "Show the real value of a secret key").action(async (key, opts) => {
|
|
3236
3396
|
try {
|
|
3237
3397
|
assertKnownKey(key);
|
|
3238
3398
|
const inspected = await inspectConfig();
|
|
3239
3399
|
const entry = inspected[key];
|
|
3240
3400
|
const raw = entry.value == null ? "" : String(entry.value);
|
|
3401
|
+
const fmt = await resolveOutput(configGet, opts);
|
|
3402
|
+
const value = raw !== "" && isSecretKey(key) && !opts.reveal ? maskSecret(raw) : raw;
|
|
3403
|
+
if (fmt !== "pretty") {
|
|
3404
|
+
console.log(formatOutput([{ key, value, source: entry.source }], COLUMNS, fmt));
|
|
3405
|
+
return;
|
|
3406
|
+
}
|
|
3241
3407
|
if (raw !== "" && isSecretKey(key)) {
|
|
3242
3408
|
if (opts.reveal) {
|
|
3243
3409
|
ui.status(`Warning: printing secret value for '${key}'`);
|
|
@@ -3590,20 +3756,6 @@ var STATUS_KIND = {
|
|
|
3590
3756
|
warn: "warn",
|
|
3591
3757
|
fail: "error"
|
|
3592
3758
|
};
|
|
3593
|
-
var DOCTOR_FORMATS = ["pretty", "json", "yaml"];
|
|
3594
|
-
function parseDoctorFormat(value) {
|
|
3595
|
-
if (!DOCTOR_FORMATS.includes(value)) {
|
|
3596
|
-
usageError(`Invalid --output '${value}'. Valid formats: ${DOCTOR_FORMATS.join(", ")}`);
|
|
3597
|
-
}
|
|
3598
|
-
return value;
|
|
3599
|
-
}
|
|
3600
|
-
function toYaml(checks) {
|
|
3601
|
-
return checks.map((c) => {
|
|
3602
|
-
const lines = [`name: ${c.name}`, `status: ${c.status}`, `detail: ${c.detail}`];
|
|
3603
|
-
if (c.hint) lines.push(`hint: ${c.hint}`);
|
|
3604
|
-
return lines.join("\n");
|
|
3605
|
-
}).join("\n---\n");
|
|
3606
|
-
}
|
|
3607
3759
|
function renderPretty(checks) {
|
|
3608
3760
|
ui.header("Doctor", "Prisma AIRS CLI preflight checks");
|
|
3609
3761
|
for (const check of checks) {
|
|
@@ -3623,18 +3775,27 @@ function renderPretty(checks) {
|
|
|
3623
3775
|
console.log("");
|
|
3624
3776
|
}
|
|
3625
3777
|
function registerDoctorCommand(program) {
|
|
3626
|
-
program.command("doctor").description("Check credentials, config, and API connectivity (preflight)").option("--output <format>", "Output format: pretty,
|
|
3778
|
+
const doctor = program.command("doctor").description("Check credentials, config, and API connectivity (preflight)").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
3627
3779
|
"after",
|
|
3628
3780
|
examples("airs doctor", `airs doctor --output json | jq '.[] | select(.status != "pass")'`)
|
|
3629
3781
|
).action(async (opts) => {
|
|
3630
|
-
const fmt =
|
|
3782
|
+
const fmt = await resolveOutput(doctor, opts);
|
|
3631
3783
|
const checks = await runDoctor();
|
|
3632
|
-
if (fmt === "
|
|
3633
|
-
console.log(JSON.stringify(checks, null, 2));
|
|
3634
|
-
} else if (fmt === "yaml") {
|
|
3635
|
-
console.log(toYaml(checks));
|
|
3636
|
-
} else {
|
|
3784
|
+
if (fmt === "pretty") {
|
|
3637
3785
|
renderPretty(checks);
|
|
3786
|
+
} else {
|
|
3787
|
+
console.log(
|
|
3788
|
+
formatOutput(
|
|
3789
|
+
checks.map((check) => ({ ...check })),
|
|
3790
|
+
[
|
|
3791
|
+
{ key: "name", label: "Name" },
|
|
3792
|
+
{ key: "status", label: "Status" },
|
|
3793
|
+
{ key: "detail", label: "Detail" },
|
|
3794
|
+
{ key: "hint", label: "Hint" }
|
|
3795
|
+
],
|
|
3796
|
+
fmt
|
|
3797
|
+
)
|
|
3798
|
+
);
|
|
3638
3799
|
}
|
|
3639
3800
|
process.exit(hasFailure(checks) ? 1 : 0);
|
|
3640
3801
|
});
|
|
@@ -3669,27 +3830,29 @@ async function createService2() {
|
|
|
3669
3830
|
function registerModelSecurityCommand(program) {
|
|
3670
3831
|
const ms = program.command("model-security").description("AI Model Security operations \u2014 groups, rules, scans");
|
|
3671
3832
|
const groups = ms.command("groups").description("Manage security groups");
|
|
3672
|
-
groups.command("list").description("List security groups").option("--source-types <types>", "Filter by source types (comma-separated)").option("--search <query>", "Search by name or UUID").option("--sort-field <field>", "Sort field (created_at, updated_at)").option("--sort-dir <dir>", "Sort direction (asc, desc)").option("--enabled-rules <uuids>", "Filter by enabled rule UUIDs (comma-separated)").option("--limit <n>", "Max results", "20").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
3833
|
+
const groupsList = groups.command("list").description("List security groups").option("--source-types <types>", "Filter by source types (comma-separated)").option("--search <query>", "Search by name or UUID").option("--sort-field <field>", "Sort field (created_at, updated_at)").option("--sort-dir <dir>", "Sort direction (asc, desc)").option("--enabled-rules <uuids>", "Filter by enabled rule UUIDs (comma-separated)").option("--limit <n>", "Max results", "20").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (opts) => {
|
|
3673
3834
|
try {
|
|
3674
|
-
const fmt = opts
|
|
3835
|
+
const fmt = await resolveOutput(groupsList, opts);
|
|
3675
3836
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3676
3837
|
const service = await createService2();
|
|
3677
|
-
const
|
|
3838
|
+
const listOptions = {
|
|
3678
3839
|
sourceTypes: opts.sourceTypes ? opts.sourceTypes.split(",").map((s) => s.trim()) : void 0,
|
|
3679
3840
|
searchQuery: opts.search,
|
|
3680
3841
|
sortField: opts.sortField,
|
|
3681
3842
|
sortDir: opts.sortDir,
|
|
3682
3843
|
enabledRules: opts.enabledRules ? opts.enabledRules.split(",").map((s) => s.trim()) : void 0,
|
|
3683
|
-
limit: Number.parseInt(opts.limit, 10)
|
|
3684
|
-
|
|
3685
|
-
|
|
3844
|
+
limit: Number.parseInt(opts.limit, 10),
|
|
3845
|
+
skip: Number(opts.offset ?? 0)
|
|
3846
|
+
};
|
|
3847
|
+
const rows = opts.all ? await service.listAllGroups({ ...listOptions, max: Number(opts.max) }) : (await service.listGroups(listOptions)).groups;
|
|
3848
|
+
renderGroupList(rows, fmt);
|
|
3686
3849
|
} catch (err) {
|
|
3687
3850
|
fail(err);
|
|
3688
3851
|
}
|
|
3689
3852
|
});
|
|
3690
|
-
groups.command("get <uuid>").description("Get security group details").option("--output <format>", "Output format: pretty, json, yaml"
|
|
3853
|
+
const groupsGet = groups.command("get <uuid>").description("Get security group details").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (uuid, opts) => {
|
|
3691
3854
|
try {
|
|
3692
|
-
const fmt = opts
|
|
3855
|
+
const fmt = await resolveOutput(groupsGet, opts);
|
|
3693
3856
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3694
3857
|
const service = await createService2();
|
|
3695
3858
|
const group = await service.getGroup(uuid);
|
|
@@ -3877,24 +4040,26 @@ function registerModelSecurityCommand(program) {
|
|
|
3877
4040
|
const ruleInstances = ms.command("rule-instances").description("Manage rule instances in groups");
|
|
3878
4041
|
ruleInstances.command("list <groupUuid>").description("List rule instances in a security group").option("--security-rule-uuid <uuid>", "Filter by security rule UUID").option("--state <state>", "Filter by state (DISABLED, ALLOWING, BLOCKING)").option("--limit <n>", "Max results", "20").action(async (groupUuid, opts) => {
|
|
3879
4042
|
try {
|
|
3880
|
-
|
|
4043
|
+
const fmt = opts.output;
|
|
4044
|
+
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3881
4045
|
const service = await createService2();
|
|
3882
4046
|
const result = await service.listRuleInstances(groupUuid, {
|
|
3883
4047
|
securityRuleUuid: opts.securityRuleUuid,
|
|
3884
4048
|
state: opts.state,
|
|
3885
4049
|
limit: Number.parseInt(opts.limit, 10)
|
|
3886
4050
|
});
|
|
3887
|
-
renderRuleInstanceList(result.ruleInstances);
|
|
4051
|
+
renderRuleInstanceList(result.ruleInstances, fmt);
|
|
3888
4052
|
} catch (err) {
|
|
3889
4053
|
fail(err);
|
|
3890
4054
|
}
|
|
3891
4055
|
});
|
|
3892
|
-
ruleInstances.command("get <groupUuid> <instanceUuid>").description("Get rule instance details").action(async (groupUuid, instanceUuid) => {
|
|
4056
|
+
ruleInstances.command("get <groupUuid> <instanceUuid>").description("Get rule instance details").action(async (groupUuid, instanceUuid, opts) => {
|
|
3893
4057
|
try {
|
|
3894
|
-
|
|
4058
|
+
const fmt = opts.output;
|
|
4059
|
+
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3895
4060
|
const service = await createService2();
|
|
3896
4061
|
const instance = await service.getRuleInstance(groupUuid, instanceUuid);
|
|
3897
|
-
renderRuleInstanceDetail(instance);
|
|
4062
|
+
renderRuleInstanceDetail(instance, fmt);
|
|
3898
4063
|
} catch (err) {
|
|
3899
4064
|
fail(err);
|
|
3900
4065
|
}
|
|
@@ -3915,33 +4080,36 @@ function registerModelSecurityCommand(program) {
|
|
|
3915
4080
|
}
|
|
3916
4081
|
});
|
|
3917
4082
|
const rules = ms.command("rules").description("Browse security rules");
|
|
3918
|
-
rules.command("list").description("List available security rules").option("--source-type <type>", "Filter by source type").option("--search <query>", "Search by name or UUID").option("--limit <n>", "Max results", "20").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
4083
|
+
const rulesList = rules.command("list").description("List available security rules").option("--source-type <type>", "Filter by source type").option("--search <query>", "Search by name or UUID").option("--limit <n>", "Max results", "20").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (opts) => {
|
|
3919
4084
|
try {
|
|
3920
|
-
const fmt = opts
|
|
4085
|
+
const fmt = await resolveOutput(rulesList, opts);
|
|
3921
4086
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3922
4087
|
const service = await createService2();
|
|
3923
|
-
const
|
|
4088
|
+
const listOptions = {
|
|
3924
4089
|
sourceType: opts.sourceType,
|
|
3925
4090
|
searchQuery: opts.search,
|
|
3926
|
-
limit: Number.parseInt(opts.limit, 10)
|
|
3927
|
-
|
|
3928
|
-
|
|
4091
|
+
limit: Number.parseInt(opts.limit, 10),
|
|
4092
|
+
skip: Number(opts.offset ?? 0)
|
|
4093
|
+
};
|
|
4094
|
+
const rows = opts.all ? await service.listAllRules({ ...listOptions, max: Number(opts.max) }) : (await service.listRules(listOptions)).rules;
|
|
4095
|
+
renderRuleList(rows, fmt);
|
|
3929
4096
|
} catch (err) {
|
|
3930
4097
|
fail(err);
|
|
3931
4098
|
}
|
|
3932
4099
|
});
|
|
3933
|
-
rules.command("get <uuid>").description("Get security rule details").action(async (uuid) => {
|
|
4100
|
+
rules.command("get <uuid>").description("Get security rule details").action(async (uuid, opts) => {
|
|
3934
4101
|
try {
|
|
3935
|
-
|
|
4102
|
+
const fmt = opts.output;
|
|
4103
|
+
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3936
4104
|
const service = await createService2();
|
|
3937
4105
|
const rule = await service.getRule(uuid);
|
|
3938
|
-
renderRuleDetail(rule);
|
|
4106
|
+
renderRuleDetail(rule, fmt);
|
|
3939
4107
|
} catch (err) {
|
|
3940
4108
|
fail(err);
|
|
3941
4109
|
}
|
|
3942
4110
|
});
|
|
3943
4111
|
const scans = ms.command("scans").description("Model security scan operations");
|
|
3944
|
-
scans.command("list").description("List model security scans").option("--eval-outcome <outcome>", "Filter by eval outcome").option("--source-type <type>", "Filter by source type").option("--scan-origin <origin>", "Filter by scan origin").option("--search <query>", "Search scans").option("--limit <n>", "Max results", "20").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
4112
|
+
const scansList = scans.command("list").description("List model security scans").option("--eval-outcome <outcome>", "Filter by eval outcome").option("--source-type <type>", "Filter by source type").option("--scan-origin <origin>", "Filter by scan origin").option("--search <query>", "Search scans").option("--limit <n>", "Max results", "20").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
3945
4113
|
"after",
|
|
3946
4114
|
examples(
|
|
3947
4115
|
"airs model-security scans list",
|
|
@@ -3950,27 +4118,30 @@ function registerModelSecurityCommand(program) {
|
|
|
3950
4118
|
)
|
|
3951
4119
|
).action(async (opts) => {
|
|
3952
4120
|
try {
|
|
3953
|
-
const fmt = opts
|
|
4121
|
+
const fmt = await resolveOutput(scansList, opts);
|
|
3954
4122
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3955
4123
|
const service = await createService2();
|
|
3956
|
-
const
|
|
4124
|
+
const listOptions = {
|
|
3957
4125
|
evalOutcome: opts.evalOutcome,
|
|
3958
4126
|
sourceType: opts.sourceType,
|
|
3959
4127
|
scanOrigin: opts.scanOrigin,
|
|
3960
4128
|
search: opts.search,
|
|
3961
|
-
limit: Number.parseInt(opts.limit, 10)
|
|
3962
|
-
|
|
3963
|
-
|
|
4129
|
+
limit: Number.parseInt(opts.limit, 10),
|
|
4130
|
+
skip: Number(opts.offset ?? 0)
|
|
4131
|
+
};
|
|
4132
|
+
const rows = opts.all ? await service.listAllScans({ ...listOptions, max: Number(opts.max) }) : (await service.listScans(listOptions)).scans;
|
|
4133
|
+
renderMsScanList(rows, fmt);
|
|
3964
4134
|
} catch (err) {
|
|
3965
4135
|
fail(err);
|
|
3966
4136
|
}
|
|
3967
4137
|
});
|
|
3968
|
-
scans.command("get <uuid>").description("Get scan details").action(async (uuid) => {
|
|
4138
|
+
scans.command("get <uuid>").description("Get scan details").action(async (uuid, opts) => {
|
|
3969
4139
|
try {
|
|
3970
|
-
|
|
4140
|
+
const fmt = opts.output;
|
|
4141
|
+
if (fmt === "pretty") renderModelSecurityHeader();
|
|
3971
4142
|
const service = await createService2();
|
|
3972
4143
|
const scan = await service.getScan(uuid);
|
|
3973
|
-
renderMsScanDetail(scan);
|
|
4144
|
+
renderMsScanDetail(scan, fmt);
|
|
3974
4145
|
} catch (err) {
|
|
3975
4146
|
fail(err);
|
|
3976
4147
|
}
|
|
@@ -4046,27 +4217,28 @@ function registerModelSecurityCommand(program) {
|
|
|
4046
4217
|
}
|
|
4047
4218
|
});
|
|
4048
4219
|
const models = ms.command("models").description("Browse the scanned model catalog (read-only)");
|
|
4049
|
-
models.command("list").description("List models in the catalog").option("--search <text>", "Filter by search text").option("--search-query <text>", "Filter by model UUID or name").option("--sort-field <field>", "Sort field: created_at, updated_at").option("--sort-order <order>", "Sort order: asc, desc").option("--limit <n>", "Max results").option("--offset <n>", "Starting offset").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
4220
|
+
const modelsList = models.command("list").description("List models in the catalog").option("--search <text>", "Filter by search text").option("--search-query <text>", "Filter by model UUID or name").option("--sort-field <field>", "Sort field: created_at, updated_at").option("--sort-order <order>", "Sort order: asc, desc").option("--limit <n>", "Max results").option("--offset <n>", "Starting offset").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText("after", examples("airs model-security models list")).action(async (opts) => {
|
|
4050
4221
|
try {
|
|
4051
|
-
const fmt = opts
|
|
4222
|
+
const fmt = await resolveOutput(modelsList, opts);
|
|
4052
4223
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
4053
4224
|
const service = await createService2();
|
|
4054
|
-
const
|
|
4225
|
+
const listOptions = {
|
|
4055
4226
|
search: opts.search,
|
|
4056
4227
|
searchQuery: opts.searchQuery,
|
|
4057
4228
|
sortField: opts.sortField,
|
|
4058
4229
|
sortOrder: opts.sortOrder,
|
|
4059
4230
|
limit: opts.limit ? Number.parseInt(opts.limit, 10) : void 0,
|
|
4060
4231
|
skip: opts.offset ? Number.parseInt(opts.offset, 10) : void 0
|
|
4061
|
-
}
|
|
4062
|
-
|
|
4232
|
+
};
|
|
4233
|
+
const rows = opts.all ? await service.listAllModels({ ...listOptions, max: Number(opts.max) }) : (await service.listModels(listOptions)).models;
|
|
4234
|
+
renderModelList(rows, fmt);
|
|
4063
4235
|
} catch (err) {
|
|
4064
4236
|
fail(err);
|
|
4065
4237
|
}
|
|
4066
4238
|
});
|
|
4067
|
-
models.command("get <uuid>").description("Get a model by UUID").option("--output <format>", "Output format: pretty, json, yaml"
|
|
4239
|
+
const modelsGet = models.command("get <uuid>").description("Get a model by UUID").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (uuid, opts) => {
|
|
4068
4240
|
try {
|
|
4069
|
-
const fmt = opts
|
|
4241
|
+
const fmt = await resolveOutput(modelsGet, opts);
|
|
4070
4242
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
4071
4243
|
const service = await createService2();
|
|
4072
4244
|
const model = await service.getModel(uuid);
|
|
@@ -4075,9 +4247,9 @@ function registerModelSecurityCommand(program) {
|
|
|
4075
4247
|
fail(err);
|
|
4076
4248
|
}
|
|
4077
4249
|
});
|
|
4078
|
-
models.command("versions <modelUuid>").description("List versions of a model").option("--sort-order <order>", "Sort order: asc, desc").option("--limit <n>", "Max results").option("--offset <n>", "Starting offset").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
4250
|
+
const modelVersions = models.command("versions <modelUuid>").description("List versions of a model").option("--sort-order <order>", "Sort order: asc, desc").option("--limit <n>", "Max results").option("--offset <n>", "Starting offset").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (modelUuid, opts) => {
|
|
4079
4251
|
try {
|
|
4080
|
-
const fmt = opts
|
|
4252
|
+
const fmt = await resolveOutput(modelVersions, opts);
|
|
4081
4253
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
4082
4254
|
const service = await createService2();
|
|
4083
4255
|
const result = await service.listModelVersions(modelUuid, {
|
|
@@ -4090,9 +4262,9 @@ function registerModelSecurityCommand(program) {
|
|
|
4090
4262
|
fail(err);
|
|
4091
4263
|
}
|
|
4092
4264
|
});
|
|
4093
|
-
models.command("version <uuid>").description("Get a model version by UUID").option("--output <format>", "Output format: pretty, json, yaml"
|
|
4265
|
+
const modelVersion = models.command("version <uuid>").description("Get a model version by UUID").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (uuid, opts) => {
|
|
4094
4266
|
try {
|
|
4095
|
-
const fmt = opts
|
|
4267
|
+
const fmt = await resolveOutput(modelVersion, opts);
|
|
4096
4268
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
4097
4269
|
const service = await createService2();
|
|
4098
4270
|
const version = await service.getModelVersion(uuid);
|
|
@@ -4101,9 +4273,9 @@ function registerModelSecurityCommand(program) {
|
|
|
4101
4273
|
fail(err);
|
|
4102
4274
|
}
|
|
4103
4275
|
});
|
|
4104
|
-
models.command("files <modelVersionUuid>").description("List files in a model version").option("--limit <n>", "Max results").option("--offset <n>", "Starting offset").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
4276
|
+
const modelFiles = models.command("files <modelVersionUuid>").description("List files in a model version").option("--limit <n>", "Max results").option("--offset <n>", "Starting offset").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (modelVersionUuid, opts) => {
|
|
4105
4277
|
try {
|
|
4106
|
-
const fmt = opts
|
|
4278
|
+
const fmt = await resolveOutput(modelFiles, opts);
|
|
4107
4279
|
if (fmt === "pretty") renderModelSecurityHeader();
|
|
4108
4280
|
const service = await createService2();
|
|
4109
4281
|
const result = await service.listModelVersionFiles(modelVersionUuid, {
|
|
@@ -4352,8 +4524,12 @@ function parseAttackGoals(input) {
|
|
|
4352
4524
|
return parsed;
|
|
4353
4525
|
}
|
|
4354
4526
|
function sliceClientSide(items, opts) {
|
|
4355
|
-
|
|
4356
|
-
|
|
4527
|
+
if (opts.all) {
|
|
4528
|
+
const max = opts.max === void 0 ? 1e4 : Number(opts.max);
|
|
4529
|
+
return max === 0 ? items : items.slice(0, max);
|
|
4530
|
+
}
|
|
4531
|
+
const offset = opts.offset !== void 0 ? Number.parseInt(String(opts.offset), 10) : 0;
|
|
4532
|
+
const limit = opts.limit !== void 0 ? Number.parseInt(String(opts.limit), 10) : void 0;
|
|
4357
4533
|
return items.slice(offset, limit === void 0 ? void 0 : offset + limit);
|
|
4358
4534
|
}
|
|
4359
4535
|
function parsePositiveInt(input, flag) {
|
|
@@ -4634,12 +4810,14 @@ function registerRedteamCommand(program) {
|
|
|
4634
4810
|
const fmt = opts.output;
|
|
4635
4811
|
if (fmt === "pretty") renderRedteamHeader();
|
|
4636
4812
|
const service = await createService3();
|
|
4637
|
-
const
|
|
4813
|
+
const listOptions = {
|
|
4638
4814
|
status: opts.status,
|
|
4639
4815
|
jobType: opts.type,
|
|
4640
4816
|
targetId: opts.target,
|
|
4641
|
-
limit: Number.parseInt(opts.limit, 10)
|
|
4642
|
-
|
|
4817
|
+
limit: Number.parseInt(opts.limit, 10),
|
|
4818
|
+
offset: Number(opts.offset ?? 0)
|
|
4819
|
+
};
|
|
4820
|
+
const scans = opts.all ? await service.listAllScans({ ...listOptions, max: Number(opts.max) }) : await service.listScans(listOptions);
|
|
4643
4821
|
renderScanList(scans, fmt);
|
|
4644
4822
|
} catch (err) {
|
|
4645
4823
|
fail(err);
|
|
@@ -5142,12 +5320,18 @@ function registerRedteamCommand(program) {
|
|
|
5142
5320
|
fail(err);
|
|
5143
5321
|
}
|
|
5144
5322
|
});
|
|
5145
|
-
const targetsBackup = targets.command("backup").description("Backup red team targets to local JSON/YAML files").option("--output-dir <path>", "Output directory").option("--
|
|
5323
|
+
const targetsBackup = targets.command("backup").description("Backup red team targets to local JSON/YAML files").option("--output-dir <path>", "Output directory").option("--file-format <format>", "Backup file format: json or yaml", "json").option("--name <targetName>", "Backup a single target by name");
|
|
5324
|
+
registerDeprecatedAlias(targetsBackup, {
|
|
5325
|
+
oldFlag: "--output <format>",
|
|
5326
|
+
oldKey: "output",
|
|
5327
|
+
canonicalFlag: "--file-format",
|
|
5328
|
+
canonicalKey: "fileFormat"
|
|
5329
|
+
});
|
|
5146
5330
|
registerDeprecatedAlias(targetsBackup, {
|
|
5147
5331
|
oldFlag: "--format <format>",
|
|
5148
5332
|
oldKey: "format",
|
|
5149
|
-
canonicalFlag: "--
|
|
5150
|
-
canonicalKey: "
|
|
5333
|
+
canonicalFlag: "--file-format",
|
|
5334
|
+
canonicalKey: "fileFormat"
|
|
5151
5335
|
});
|
|
5152
5336
|
targetsBackup.action(async (opts) => {
|
|
5153
5337
|
resolveDeprecatedAliases(targetsBackup, opts);
|
|
@@ -5156,7 +5340,7 @@ function registerRedteamCommand(program) {
|
|
|
5156
5340
|
const outputDir = resolveOutputDir(opts.outputDir, "targets");
|
|
5157
5341
|
const results = await backupTargets({
|
|
5158
5342
|
outputDir,
|
|
5159
|
-
format: opts.
|
|
5343
|
+
format: opts.fileFormat ?? "json",
|
|
5160
5344
|
name: opts.name
|
|
5161
5345
|
});
|
|
5162
5346
|
renderBackupSummary(results, outputDir);
|
|
@@ -5221,11 +5405,13 @@ function registerRedteamCommand(program) {
|
|
|
5221
5405
|
const fmt = opts.output;
|
|
5222
5406
|
if (fmt === "pretty") renderRedteamHeader();
|
|
5223
5407
|
const service = await createService3();
|
|
5224
|
-
const
|
|
5408
|
+
const listOptions = {
|
|
5225
5409
|
limit: opts.limit ? parsePositiveInt(opts.limit, "--limit") : void 0,
|
|
5226
5410
|
offset: opts.offset ? Number.parseInt(opts.offset, 10) : void 0,
|
|
5227
5411
|
search: opts.search
|
|
5228
|
-
}
|
|
5412
|
+
};
|
|
5413
|
+
const result = opts.all ? { adapters: await service.listAllAdapters({ ...listOptions, max: Number(opts.max) }) } : await service.listAdapters(listOptions);
|
|
5414
|
+
const { adapters, totalItems } = result;
|
|
5229
5415
|
renderAdapterList(adapters, fmt, totalItems);
|
|
5230
5416
|
} catch (err) {
|
|
5231
5417
|
fail(err);
|
|
@@ -5367,12 +5553,13 @@ function registerRedteamCommand(program) {
|
|
|
5367
5553
|
const fmt = opts.output;
|
|
5368
5554
|
if (fmt === "pretty") renderRedteamHeader();
|
|
5369
5555
|
const service = await createService3();
|
|
5370
|
-
const
|
|
5556
|
+
const listOptions = {
|
|
5371
5557
|
limit: opts.limit ? parsePositiveInt(opts.limit, "--limit") : void 0,
|
|
5372
5558
|
offset: opts.offset ? Number.parseInt(opts.offset, 10) : void 0,
|
|
5373
5559
|
search: opts.search,
|
|
5374
5560
|
status: opts.status
|
|
5375
|
-
}
|
|
5561
|
+
};
|
|
5562
|
+
const list = opts.all ? await service.listAllChannels({ ...listOptions, max: Number(opts.max) }) : (await service.listChannels(listOptions)).channels;
|
|
5376
5563
|
renderChannelList(list, fmt);
|
|
5377
5564
|
} catch (err) {
|
|
5378
5565
|
fail(err);
|
|
@@ -5914,6 +6101,31 @@ async function loadBulkScanState(filePath) {
|
|
|
5914
6101
|
|
|
5915
6102
|
// src/cli/pagination.ts
|
|
5916
6103
|
var DEFAULT_PAGE_SIZE = 50;
|
|
6104
|
+
var DEFAULT_OFFSET_LIMIT = 100;
|
|
6105
|
+
var DEFAULT_MAX_ITEMS = 1e4;
|
|
6106
|
+
function registerListFlags(command, options) {
|
|
6107
|
+
const defaultLimit = options.dialect === "offset" ? DEFAULT_OFFSET_LIMIT : DEFAULT_PAGE_SIZE;
|
|
6108
|
+
return command.option("--limit <n>", `Items per page (default: ${defaultLimit})`, Number, defaultLimit).option("--offset <n>", "Item offset (default: 0)", Number, 0).option("--all", "Walk all pages").option("--max <n>", "Maximum items with --all; 0 removes the cap", Number, DEFAULT_MAX_ITEMS);
|
|
6109
|
+
}
|
|
6110
|
+
function integerFlag(name, value, minimum) {
|
|
6111
|
+
const parsed = Number(value);
|
|
6112
|
+
if (!Number.isSafeInteger(parsed) || parsed < minimum) {
|
|
6113
|
+
const qualifier = minimum === 1 ? "a positive integer" : "a non-negative integer";
|
|
6114
|
+
throw new CliUsageError(`${name} must be ${qualifier}`);
|
|
6115
|
+
}
|
|
6116
|
+
return parsed;
|
|
6117
|
+
}
|
|
6118
|
+
function resolveListParams(command, opts, options) {
|
|
6119
|
+
const defaultLimit = options.dialect === "offset" ? DEFAULT_OFFSET_LIMIT : DEFAULT_PAGE_SIZE;
|
|
6120
|
+
const limit = integerFlag("--limit", opts.limit ?? defaultLimit, 1);
|
|
6121
|
+
const offset = integerFlag("--offset", opts.offset ?? 0, 0);
|
|
6122
|
+
const max = integerFlag("--max", opts.max ?? DEFAULT_MAX_ITEMS, 0);
|
|
6123
|
+
const all = Boolean(opts.all);
|
|
6124
|
+
if (all && command.getOptionValueSource?.("offset") === "cli") {
|
|
6125
|
+
throw new CliUsageError("--all cannot be combined with --offset");
|
|
6126
|
+
}
|
|
6127
|
+
return { limit, offset, all, max };
|
|
6128
|
+
}
|
|
5917
6129
|
function registerPageAliases(cmd, opts) {
|
|
5918
6130
|
registerDeprecatedAlias(cmd, {
|
|
5919
6131
|
oldFlag: `${opts.sizeFlag} <n>`,
|
|
@@ -6035,6 +6247,71 @@ function parseQuotedField(content, start, len) {
|
|
|
6035
6247
|
return { value, nextIndex: i };
|
|
6036
6248
|
}
|
|
6037
6249
|
|
|
6250
|
+
// src/cli/renderer/views/runtime.ts
|
|
6251
|
+
var profilesView = {
|
|
6252
|
+
name: "profiles",
|
|
6253
|
+
columns: [
|
|
6254
|
+
{ key: "profileId", label: "ID" },
|
|
6255
|
+
{ key: "profileName", label: "Name" },
|
|
6256
|
+
{ key: "active", label: "Active" },
|
|
6257
|
+
{ key: "revision", label: "Revision" }
|
|
6258
|
+
],
|
|
6259
|
+
pretty: {
|
|
6260
|
+
list: (items) => renderProfileList(items, "pretty"),
|
|
6261
|
+
detail: renderProfileDetail
|
|
6262
|
+
}
|
|
6263
|
+
};
|
|
6264
|
+
var apiKeysView = {
|
|
6265
|
+
name: "API keys",
|
|
6266
|
+
columns: [
|
|
6267
|
+
{ key: "id", label: "ID" },
|
|
6268
|
+
{ key: "name", label: "Name" },
|
|
6269
|
+
{ key: "last8", label: "Last 8" },
|
|
6270
|
+
{ key: "expiresAt", label: "Expires" }
|
|
6271
|
+
],
|
|
6272
|
+
pretty: {
|
|
6273
|
+
list: (items) => renderApiKeyList(items, "pretty"),
|
|
6274
|
+
detail: renderApiKeyDetail
|
|
6275
|
+
}
|
|
6276
|
+
};
|
|
6277
|
+
var customerAppsView = {
|
|
6278
|
+
name: "customer apps",
|
|
6279
|
+
columns: [
|
|
6280
|
+
{ key: "id", label: "ID" },
|
|
6281
|
+
{ key: "name", label: "Name" },
|
|
6282
|
+
{ key: "description", label: "Description" }
|
|
6283
|
+
],
|
|
6284
|
+
pretty: {
|
|
6285
|
+
list: (items) => renderCustomerAppList(items, "pretty"),
|
|
6286
|
+
detail: renderCustomerAppDetail
|
|
6287
|
+
}
|
|
6288
|
+
};
|
|
6289
|
+
var topicsView = {
|
|
6290
|
+
name: "topics",
|
|
6291
|
+
columns: [
|
|
6292
|
+
{ key: "topic_id", label: "ID" },
|
|
6293
|
+
{ key: "topic_name", label: "Name" },
|
|
6294
|
+
{ key: "revision", label: "Revision" },
|
|
6295
|
+
{ key: "description", label: "Description" }
|
|
6296
|
+
],
|
|
6297
|
+
structured: (topic) => ({
|
|
6298
|
+
topicId: topic.topic_id,
|
|
6299
|
+
topicName: topic.topic_name,
|
|
6300
|
+
revision: topic.revision,
|
|
6301
|
+
active: topic.active,
|
|
6302
|
+
description: topic.description,
|
|
6303
|
+
examples: topic.examples,
|
|
6304
|
+
createdBy: topic.created_by,
|
|
6305
|
+
updatedBy: topic.updated_by,
|
|
6306
|
+
lastModifiedTs: topic.last_modified_ts,
|
|
6307
|
+
createdTs: topic.created_ts
|
|
6308
|
+
}),
|
|
6309
|
+
pretty: {
|
|
6310
|
+
list: (items) => renderTopicList(items, "pretty"),
|
|
6311
|
+
detail: renderTopicDetail
|
|
6312
|
+
}
|
|
6313
|
+
};
|
|
6314
|
+
|
|
6038
6315
|
// src/cli/commands/dlp/dictionaries.ts
|
|
6039
6316
|
import { readFile as readFile6 } from "fs/promises";
|
|
6040
6317
|
import { basename as basename2 } from "path";
|
|
@@ -6048,6 +6325,9 @@ var SdkDictionariesService = class {
|
|
|
6048
6325
|
async list(params) {
|
|
6049
6326
|
return this.client.list(params);
|
|
6050
6327
|
}
|
|
6328
|
+
async listAll(params) {
|
|
6329
|
+
return this.client.listAll(params);
|
|
6330
|
+
}
|
|
6051
6331
|
async create(params) {
|
|
6052
6332
|
return this.client.create(params);
|
|
6053
6333
|
}
|
|
@@ -6155,20 +6435,22 @@ function register(dlp) {
|
|
|
6155
6435
|
"--offset <n>",
|
|
6156
6436
|
"Starting offset \u2014 rounds down to a page boundary",
|
|
6157
6437
|
(v) => Number.parseInt(v, 10)
|
|
6158
|
-
).option("--sort <field,dir>", "(repeatable)", (v, p = []) => [...p, v]).option("--keywords", "Include keyword list in response").option("--include-keywords", "Alias for --keywords").option("--output <fmt>", "Output format
|
|
6438
|
+
).option("--sort <field,dir>", "(repeatable)", (v, p = []) => [...p, v]).option("--keywords", "Include keyword list in response").option("--include-keywords", "Alias for --keywords").option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml");
|
|
6159
6439
|
registerPageAliases(listCmd, { sizeFlag: "--size", sizeKey: "size" });
|
|
6160
6440
|
listCmd.action(async (opts) => {
|
|
6161
6441
|
try {
|
|
6162
6442
|
const { page, size } = resolvePageParams(listCmd, opts);
|
|
6163
6443
|
const includeKeywords = opts.keywords || opts.includeKeywords;
|
|
6444
|
+
const svc = new SdkDictionariesService();
|
|
6445
|
+
const params = {
|
|
6446
|
+
size,
|
|
6447
|
+
sort: opts.sort,
|
|
6448
|
+
keywords: includeKeywords ? true : void 0
|
|
6449
|
+
};
|
|
6450
|
+
const all = opts.all ? await svc.listAll({ ...params, max: Number(opts.max) }) : void 0;
|
|
6164
6451
|
dlpDictionaries.renderList(
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
size,
|
|
6168
|
-
sort: opts.sort,
|
|
6169
|
-
keywords: includeKeywords ? true : void 0
|
|
6170
|
-
}),
|
|
6171
|
-
opts.output
|
|
6452
|
+
all ? { content: all, totalElements: all.length } : await svc.list({ ...params, page }),
|
|
6453
|
+
await resolveOutput(listCmd, opts)
|
|
6172
6454
|
);
|
|
6173
6455
|
} catch (err) {
|
|
6174
6456
|
fail(err);
|
|
@@ -6189,12 +6471,12 @@ function register(dlp) {
|
|
|
6189
6471
|
usageError(err instanceof Error ? err.message : String(err));
|
|
6190
6472
|
}
|
|
6191
6473
|
});
|
|
6192
|
-
group.command("get <id>").option("--keywords", "").option("--include-keywords", "Alias for --keywords").option("--output <fmt>", "Output format
|
|
6474
|
+
const getCmd = group.command("get <id>").option("--keywords", "").option("--include-keywords", "Alias for --keywords").option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (id, opts) => {
|
|
6193
6475
|
try {
|
|
6194
6476
|
const includeKeywords = opts.keywords || opts.includeKeywords;
|
|
6195
6477
|
dlpDictionaries.renderGet(
|
|
6196
6478
|
await new SdkDictionariesService().get(id, { includeKeywords }),
|
|
6197
|
-
opts
|
|
6479
|
+
await resolveOutput(getCmd, opts)
|
|
6198
6480
|
);
|
|
6199
6481
|
} catch (err) {
|
|
6200
6482
|
fail(err);
|
|
@@ -6255,6 +6537,9 @@ var SdkDataFilteringProfilesService = class {
|
|
|
6255
6537
|
async list(params) {
|
|
6256
6538
|
return this.client.list(params);
|
|
6257
6539
|
}
|
|
6540
|
+
async listAll(params) {
|
|
6541
|
+
return this.client.listAll(params);
|
|
6542
|
+
}
|
|
6258
6543
|
async get(id) {
|
|
6259
6544
|
return this.client.get(id);
|
|
6260
6545
|
}
|
|
@@ -6388,7 +6673,7 @@ function listFlags(cmd) {
|
|
|
6388
6673
|
"--offset <n>",
|
|
6389
6674
|
"Starting offset \u2014 rounds down to a page boundary",
|
|
6390
6675
|
(v) => Number.parseInt(v, 10)
|
|
6391
|
-
).option("--sort <field,dir>", "Sort criteria (repeatable)", repeatable).option("--output <fmt>", "Output format
|
|
6676
|
+
).option("--sort <field,dir>", "Sort criteria (repeatable)", repeatable).option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml");
|
|
6392
6677
|
registerPageAliases(cmd, { sizeFlag: "--size", sizeKey: "size" });
|
|
6393
6678
|
return cmd;
|
|
6394
6679
|
}
|
|
@@ -6409,16 +6694,17 @@ function register2(dlp) {
|
|
|
6409
6694
|
try {
|
|
6410
6695
|
const { page, size } = resolvePageParams(listCmd, opts);
|
|
6411
6696
|
const svc = new SdkDataFilteringProfilesService();
|
|
6412
|
-
const
|
|
6413
|
-
|
|
6697
|
+
const all = opts.all ? await svc.listAll({ size, sort: opts.sort, max: Number(opts.max) }) : void 0;
|
|
6698
|
+
const r = all ? { content: all, totalElements: all.length } : await svc.list({ page, size, sort: opts.sort });
|
|
6699
|
+
dlpFilteringProfiles.renderList(r, await resolveOutput(listCmd, opts));
|
|
6414
6700
|
} catch (err) {
|
|
6415
6701
|
fail(err);
|
|
6416
6702
|
}
|
|
6417
6703
|
});
|
|
6418
|
-
group.command("get <id>").description("Get a filtering profile by id").option("--output <fmt>", "Output format
|
|
6704
|
+
const getCmd = group.command("get <id>").description("Get a filtering profile by id").option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (id, opts) => {
|
|
6419
6705
|
try {
|
|
6420
6706
|
const svc = new SdkDataFilteringProfilesService();
|
|
6421
|
-
dlpFilteringProfiles.renderGet(await svc.get(id), opts
|
|
6707
|
+
dlpFilteringProfiles.renderGet(await svc.get(id), await resolveOutput(getCmd, opts));
|
|
6422
6708
|
} catch (err) {
|
|
6423
6709
|
fail(err);
|
|
6424
6710
|
}
|
|
@@ -6514,6 +6800,9 @@ var SdkDataPatternsService = class {
|
|
|
6514
6800
|
async list(params) {
|
|
6515
6801
|
return this.client.list(params);
|
|
6516
6802
|
}
|
|
6803
|
+
async listAll(params) {
|
|
6804
|
+
return this.client.listAll(params);
|
|
6805
|
+
}
|
|
6517
6806
|
async create(body) {
|
|
6518
6807
|
return this.client.create(body);
|
|
6519
6808
|
}
|
|
@@ -6537,7 +6826,7 @@ function listFlags2(cmd) {
|
|
|
6537
6826
|
"--offset <n>",
|
|
6538
6827
|
"Starting offset \u2014 rounds down to a page boundary",
|
|
6539
6828
|
(v) => Number.parseInt(v, 10)
|
|
6540
|
-
).option("--sort <field,dir>", "Sort criteria (repeatable)", repeatable).option("--output <fmt>", "Output format
|
|
6829
|
+
).option("--sort <field,dir>", "Sort criteria (repeatable)", repeatable).option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml");
|
|
6541
6830
|
registerPageAliases(cmd, { sizeFlag: "--size", sizeKey: "size" });
|
|
6542
6831
|
return cmd;
|
|
6543
6832
|
}
|
|
@@ -6559,9 +6848,10 @@ function register4(dlp) {
|
|
|
6559
6848
|
try {
|
|
6560
6849
|
const { page, size } = resolvePageParams(listCmd, opts);
|
|
6561
6850
|
const svc = new SdkDataPatternsService();
|
|
6851
|
+
const result = opts.all ? await svc.listAll({ size, sort: opts.sort, max: Number(opts.max) }) : void 0;
|
|
6562
6852
|
dlpPatterns.renderList(
|
|
6563
|
-
await svc.list({ page, size, sort: opts.sort }),
|
|
6564
|
-
opts
|
|
6853
|
+
result ? { content: result, totalElements: result.length } : await svc.list({ page, size, sort: opts.sort }),
|
|
6854
|
+
await resolveOutput(listCmd, opts)
|
|
6565
6855
|
);
|
|
6566
6856
|
} catch (err) {
|
|
6567
6857
|
fail(err);
|
|
@@ -6579,11 +6869,11 @@ function register4(dlp) {
|
|
|
6579
6869
|
usageError(err instanceof Error ? err.message : String(err));
|
|
6580
6870
|
}
|
|
6581
6871
|
});
|
|
6582
|
-
group.command("get <id>").description("Get a data pattern by id").option("--output <fmt>", "Output format
|
|
6872
|
+
const getCmd = group.command("get <id>").description("Get a data pattern by id").option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (id, opts) => {
|
|
6583
6873
|
try {
|
|
6584
6874
|
dlpPatterns.renderGet(
|
|
6585
6875
|
await new SdkDataPatternsService().get(id),
|
|
6586
|
-
opts
|
|
6876
|
+
await resolveOutput(getCmd, opts)
|
|
6587
6877
|
);
|
|
6588
6878
|
} catch (err) {
|
|
6589
6879
|
fail(err);
|
|
@@ -6639,6 +6929,9 @@ var SdkDataProfilesService = class {
|
|
|
6639
6929
|
async list(params) {
|
|
6640
6930
|
return this.client.list(params);
|
|
6641
6931
|
}
|
|
6932
|
+
async listAll(params) {
|
|
6933
|
+
return this.client.listAll(params);
|
|
6934
|
+
}
|
|
6642
6935
|
async create(body) {
|
|
6643
6936
|
return this.client.create(body);
|
|
6644
6937
|
}
|
|
@@ -6659,7 +6952,7 @@ function listFlags3(cmd) {
|
|
|
6659
6952
|
"--offset <n>",
|
|
6660
6953
|
"Starting offset \u2014 rounds down to a page boundary",
|
|
6661
6954
|
(v) => Number.parseInt(v, 10)
|
|
6662
|
-
).option("--sort <field,dir>", "Sort criteria (repeatable)", repeatable).option("--output <fmt>", "Output format
|
|
6955
|
+
).option("--sort <field,dir>", "Sort criteria (repeatable)", repeatable).option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml");
|
|
6663
6956
|
registerPageAliases(cmd, { sizeFlag: "--size", sizeKey: "size" });
|
|
6664
6957
|
return cmd;
|
|
6665
6958
|
}
|
|
@@ -6693,9 +6986,10 @@ function register5(dlp) {
|
|
|
6693
6986
|
try {
|
|
6694
6987
|
const { page, size } = resolvePageParams(listCmd, opts);
|
|
6695
6988
|
const svc = new SdkDataProfilesService();
|
|
6989
|
+
const result = opts.all ? await svc.listAll({ size, sort: opts.sort, max: Number(opts.max) }) : void 0;
|
|
6696
6990
|
dlpProfiles.renderList(
|
|
6697
|
-
await svc.list({ page, size, sort: opts.sort }),
|
|
6698
|
-
opts
|
|
6991
|
+
result ? { content: result, totalElements: result.length } : await svc.list({ page, size, sort: opts.sort }),
|
|
6992
|
+
await resolveOutput(listCmd, opts)
|
|
6699
6993
|
);
|
|
6700
6994
|
} catch (err) {
|
|
6701
6995
|
fail(err);
|
|
@@ -6713,11 +7007,11 @@ function register5(dlp) {
|
|
|
6713
7007
|
usageError(err instanceof Error ? err.message : String(err));
|
|
6714
7008
|
}
|
|
6715
7009
|
});
|
|
6716
|
-
group.command("get <id>").description("Get a data profile by id").option("--output <fmt>", "Output format
|
|
7010
|
+
const getCmd = group.command("get <id>").description("Get a data profile by id").option("--output <fmt>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (id, opts) => {
|
|
6717
7011
|
try {
|
|
6718
7012
|
dlpProfiles.renderGet(
|
|
6719
7013
|
await new SdkDataProfilesService().get(id),
|
|
6720
|
-
opts
|
|
7014
|
+
await resolveOutput(getCmd, opts)
|
|
6721
7015
|
);
|
|
6722
7016
|
} catch (err) {
|
|
6723
7017
|
fail(err);
|
|
@@ -7365,15 +7659,26 @@ async function createMgmtService() {
|
|
|
7365
7659
|
function registerRuntimeCommand(program) {
|
|
7366
7660
|
const runtime = program.command("runtime").description("Runtime prompt scanning against AIRS profiles");
|
|
7367
7661
|
const apiKeys = runtime.command("api-keys").description("Manage AIRS API keys");
|
|
7368
|
-
apiKeys.command("list").description("List API keys").option("--
|
|
7662
|
+
const apiKeysList = registerListFlags(apiKeys.command("list"), { dialect: "offset" }).description("List API keys").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (opts) => {
|
|
7369
7663
|
try {
|
|
7370
|
-
const fmt = opts
|
|
7664
|
+
const fmt = await resolveOutput(apiKeysList, opts);
|
|
7665
|
+
const page = resolveListParams(apiKeysList, opts, { dialect: "offset" });
|
|
7371
7666
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
7372
7667
|
const service = await createMgmtService();
|
|
7668
|
+
if (page.all) {
|
|
7669
|
+
const items = await service.listAllApiKeys({ limit: page.limit, max: page.max });
|
|
7670
|
+
emitList(apiKeysView, items, fmt, {
|
|
7671
|
+
page: { returned: items.length, total: items.length, all: true }
|
|
7672
|
+
});
|
|
7673
|
+
return;
|
|
7674
|
+
}
|
|
7373
7675
|
const result = await service.listApiKeys({
|
|
7374
|
-
limit:
|
|
7676
|
+
limit: page.limit,
|
|
7677
|
+
offset: page.offset
|
|
7678
|
+
});
|
|
7679
|
+
emitList(apiKeysView, result.apiKeys, fmt, {
|
|
7680
|
+
page: { returned: result.apiKeys.length, next: result.nextOffset }
|
|
7375
7681
|
});
|
|
7376
|
-
renderApiKeyList(result.apiKeys, fmt);
|
|
7377
7682
|
} catch (err) {
|
|
7378
7683
|
fail(err);
|
|
7379
7684
|
}
|
|
@@ -7560,25 +7865,37 @@ function registerRuntimeCommand(program) {
|
|
|
7560
7865
|
}
|
|
7561
7866
|
});
|
|
7562
7867
|
const customerApps = runtime.command("customer-apps").description("Manage AIRS customer apps");
|
|
7563
|
-
customerApps.command("list").description("List customer apps").option("--
|
|
7868
|
+
const customerAppsList = registerListFlags(customerApps.command("list"), { dialect: "offset" }).description("List customer apps").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (opts) => {
|
|
7564
7869
|
try {
|
|
7565
|
-
const fmt = opts
|
|
7870
|
+
const fmt = await resolveOutput(customerAppsList, opts);
|
|
7871
|
+
const page = resolveListParams(customerAppsList, opts, { dialect: "offset" });
|
|
7566
7872
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
7567
7873
|
const service = await createMgmtService();
|
|
7874
|
+
if (page.all) {
|
|
7875
|
+
const items = await service.listAllCustomerApps({ limit: page.limit, max: page.max });
|
|
7876
|
+
emitList(customerAppsView, items, fmt, {
|
|
7877
|
+
page: { returned: items.length, total: items.length, all: true }
|
|
7878
|
+
});
|
|
7879
|
+
return;
|
|
7880
|
+
}
|
|
7568
7881
|
const result = await service.listCustomerApps({
|
|
7569
|
-
limit:
|
|
7882
|
+
limit: page.limit,
|
|
7883
|
+
offset: page.offset
|
|
7884
|
+
});
|
|
7885
|
+
emitList(customerAppsView, result.apps, fmt, {
|
|
7886
|
+
page: { returned: result.apps.length, next: result.nextOffset }
|
|
7570
7887
|
});
|
|
7571
|
-
renderCustomerAppList(result.apps, fmt);
|
|
7572
7888
|
} catch (err) {
|
|
7573
7889
|
fail(err);
|
|
7574
7890
|
}
|
|
7575
7891
|
});
|
|
7576
|
-
customerApps.command("get <appName>").description("Get customer app details").action(async (appName) => {
|
|
7892
|
+
const customerAppsGet = customerApps.command("get <appName>").description("Get customer app details").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (appName, opts) => {
|
|
7577
7893
|
try {
|
|
7578
|
-
|
|
7894
|
+
const fmt = await resolveOutput(customerAppsGet, opts);
|
|
7895
|
+
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
7579
7896
|
const service = await createMgmtService();
|
|
7580
7897
|
const app = await service.getCustomerApp(appName);
|
|
7581
|
-
|
|
7898
|
+
emitDetail(customerAppsView, app, fmt);
|
|
7582
7899
|
} catch (err) {
|
|
7583
7900
|
fail(err);
|
|
7584
7901
|
}
|
|
@@ -7605,14 +7922,14 @@ function registerRuntimeCommand(program) {
|
|
|
7605
7922
|
fail(err);
|
|
7606
7923
|
}
|
|
7607
7924
|
});
|
|
7608
|
-
customerApps.command("consumption").argument(
|
|
7925
|
+
const customerAppsConsumption = customerApps.command("consumption").argument(
|
|
7609
7926
|
"[appName]",
|
|
7610
7927
|
"Dashboard application name \u2014 the literal scan-payload metadata.app_name, as shown in the SCM AI Applications view (may differ from the SCM-registered customer-app name). Omit to report every dashboard bucket."
|
|
7611
7928
|
).description(
|
|
7612
7929
|
"Show per-app token consumption + violation breakdown (SCM dashboard). Omit appName to scan all apps."
|
|
7613
|
-
).option("--time-interval <n>", "Window in days: 7, 30, or 60", "30").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
7930
|
+
).option("--time-interval <n>", "Window in days: 7, 30, or 60", "30").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (appName, opts) => {
|
|
7614
7931
|
try {
|
|
7615
|
-
const fmt = opts
|
|
7932
|
+
const fmt = await resolveOutput(customerAppsConsumption, opts);
|
|
7616
7933
|
const interval = Number.parseInt(opts.timeInterval, 10);
|
|
7617
7934
|
if (interval !== 7 && interval !== 30 && interval !== 60) {
|
|
7618
7935
|
usageError("--time-interval must be 7, 30, or 60 (the API rejects other values)");
|
|
@@ -7646,9 +7963,9 @@ function registerRuntimeCommand(program) {
|
|
|
7646
7963
|
}
|
|
7647
7964
|
});
|
|
7648
7965
|
const deploymentProfiles = runtime.command("deployment-profiles").description("List AIRS deployment profiles");
|
|
7649
|
-
deploymentProfiles.command("list").description("List deployment profiles").option("--unactivated", "Include unactivated profiles").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
7966
|
+
const deploymentProfilesList = deploymentProfiles.command("list").description("List deployment profiles").option("--unactivated", "Include unactivated profiles").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (opts) => {
|
|
7650
7967
|
try {
|
|
7651
|
-
const fmt = opts
|
|
7968
|
+
const fmt = await resolveOutput(deploymentProfilesList, opts);
|
|
7652
7969
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
7653
7970
|
const service = await createMgmtService();
|
|
7654
7971
|
const profiles2 = await service.listDeploymentProfiles({
|
|
@@ -7660,7 +7977,7 @@ function registerRuntimeCommand(program) {
|
|
|
7660
7977
|
}
|
|
7661
7978
|
});
|
|
7662
7979
|
const profiles = runtime.command("profiles").description("Manage AIRS security profiles");
|
|
7663
|
-
profiles.command("list").description("List security profiles").option("--
|
|
7980
|
+
const profilesList = registerListFlags(profiles.command("list"), { dialect: "offset" }).description("List security profiles").option("--all-versions", "Include every profile revision").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
7664
7981
|
"after",
|
|
7665
7982
|
examples(
|
|
7666
7983
|
"airs runtime profiles list",
|
|
@@ -7669,49 +7986,55 @@ function registerRuntimeCommand(program) {
|
|
|
7669
7986
|
)
|
|
7670
7987
|
).action(async (opts) => {
|
|
7671
7988
|
try {
|
|
7672
|
-
const fmt = opts
|
|
7673
|
-
|
|
7674
|
-
usageError(`Invalid output format "${fmt}". Valid: ${OUTPUT_FORMATS.join(", ")}`);
|
|
7675
|
-
}
|
|
7989
|
+
const fmt = await resolveOutput(profilesList, opts);
|
|
7990
|
+
const page = resolveListParams(profilesList, opts, { dialect: "offset" });
|
|
7676
7991
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
7677
7992
|
const service = await createMgmtService();
|
|
7993
|
+
if (page.all) {
|
|
7994
|
+
const items = await service.listAllProfiles({
|
|
7995
|
+
limit: page.limit,
|
|
7996
|
+
latest: !opts.allVersions,
|
|
7997
|
+
max: page.max
|
|
7998
|
+
});
|
|
7999
|
+
emitList(profilesView, items, fmt, {
|
|
8000
|
+
page: { returned: items.length, total: items.length, all: true }
|
|
8001
|
+
});
|
|
8002
|
+
return;
|
|
8003
|
+
}
|
|
7678
8004
|
const result = await service.listProfiles({
|
|
7679
|
-
limit:
|
|
7680
|
-
offset:
|
|
8005
|
+
limit: page.limit,
|
|
8006
|
+
offset: page.offset,
|
|
8007
|
+
latest: !opts.allVersions
|
|
8008
|
+
});
|
|
8009
|
+
emitList(profilesView, result.profiles, fmt, {
|
|
8010
|
+
page: {
|
|
8011
|
+
returned: result.profiles.length,
|
|
8012
|
+
next: result.nextOffset
|
|
8013
|
+
}
|
|
7681
8014
|
});
|
|
7682
|
-
renderProfileList(result.profiles, fmt);
|
|
7683
|
-
if (fmt === "pretty" && result.nextOffset != null) {
|
|
7684
|
-
ui.dim(`Next offset: ${result.nextOffset}`);
|
|
7685
|
-
}
|
|
7686
8015
|
} catch (err) {
|
|
7687
8016
|
fail(err);
|
|
7688
8017
|
}
|
|
7689
8018
|
});
|
|
7690
|
-
profiles.command("get <nameOrId>").description("Get a security profile by name or UUID").option("--output <format>", "Output format: pretty, json, yaml"
|
|
8019
|
+
const profilesGet = profiles.command("get <nameOrId>").description("Get a security profile by name or UUID").option("--revision <n>", "Select an exact revision", Number).option("--all-versions", "Return every matching revision").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (nameOrId, opts) => {
|
|
7691
8020
|
try {
|
|
7692
|
-
const fmt = opts
|
|
7693
|
-
if (fmt !== "pretty" && fmt !== "json" && fmt !== "yaml") {
|
|
7694
|
-
usageError(`Invalid output format "${fmt}". Valid: pretty, json, yaml`);
|
|
7695
|
-
}
|
|
8021
|
+
const fmt = await resolveOutput(profilesGet, opts);
|
|
7696
8022
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
7697
8023
|
const service = await createMgmtService();
|
|
7698
8024
|
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
|
|
7699
8025
|
nameOrId
|
|
7700
8026
|
);
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
const
|
|
7706
|
-
if (
|
|
7707
|
-
if (
|
|
7708
|
-
|
|
7709
|
-
if (profile.updatedBy) lines.push(`updatedBy: ${profile.updatedBy}`);
|
|
7710
|
-
if (profile.lastModifiedTs) lines.push(`lastModifiedTs: ${profile.lastModifiedTs}`);
|
|
7711
|
-
if (profile.policy) lines.push(`policy: ${JSON.stringify(profile.policy, null, 2)}`);
|
|
7712
|
-
console.log(lines.join("\n"));
|
|
8027
|
+
if (opts.revision !== void 0 || opts.allVersions) {
|
|
8028
|
+
const profiles2 = (await service.listAllProfiles({ latest: false })).filter(
|
|
8029
|
+
(profile) => isUuid ? profile.profileId === nameOrId : profile.profileName === nameOrId
|
|
8030
|
+
);
|
|
8031
|
+
const selected = opts.revision === void 0 ? profiles2 : profiles2.filter((profile) => profile.revision === opts.revision);
|
|
8032
|
+
if (selected.length === 0) throw new Error(`Profile ${nameOrId} not found`);
|
|
8033
|
+
if (opts.allVersions) emitList(profilesView, selected, fmt);
|
|
8034
|
+
else emitDetail(profilesView, selected[0], fmt);
|
|
7713
8035
|
} else {
|
|
7714
|
-
|
|
8036
|
+
const profile = isUuid ? await service.getProfile(nameOrId) : await service.getProfileByName(nameOrId);
|
|
8037
|
+
emitDetail(profilesView, profile, fmt);
|
|
7715
8038
|
}
|
|
7716
8039
|
} catch (err) {
|
|
7717
8040
|
fail(err);
|
|
@@ -7994,12 +8317,12 @@ function registerRuntimeCommand(program) {
|
|
|
7994
8317
|
}
|
|
7995
8318
|
});
|
|
7996
8319
|
const scanLogs = runtime.command("scan-logs").description("Query AIRS scan logs");
|
|
7997
|
-
const scanLogsQuery = scanLogs.command("query").description("Query scan logs").requiredOption("--interval <n>", "Time interval").requiredOption("--unit <unit>", "Time unit (hours)").option("--filter <filter>", "Filter: all, benign, threat", "all").option("--limit <n>", "Max results per page (API page size)", "50").option("--offset <n>", "Starting offset \u2014 rounds down to a page boundary", "0").option("--output <format>", "Output format: pretty, table, csv, json, yaml"
|
|
8320
|
+
const scanLogsQuery = scanLogs.command("query").description("Query scan logs").requiredOption("--interval <n>", "Time interval").requiredOption("--unit <unit>", "Time unit (hours)").option("--filter <filter>", "Filter: all, benign, threat", "all").option("--limit <n>", "Max results per page (API page size)", "50").option("--offset <n>", "Starting offset \u2014 rounds down to a page boundary", "0").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml");
|
|
7998
8321
|
registerPageAliases(scanLogsQuery, { sizeFlag: "--page-size", sizeKey: "pageSize" });
|
|
7999
8322
|
scanLogsQuery.action(async (opts) => {
|
|
8000
8323
|
try {
|
|
8001
8324
|
const { page, size } = resolvePageParams(scanLogsQuery, opts, { indexBase: 1 });
|
|
8002
|
-
const fmt = opts
|
|
8325
|
+
const fmt = await resolveOutput(scanLogsQuery, opts);
|
|
8003
8326
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
8004
8327
|
const service = await createMgmtService();
|
|
8005
8328
|
const result = await service.queryScanLogs({
|
|
@@ -8036,52 +8359,47 @@ function registerRuntimeCommand(program) {
|
|
|
8036
8359
|
}
|
|
8037
8360
|
});
|
|
8038
8361
|
registerEvalCommand(topics);
|
|
8039
|
-
topics.command("get <nameOrId>").description("Get a custom topic by name or UUID").option("--output <format>", "Output format: pretty, json, yaml"
|
|
8362
|
+
const topicsGet = topics.command("get <nameOrId>").description("Get a custom topic by name or UUID").option("--revision <n>", "Select an exact revision", Number).option("--all-versions", "Return every matching revision").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (nameOrId, opts) => {
|
|
8040
8363
|
try {
|
|
8041
|
-
const fmt = opts
|
|
8042
|
-
if (fmt !== "pretty" && fmt !== "json" && fmt !== "yaml") {
|
|
8043
|
-
usageError(`Invalid output format "${fmt}". Valid: pretty, json, yaml`);
|
|
8044
|
-
}
|
|
8364
|
+
const fmt = await resolveOutput(topicsGet, opts);
|
|
8045
8365
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
8046
8366
|
const service = await createMgmtService();
|
|
8047
8367
|
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
|
|
8048
8368
|
nameOrId
|
|
8049
8369
|
);
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
const
|
|
8055
|
-
if (
|
|
8056
|
-
if (
|
|
8057
|
-
|
|
8058
|
-
lines.push("examples:");
|
|
8059
|
-
for (const ex of topic.examples) lines.push(` - ${ex}`);
|
|
8060
|
-
}
|
|
8061
|
-
if (topic.created_by) lines.push(`created_by: ${topic.created_by}`);
|
|
8062
|
-
if (topic.updated_by) lines.push(`updated_by: ${topic.updated_by}`);
|
|
8063
|
-
if (topic.last_modified_ts) lines.push(`last_modified_ts: ${topic.last_modified_ts}`);
|
|
8064
|
-
console.log(lines.join("\n"));
|
|
8370
|
+
if (opts.revision !== void 0 || opts.allVersions) {
|
|
8371
|
+
const topics2 = (await service.listTopics()).filter(
|
|
8372
|
+
(topic) => isUuid ? topic.topic_id === nameOrId : topic.topic_name === nameOrId
|
|
8373
|
+
);
|
|
8374
|
+
const selected = opts.revision === void 0 ? topics2 : topics2.filter((topic) => topic.revision === opts.revision);
|
|
8375
|
+
if (selected.length === 0) throw new Error(`Topic ${nameOrId} not found`);
|
|
8376
|
+
if (opts.allVersions) emitList(topicsView, selected, fmt);
|
|
8377
|
+
else emitDetail(topicsView, selected[0], fmt);
|
|
8065
8378
|
} else {
|
|
8066
|
-
|
|
8379
|
+
const topic = isUuid ? await service.getTopic(nameOrId) : await service.getTopicByName(nameOrId);
|
|
8380
|
+
emitDetail(topicsView, topic, fmt);
|
|
8067
8381
|
}
|
|
8068
8382
|
} catch (err) {
|
|
8069
8383
|
fail(err);
|
|
8070
8384
|
}
|
|
8071
8385
|
});
|
|
8072
|
-
topics.command("list").description("List custom topics").option("--
|
|
8386
|
+
const topicsList = registerListFlags(topics.command("list"), { dialect: "offset" }).description("List custom topics").option("--all-versions", "Include every topic revision").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").action(async (opts) => {
|
|
8073
8387
|
try {
|
|
8074
|
-
const fmt = opts
|
|
8388
|
+
const fmt = await resolveOutput(topicsList, opts);
|
|
8389
|
+
const params = resolveListParams(topicsList, opts, { dialect: "offset" });
|
|
8075
8390
|
if (fmt === "pretty") renderRuntimeConfigHeader();
|
|
8076
8391
|
const service = await createMgmtService();
|
|
8077
|
-
const allTopics = await service.listTopics()
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
const page = allTopics.slice(offset, offset + limit);
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8392
|
+
const allTopics = opts.allVersions ? await service.listTopics() : await service.listLatestTopics(
|
|
8393
|
+
params.all ? { offset: 0, limit: params.max === 0 ? 1e4 : params.max } : { offset: params.offset, limit: params.limit }
|
|
8394
|
+
);
|
|
8395
|
+
const page = opts.allVersions && !params.all ? allTopics.slice(params.offset, params.offset + params.limit) : allTopics;
|
|
8396
|
+
emitList(topicsView, page, fmt, {
|
|
8397
|
+
page: params.all ? { returned: page.length, total: page.length, all: true } : {
|
|
8398
|
+
returned: page.length,
|
|
8399
|
+
total: opts.allVersions ? allTopics.length : void 0,
|
|
8400
|
+
next: opts.allVersions && params.offset + params.limit < allTopics.length ? params.offset + params.limit : void 0
|
|
8401
|
+
}
|
|
8402
|
+
});
|
|
8085
8403
|
} catch (err) {
|
|
8086
8404
|
fail(err);
|
|
8087
8405
|
}
|
|
@@ -8283,6 +8601,27 @@ function installDebugLogger(logPath) {
|
|
|
8283
8601
|
}
|
|
8284
8602
|
|
|
8285
8603
|
// src/cli/program.ts
|
|
8604
|
+
var READ_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
8605
|
+
"categories",
|
|
8606
|
+
"consumption",
|
|
8607
|
+
"evaluation",
|
|
8608
|
+
"evaluations",
|
|
8609
|
+
"files",
|
|
8610
|
+
"get",
|
|
8611
|
+
"languages",
|
|
8612
|
+
"list",
|
|
8613
|
+
"pypi-auth",
|
|
8614
|
+
"query",
|
|
8615
|
+
"registry-credentials",
|
|
8616
|
+
"report",
|
|
8617
|
+
"stats",
|
|
8618
|
+
"status",
|
|
8619
|
+
"values",
|
|
8620
|
+
"version",
|
|
8621
|
+
"versions",
|
|
8622
|
+
"violation",
|
|
8623
|
+
"violations"
|
|
8624
|
+
]);
|
|
8286
8625
|
function applyListDeleteAliases(cmd) {
|
|
8287
8626
|
for (const sub of cmd.commands) {
|
|
8288
8627
|
if (sub.name() === "list" && !sub.aliases().includes("ls")) sub.alias("ls");
|
|
@@ -8290,16 +8629,45 @@ function applyListDeleteAliases(cmd) {
|
|
|
8290
8629
|
applyListDeleteAliases(sub);
|
|
8291
8630
|
}
|
|
8292
8631
|
}
|
|
8632
|
+
function applyReadContractFlags(cmd) {
|
|
8633
|
+
for (const sub of cmd.commands) {
|
|
8634
|
+
const flags = () => sub.options.map((option) => option.long);
|
|
8635
|
+
if ((sub.name() === "list" || sub.name() === "get") && !flags().includes("--output")) {
|
|
8636
|
+
sub.option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml");
|
|
8637
|
+
}
|
|
8638
|
+
if (sub.name() === "list" && (flags().includes("--limit") || flags().includes("--offset"))) {
|
|
8639
|
+
if (!flags().includes("--limit")) sub.option("--limit <n>", "Items per page", Number, 50);
|
|
8640
|
+
if (!flags().includes("--offset")) sub.option("--offset <n>", "Item offset", Number, 0);
|
|
8641
|
+
if (!flags().includes("--all")) sub.option("--all", "Walk all pages");
|
|
8642
|
+
if (!flags().includes("--max")) {
|
|
8643
|
+
sub.option("--max <n>", "Maximum items with --all; 0 removes the cap", Number, 1e4);
|
|
8644
|
+
}
|
|
8645
|
+
}
|
|
8646
|
+
applyReadContractFlags(sub);
|
|
8647
|
+
}
|
|
8648
|
+
}
|
|
8649
|
+
function applySortedHelp(cmd) {
|
|
8650
|
+
cmd.configureHelp({ sortOptions: true, sortSubcommands: true });
|
|
8651
|
+
for (const sub of cmd.commands) applySortedHelp(sub);
|
|
8652
|
+
}
|
|
8293
8653
|
function buildProgram() {
|
|
8294
8654
|
const here = dirname4(fileURLToPath(import.meta.url));
|
|
8295
8655
|
const pkg = JSON.parse(readFileSync4(join4(here, "../../package.json"), "utf-8"));
|
|
8296
8656
|
const program = new Command();
|
|
8297
8657
|
program.name("airs").description(
|
|
8298
8658
|
"CLI and library for Palo Alto Prisma AIRS \u2014 guardrail refinement, AI red teaming, model security scanning, profile audits"
|
|
8299
|
-
).version(pkg.version).option("--debug", "Log all AIRS/SCM API requests and responses to a JSONL file").option("--quiet", "Suppress status and decorative output (data and errors still print)");
|
|
8300
|
-
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
8659
|
+
).version(pkg.version).option("--debug", "Log all AIRS/SCM API requests and responses to a JSONL file").option("--output <format>", "Default output format for read commands").option("--quiet", "Suppress status and decorative output (data and errors still print)");
|
|
8660
|
+
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
8301
8661
|
const root = actionCommand.optsWithGlobals?.() ?? _thisCommand.opts();
|
|
8302
8662
|
setQuiet(Boolean(root.quiet));
|
|
8663
|
+
if (READ_COMMAND_NAMES.has(actionCommand.name()) && actionCommand.options.some((option) => option.long === "--output")) {
|
|
8664
|
+
try {
|
|
8665
|
+
const format = await resolveOutput(actionCommand, actionCommand.opts());
|
|
8666
|
+
actionCommand.setOptionValueWithSource("output", format, "implied");
|
|
8667
|
+
} catch (error) {
|
|
8668
|
+
fail(error);
|
|
8669
|
+
}
|
|
8670
|
+
}
|
|
8303
8671
|
if (root.debug) {
|
|
8304
8672
|
const logPath = join4(homedir(), ".prisma-airs", `debug-api-${Date.now()}.jsonl`);
|
|
8305
8673
|
installDebugLogger(logPath);
|
|
@@ -8314,6 +8682,8 @@ function buildProgram() {
|
|
|
8314
8682
|
registerDoctorCommand(program);
|
|
8315
8683
|
registerCompletionCommand(program);
|
|
8316
8684
|
applyListDeleteAliases(program);
|
|
8685
|
+
applyReadContractFlags(program);
|
|
8686
|
+
applySortedHelp(program);
|
|
8317
8687
|
return program;
|
|
8318
8688
|
}
|
|
8319
8689
|
|