@cdot65/prisma-airs-cli 4.2.2 → 4.3.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 +2 -2
- package/dist/cli/index.js +144 -54
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/cdot65/prisma-airs-cli/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/@cdot65/prisma-airs-cli)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
|
-
[](https://nodejs.org/)
|
|
9
9
|
|
|
10
10
|
**Full operational coverage over Palo Alto Prisma AIRS AI security — guardrail refinement, runtime scanning, AI red teaming, AI Gateway, and model security.**
|
|
11
11
|
|
|
@@ -30,7 +30,7 @@ npm install -g @cdot65/prisma-airs-cli
|
|
|
30
30
|
airs --version
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Requires **Node.js
|
|
33
|
+
Requires **Node.js 20.17+, 22.13+, or 24+** (exact engine range: `^20.17.0 || ^22.13.0 || >=23.5.0`). Also available via `pnpm add -g`, `npx`, or as a [Docker image](https://github.com/cdot65/prisma-airs-cli/pkgs/container/prisma-airs-cli). See the [installation guide](https://cdot65.github.io/prisma-airs-cli/getting-started/installation/) for details.
|
|
34
34
|
|
|
35
35
|
## Quick Start
|
|
36
36
|
|
package/dist/cli/index.js
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
|
|
55
55
|
// src/airs/aigateway.ts
|
|
56
56
|
import {
|
|
57
|
+
AIGatewayChartFiltersSchema,
|
|
57
58
|
AIGatewayClient
|
|
58
59
|
} from "@cdot65/prisma-airs-sdk";
|
|
59
60
|
function toLimitArray(value) {
|
|
@@ -164,7 +165,7 @@ var SdkAiGatewayService = class {
|
|
|
164
165
|
* Match a user-supplied ref against the workspace list so name | slug |
|
|
165
166
|
* uuid all work. Unmatched refs pass through so the API's own error stands.
|
|
166
167
|
*/
|
|
167
|
-
async resolveWorkspaceRef(ref, planes) {
|
|
168
|
+
async resolveWorkspaceRef(ref, planes, requireSlug = false) {
|
|
168
169
|
for (const plane of planes) {
|
|
169
170
|
let rows;
|
|
170
171
|
try {
|
|
@@ -172,7 +173,8 @@ var SdkAiGatewayService = class {
|
|
|
172
173
|
} catch {
|
|
173
174
|
continue;
|
|
174
175
|
}
|
|
175
|
-
|
|
176
|
+
const byRef = rows.find((w) => w.id === ref || w.slug === ref);
|
|
177
|
+
if (byRef) return requireSlug ? byRef.slug : ref;
|
|
176
178
|
const byName = rows.filter((w) => w.name === ref);
|
|
177
179
|
if (byName.length > 1) {
|
|
178
180
|
throw new Error(
|
|
@@ -184,11 +186,15 @@ var SdkAiGatewayService = class {
|
|
|
184
186
|
return ref;
|
|
185
187
|
}
|
|
186
188
|
async getTelemetryCost(opts) {
|
|
187
|
-
const days =
|
|
188
|
-
const
|
|
189
|
+
const { workspaceSlug: workspaceRef, days = 7, ...rawFilters } = opts;
|
|
190
|
+
const filters = AIGatewayChartFiltersSchema.parse(rawFilters);
|
|
191
|
+
if (!Number.isSafeInteger(days) || days <= 0)
|
|
192
|
+
throw new Error("Expected days to be a positive integer");
|
|
193
|
+
const workspaceSlug = await this.resolveWorkspaceRef(workspaceRef, ["data", "admin"], true);
|
|
189
194
|
const raw = await this.client.telemetry.cost({
|
|
190
195
|
workspaceSlug,
|
|
191
|
-
days
|
|
196
|
+
days,
|
|
197
|
+
...filters
|
|
192
198
|
});
|
|
193
199
|
return {
|
|
194
200
|
workspaceSlug,
|
|
@@ -4543,6 +4549,52 @@ function registerAiGatewayInventory(root) {
|
|
|
4543
4549
|
);
|
|
4544
4550
|
}
|
|
4545
4551
|
|
|
4552
|
+
// src/cli/commands/aigateway/telemetry-filters.ts
|
|
4553
|
+
import { AIGatewayChartFiltersSchema as AIGatewayChartFiltersSchema2 } from "@cdot65/prisma-airs-sdk";
|
|
4554
|
+
function addChartFilterOptions(command) {
|
|
4555
|
+
return command.option("--trace-id <id>", "Filter by one trace ID").option("--metadata <json>", "Filter by string-valued metadata (JSON object)").option("--status-codes <codes>", "Comma-separated HTTP statuses (OR within the list)").option("--api-key-ids <ids>", "Comma-separated service key UUIDs (not secret key values)").option(
|
|
4556
|
+
"--ai-org-models <pairs>",
|
|
4557
|
+
"Comma-separated provider__model pairs, e.g. openai__gpt-5.6-terra"
|
|
4558
|
+
).option("--total-units-min <n>", "Inclusive minimum total tokens (nonnegative integer)").option("--total-units-max <n>", "Inclusive maximum total tokens (nonnegative integer)").option("--cost-min <cents>", "Inclusive minimum cost in cents (fractional cents allowed)").option("--cost-max <cents>", "Inclusive maximum cost in cents (fractional cents allowed)");
|
|
4559
|
+
}
|
|
4560
|
+
function csv(value) {
|
|
4561
|
+
const values = value.split(",").map((entry) => entry.trim());
|
|
4562
|
+
if (values.some((entry) => entry.length === 0)) throw new CliUsageError("Empty CSV element");
|
|
4563
|
+
return values;
|
|
4564
|
+
}
|
|
4565
|
+
function decimal(value) {
|
|
4566
|
+
if (!/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(value)) {
|
|
4567
|
+
throw new CliUsageError("Expected a decimal number");
|
|
4568
|
+
}
|
|
4569
|
+
return Number(value);
|
|
4570
|
+
}
|
|
4571
|
+
function chartFiltersFrom(opts) {
|
|
4572
|
+
const filters = {};
|
|
4573
|
+
try {
|
|
4574
|
+
if (opts.traceId !== void 0) filters.traceId = opts.traceId;
|
|
4575
|
+
if (opts.metadata !== void 0) filters.metadata = parseJsonOption(opts.metadata);
|
|
4576
|
+
if (opts.statusCodes !== void 0)
|
|
4577
|
+
filters.statusCodes = csv(opts.statusCodes).map(parseIntegerOption);
|
|
4578
|
+
if (opts.apiKeyIds !== void 0) filters.apiKeyIds = csv(opts.apiKeyIds);
|
|
4579
|
+
if (opts.aiOrgModels !== void 0) filters.aiOrgModels = csv(opts.aiOrgModels);
|
|
4580
|
+
for (const key of ["totalUnitsMin", "totalUnitsMax"]) {
|
|
4581
|
+
if (opts[key] !== void 0) filters[key] = parseIntegerOption(opts[key]);
|
|
4582
|
+
}
|
|
4583
|
+
for (const key of ["costMin", "costMax"]) {
|
|
4584
|
+
if (opts[key] !== void 0) filters[key] = decimal(opts[key]);
|
|
4585
|
+
}
|
|
4586
|
+
} catch {
|
|
4587
|
+
throw new CliUsageError("Invalid chart filters: check JSON, CSV and numeric flag syntax");
|
|
4588
|
+
}
|
|
4589
|
+
const result = AIGatewayChartFiltersSchema2.safeParse(filters);
|
|
4590
|
+
if (!result.success) {
|
|
4591
|
+
throw new CliUsageError(
|
|
4592
|
+
"Invalid chart filters: check status codes, UUIDs, provider__model pairs, string metadata and inclusive nonnegative bounds"
|
|
4593
|
+
);
|
|
4594
|
+
}
|
|
4595
|
+
return result.data;
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4546
4598
|
// src/cli/commands/aigateway/telemetry.ts
|
|
4547
4599
|
function addWindowOptions(command) {
|
|
4548
4600
|
return addReadOutput(
|
|
@@ -4582,6 +4634,20 @@ function registerMetric(telemetry, name, description, method) {
|
|
|
4582
4634
|
(opts) => runDetail(command, opts, (client) => client.telemetry[method](windowFrom(opts)))
|
|
4583
4635
|
);
|
|
4584
4636
|
}
|
|
4637
|
+
function registerFilteredMetric(telemetry, name, description) {
|
|
4638
|
+
const command = addChartFilterOptions(
|
|
4639
|
+
addWindowOptions(telemetry.command(name).description(description))
|
|
4640
|
+
);
|
|
4641
|
+
command.action(async (opts) => {
|
|
4642
|
+
let options;
|
|
4643
|
+
try {
|
|
4644
|
+
options = { ...windowFrom(opts), ...chartFiltersFrom(opts) };
|
|
4645
|
+
} catch (error) {
|
|
4646
|
+
failAiGateway(error);
|
|
4647
|
+
}
|
|
4648
|
+
await runDetail(command, opts, (client) => client.telemetry[name](options));
|
|
4649
|
+
});
|
|
4650
|
+
}
|
|
4585
4651
|
function registerAiGatewayTelemetryReads(telemetry) {
|
|
4586
4652
|
const cache = showHelpOnEmpty(telemetry.command("cache").description("Inspect cache telemetry"));
|
|
4587
4653
|
const cacheSummary = addWindowOptions(cache.command("summary").description("Get cache totals"));
|
|
@@ -4622,7 +4688,7 @@ function registerAiGatewayTelemetryReads(telemetry) {
|
|
|
4622
4688
|
})
|
|
4623
4689
|
)
|
|
4624
4690
|
);
|
|
4625
|
-
|
|
4691
|
+
registerFilteredMetric(telemetry, "latency", "Get latency telemetry");
|
|
4626
4692
|
const logs = showHelpOnEmpty(telemetry.command("logs").description("Inspect request logs"));
|
|
4627
4693
|
const logsList = addWindowOptions(
|
|
4628
4694
|
logs.command("list").description("List request logs").option("--page-size <n>", "Rows per response", "50").option("--status-code <code>", "Filter by HTTP status").option("--trace-id <id>", "Return one trace id")
|
|
@@ -4639,9 +4705,9 @@ function registerAiGatewayTelemetryReads(telemetry) {
|
|
|
4639
4705
|
})
|
|
4640
4706
|
)
|
|
4641
4707
|
);
|
|
4642
|
-
|
|
4708
|
+
registerFilteredMetric(telemetry, "requests", "Get request count");
|
|
4643
4709
|
registerMetric(telemetry, "rescued-retries", "Get rescued retry telemetry", "rescuedRetries");
|
|
4644
|
-
|
|
4710
|
+
registerFilteredMetric(telemetry, "tokens", "Get token usage");
|
|
4645
4711
|
registerMetric(telemetry, "user-trends", "Get user trends", "userTrends");
|
|
4646
4712
|
registerMetric(telemetry, "users", "Get unique-user count", "users");
|
|
4647
4713
|
}
|
|
@@ -4842,24 +4908,28 @@ function registerAiGatewayCommand(program) {
|
|
|
4842
4908
|
workspace.command("delete <ref>", { hidden: true }).description("Deprecated compatibility command for archive").option("--force", "Skip confirmation prompt").action((ref, opts) => archiveWorkspace(ref, opts, true));
|
|
4843
4909
|
const telemetry = aigateway.command("telemetry").description("AI Gateway runtime telemetry (data plane)").action(() => telemetry.outputHelp());
|
|
4844
4910
|
registerAiGatewayTelemetryReads(telemetry);
|
|
4845
|
-
const cost =
|
|
4846
|
-
"
|
|
4847
|
-
|
|
4848
|
-
"
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4911
|
+
const cost = addChartFilterOptions(
|
|
4912
|
+
telemetry.command("cost").description(
|
|
4913
|
+
"Total and per-day spend for a workspace (API reports cents; pretty output shows dollars)"
|
|
4914
|
+
).requiredOption("--workspace <ref>", "Workspace slug, UUID, or unique display name").option("--days <n>", "Rolling window in days, counted back from now", "7").option("--output <format>", "Output format: pretty, table, markdown, csv, json, yaml").addHelpText(
|
|
4915
|
+
"after",
|
|
4916
|
+
examples(
|
|
4917
|
+
"airs aigateway telemetry cost --workspace ws-main-a-349e0e",
|
|
4918
|
+
"airs aigateway telemetry cost --workspace ws-main-a-349e0e --days 30 --output json"
|
|
4919
|
+
)
|
|
4852
4920
|
)
|
|
4853
4921
|
).action(async (opts) => {
|
|
4854
4922
|
try {
|
|
4923
|
+
const days = parsePositiveInteger2(opts.days, "--days");
|
|
4924
|
+
const filters = chartFiltersFrom(opts);
|
|
4855
4925
|
const fmt = await resolveOutput(cost, opts);
|
|
4856
4926
|
if (fmt === "pretty") renderAiGatewayHeader();
|
|
4857
|
-
const days = Number.parseInt(opts.days, 10);
|
|
4858
|
-
if (!Number.isFinite(days) || days <= 0) {
|
|
4859
|
-
usageError(`Invalid --days '${opts.days}'. Expected a positive integer`);
|
|
4860
|
-
}
|
|
4861
4927
|
const service = await createService();
|
|
4862
|
-
const report = await service.getTelemetryCost({
|
|
4928
|
+
const report = await service.getTelemetryCost({
|
|
4929
|
+
workspaceSlug: opts.workspace,
|
|
4930
|
+
days,
|
|
4931
|
+
...filters
|
|
4932
|
+
});
|
|
4863
4933
|
renderCostReport(report, fmt);
|
|
4864
4934
|
} catch (err) {
|
|
4865
4935
|
failWithGrantHint(err);
|
|
@@ -5150,17 +5220,23 @@ import { randomUUID } from "crypto";
|
|
|
5150
5220
|
import { readFile as readFile4 } from "fs/promises";
|
|
5151
5221
|
import { init, Scanner } from "@cdot65/prisma-airs-sdk";
|
|
5152
5222
|
var DOCTOR_TIMEOUT_MS = 5e3;
|
|
5153
|
-
var
|
|
5223
|
+
var SUPPORTED_NODE_VERSIONS = "^20.17.0 || ^22.13.0 || >=23.5.0";
|
|
5154
5224
|
function checkNodeVersion(version = process.version) {
|
|
5155
|
-
const
|
|
5156
|
-
|
|
5157
|
-
|
|
5225
|
+
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version);
|
|
5226
|
+
const [major, minor, patch] = match ? match.slice(1).map(Number) : [];
|
|
5227
|
+
const supported = [major, minor, patch].every(Number.isSafeInteger) && (major === 20 && minor >= 17 || major === 22 && minor >= 13 || major === 23 && minor >= 5 || major >= 24);
|
|
5228
|
+
if (supported) {
|
|
5229
|
+
return {
|
|
5230
|
+
name: "Node.js version",
|
|
5231
|
+
status: "pass",
|
|
5232
|
+
detail: `${version} (${SUPPORTED_NODE_VERSIONS} required)`
|
|
5233
|
+
};
|
|
5158
5234
|
}
|
|
5159
5235
|
return {
|
|
5160
5236
|
name: "Node.js version",
|
|
5161
5237
|
status: "fail",
|
|
5162
|
-
detail: `${version}
|
|
5163
|
-
hint:
|
|
5238
|
+
detail: `${version} does not satisfy ${SUPPORTED_NODE_VERSIONS}`,
|
|
5239
|
+
hint: "Use a supported Node runtime: 20.17+, 22.13+, or 24+ (e.g. via nvm or your package manager)"
|
|
5164
5240
|
};
|
|
5165
5241
|
}
|
|
5166
5242
|
async function checkConfigFile(filePath) {
|
|
@@ -6594,9 +6670,9 @@ function registerRedteamCommand(program) {
|
|
|
6594
6670
|
try {
|
|
6595
6671
|
renderRedteamHeader();
|
|
6596
6672
|
const service = await createPromptSetService();
|
|
6597
|
-
const
|
|
6673
|
+
const csv2 = await service.downloadTemplate(uuid);
|
|
6598
6674
|
const outPath = opts.outputFile || `${uuid}-template.csv`;
|
|
6599
|
-
fs2.writeFileSync(outPath,
|
|
6675
|
+
fs2.writeFileSync(outPath, csv2, "utf-8");
|
|
6600
6676
|
ui.success(`Template saved to ${outPath}`);
|
|
6601
6677
|
} catch (err) {
|
|
6602
6678
|
fail(err);
|
|
@@ -8419,6 +8495,30 @@ function register2(dlp) {
|
|
|
8419
8495
|
});
|
|
8420
8496
|
}
|
|
8421
8497
|
|
|
8498
|
+
// src/cli/renderer/dlp-generate.ts
|
|
8499
|
+
function renderGenerateSummary(summary, output) {
|
|
8500
|
+
if (output === "json") {
|
|
8501
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
8502
|
+
return;
|
|
8503
|
+
}
|
|
8504
|
+
ui.header("DLP Test-File Generation");
|
|
8505
|
+
ui.keyValue([
|
|
8506
|
+
["Output", summary.out],
|
|
8507
|
+
["Seed", summary.seed],
|
|
8508
|
+
["Clean", summary.clean],
|
|
8509
|
+
["Dirty", summary.dirty],
|
|
8510
|
+
["Manifest", summary.manifestPath]
|
|
8511
|
+
]);
|
|
8512
|
+
ui.table(
|
|
8513
|
+
[
|
|
8514
|
+
{ key: "format", label: "Format" },
|
|
8515
|
+
{ key: "clean", label: "Clean" },
|
|
8516
|
+
{ key: "dirty", label: "Dirty" }
|
|
8517
|
+
],
|
|
8518
|
+
Object.entries(summary.byFormat).map(([format, counts]) => ({ format, ...counts }))
|
|
8519
|
+
);
|
|
8520
|
+
}
|
|
8521
|
+
|
|
8422
8522
|
// src/cli/commands/dlp/generate.ts
|
|
8423
8523
|
var ALL_FORMATS = ["pdf", "png", "jpeg", "svg", "docx"];
|
|
8424
8524
|
var OPTIONAL_DEPS_HINT = "DLP generate requires optional dependencies. Install them with: pnpm add sharp pdf-lib docx piexifjs";
|
|
@@ -8447,39 +8547,29 @@ function parseTypes(value) {
|
|
|
8447
8547
|
return types;
|
|
8448
8548
|
}
|
|
8449
8549
|
function register3(parent) {
|
|
8450
|
-
parent.command("generate").description(
|
|
8550
|
+
const command = parent.command("generate").description(
|
|
8451
8551
|
"Generate clean + dirty DLP test files (synthetic sensitive data) across PDF/PNG/JPEG/SVG/DOCX"
|
|
8452
|
-
).option("--types <list>", "Comma list: pdf,png,jpeg,svg,docx (or all)", "all").option("--count <n>", "Clean files per type", "1").option("--out <dir>", "Output base directory", "./temp").option("--techniques <list>", "all or comma list of technique ids", "all").option("--seed <n>", "
|
|
8552
|
+
).option("--types <list>", "Comma list: pdf,png,jpeg,svg,docx (or all)", "all").option("--count <n>", "Clean files per type", "1").option("--out <dir>", "Output base directory", "./temp").option("--techniques <list>", "all or comma list of technique ids", "all").option("--seed <n>", "Safe integer seed for reproducible payloads").option("--output <format>", "Summary format: pretty or json", "pretty").action(async (opts) => {
|
|
8453
8553
|
let types;
|
|
8454
8554
|
try {
|
|
8455
8555
|
types = parseTypes(opts.types);
|
|
8456
8556
|
} catch (err) {
|
|
8457
8557
|
usageError(err instanceof Error ? err.message : String(err));
|
|
8458
8558
|
}
|
|
8459
|
-
const count = Number
|
|
8460
|
-
if (!Number.
|
|
8461
|
-
usageError("--count must be a positive integer");
|
|
8559
|
+
const count = Number(opts.count);
|
|
8560
|
+
if (!/^\d+$/.test(opts.count) || !Number.isSafeInteger(count) || count < 1) {
|
|
8561
|
+
usageError("--count must be a positive safe integer");
|
|
8462
8562
|
}
|
|
8463
8563
|
const techniques = opts.techniques === "all" ? "all" : opts.techniques.split(",").map((t) => t.trim());
|
|
8464
|
-
const seed = opts.seed === void 0 ? void 0 : Number
|
|
8564
|
+
const seed = opts.seed === void 0 ? void 0 : Number(opts.seed);
|
|
8565
|
+
if (seed !== void 0 && (!/^-?\d+$/.test(opts.seed) || !Number.isSafeInteger(seed))) {
|
|
8566
|
+
usageError("--seed must be a safe integer");
|
|
8567
|
+
}
|
|
8465
8568
|
try {
|
|
8569
|
+
const output = await resolveOutput(command, opts, { allowed: ["pretty", "json"] });
|
|
8466
8570
|
const generateCorpus = await loadGenerateCorpus();
|
|
8467
8571
|
const summary = await generateCorpus({ types, count, out: opts.out, techniques, seed });
|
|
8468
|
-
|
|
8469
|
-
console.log(JSON.stringify(summary, null, 2));
|
|
8470
|
-
return;
|
|
8471
|
-
}
|
|
8472
|
-
ui.header("DLP Test-File Generation");
|
|
8473
|
-
ui.keyValue([
|
|
8474
|
-
["Output", summary.out],
|
|
8475
|
-
["Seed", summary.seed],
|
|
8476
|
-
["Clean", summary.clean],
|
|
8477
|
-
["Dirty", summary.dirty],
|
|
8478
|
-
["Manifest", summary.manifestPath]
|
|
8479
|
-
]);
|
|
8480
|
-
for (const [fmt, counts] of Object.entries(summary.byFormat)) {
|
|
8481
|
-
ui.dim(`${fmt.padEnd(5)} clean=${counts.clean} dirty=${counts.dirty}`);
|
|
8482
|
-
}
|
|
8572
|
+
renderGenerateSummary(summary, output);
|
|
8483
8573
|
} catch (err) {
|
|
8484
8574
|
fail(err);
|
|
8485
8575
|
}
|
|
@@ -9047,8 +9137,8 @@ function parseCsvLine(line) {
|
|
|
9047
9137
|
}
|
|
9048
9138
|
return fields;
|
|
9049
9139
|
}
|
|
9050
|
-
function loadPrompts(
|
|
9051
|
-
const lines =
|
|
9140
|
+
function loadPrompts(csv2, onWarning) {
|
|
9141
|
+
const lines = csv2.split(/\r?\n/);
|
|
9052
9142
|
const nonEmpty = lines.filter((l) => l.trim() !== "");
|
|
9053
9143
|
if (nonEmpty.length === 0) {
|
|
9054
9144
|
throw new Error("CSV is empty");
|
|
@@ -9245,12 +9335,12 @@ function registerSampleCommand(parent) {
|
|
|
9245
9335
|
});
|
|
9246
9336
|
cmd.action(async (opts) => {
|
|
9247
9337
|
resolveDeprecatedAliases(cmd, opts);
|
|
9248
|
-
const
|
|
9338
|
+
const csv2 = buildSampleCsv();
|
|
9249
9339
|
if (opts.outputFile) {
|
|
9250
|
-
await writeFile4(opts.outputFile,
|
|
9340
|
+
await writeFile4(opts.outputFile, csv2, "utf-8");
|
|
9251
9341
|
ui.success(`Sample CSV written to ${opts.outputFile}`);
|
|
9252
9342
|
} else {
|
|
9253
|
-
process.stdout.write(
|
|
9343
|
+
process.stdout.write(csv2);
|
|
9254
9344
|
}
|
|
9255
9345
|
});
|
|
9256
9346
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdot65/prisma-airs-cli",
|
|
3
3
|
"packageManager": "pnpm@10.6.5",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.3.1",
|
|
5
5
|
"description": "CLI and library for Palo Alto Prisma AIRS — guardrail refinement, AI red teaming, model security scanning, profile audits",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -14,11 +14,13 @@
|
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsup",
|
|
17
|
-
"prepublishOnly": "pnpm run build",
|
|
17
|
+
"prepublishOnly": "pnpm audit:prod && pnpm run build",
|
|
18
18
|
"dev": "tsx src/cli/index.ts",
|
|
19
19
|
"test": "vitest run",
|
|
20
20
|
"test:watch": "vitest",
|
|
21
21
|
"test:coverage": "vitest run --coverage",
|
|
22
|
+
"test:release": "node --test .github/scripts/*.test.mjs",
|
|
23
|
+
"audit:prod": "pnpm audit --prod --audit-level low",
|
|
22
24
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
23
25
|
"test:e2e:aigateway": "vitest run --config vitest.e2e.config.ts tests/e2e/aigateway-cli.e2e.spec.ts",
|
|
24
26
|
"lint": "biome check --config-path config .",
|
|
@@ -49,7 +51,7 @@
|
|
|
49
51
|
"local:unlink": "pnpm uninstall --global @cdot65/prisma-airs-cli"
|
|
50
52
|
},
|
|
51
53
|
"engines": {
|
|
52
|
-
"node": "
|
|
54
|
+
"node": "^20.17.0 || ^22.13.0 || >=23.5.0"
|
|
53
55
|
},
|
|
54
56
|
"repository": {
|
|
55
57
|
"type": "git",
|
|
@@ -57,13 +59,13 @@
|
|
|
57
59
|
},
|
|
58
60
|
"license": "MIT",
|
|
59
61
|
"dependencies": {
|
|
60
|
-
"@cdot65/prisma-airs-sdk": "0.
|
|
62
|
+
"@cdot65/prisma-airs-sdk": "0.24.0",
|
|
61
63
|
"@inquirer/prompts": "^8.3.0",
|
|
62
64
|
"chalk": "^5.6.2",
|
|
63
65
|
"commander": "^14.0.3",
|
|
64
66
|
"dotenv": "^17.3.1",
|
|
65
|
-
"js-yaml": "^4.
|
|
66
|
-
"nanoid": "^5.
|
|
67
|
+
"js-yaml": "^4.3.2",
|
|
68
|
+
"nanoid": "^5.1.16",
|
|
67
69
|
"p-limit": "^6.0.0",
|
|
68
70
|
"zod": "^3.24.0"
|
|
69
71
|
},
|
|
@@ -84,6 +86,6 @@
|
|
|
84
86
|
"docx": "^9.6.1",
|
|
85
87
|
"pdf-lib": "^1.17.1",
|
|
86
88
|
"piexifjs": "^1.0.6",
|
|
87
|
-
"sharp": "^0.
|
|
89
|
+
"sharp": "^0.35.4"
|
|
88
90
|
}
|
|
89
91
|
}
|