@zksecurity/zkao-cli 0.25.0-next.17 → 0.28.0-next.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,9 @@ zkao repos
16
16
  zkao scans launch --repo <repoId> --budget 500 --preset <ref>
17
17
  zkao scans launch --repo <repoId> --preset "builtin:Diff Scan" --base main --commit <sha>
18
18
  zkao scans wait <scanId> # block until the scan finishes
19
+ zkao scans get <scanId> # check triage completeness
20
+ zkao scans resume-triage <scanId> --budget <credits> --idempotency-key <key>
21
+ zkao scans triage-wait <scanId> <runId> # wait for the returned triage run
19
22
  zkao scans cancel <scanId> # cancel a running or queued scan
20
23
  zkao findings list --scan <scanId>
21
24
  ```
@@ -24,6 +27,12 @@ All output is JSON. `zkao --help` lists every command. Credentials come from
24
27
  `zkao login`, `zkao config set`, or the `ZKAO_API_TOKEN` / `ZKAO_PROJECT_ID`
25
28
  environment variables. Point at another environment with `ZKAO_URL`.
26
29
 
30
+ Check `triage` before treating a completed scan as fully reviewed.
31
+ Resume only within its offered budget range and your authorized spending limit.
32
+ Reuse the same key and budget when retrying a resumption.
33
+ After resumed triage finishes, check the scan's `triage` again.
34
+ Use `--json-errors` for API error status, code, and message as JSON on stderr.
35
+
27
36
  Full docs and the SDK (`@zksecurity/zkao-sdk`): **https://github.com/zksecurity/zkao-sdk**
28
37
 
29
38
  ## License
package/dist/index.js CHANGED
@@ -570,7 +570,7 @@ async function refreshUpdateCache(currentVersion) {
570
570
  // src/index.ts
571
571
  var { version } = createRequire(import.meta.url)("../package.json");
572
572
  var program = new Command();
573
- program.name("zkao").description("Control a zkao project from the command line.").version(version).option("--token <token>", "project API token (or env ZKAO_API_TOKEN)").option("--project <id>", "project id (or env ZKAO_PROJECT_ID)").option("--base-url <url>", "API base URL, used verbatim (env: ZKAO_URL sets the environment)");
573
+ program.name("zkao").description("Control a zkao project from the command line.").version(version).option("--token <token>", "project API token (or env ZKAO_API_TOKEN)").option("--project <id>", "project id (or env ZKAO_PROJECT_ID)").option("--json-errors", "print API error status, code, and message as JSON on stderr").option("--base-url <url>", "API base URL, used verbatim (env: ZKAO_URL sets the environment)");
574
574
  function out(data) {
575
575
  console.log(JSON.stringify(data, null, 2));
576
576
  }
@@ -578,6 +578,20 @@ function fail(message) {
578
578
  console.error(message);
579
579
  process.exit(1);
580
580
  }
581
+ function failApi(error) {
582
+ if (program.opts().jsonErrors) {
583
+ console.error(JSON.stringify({
584
+ error: {
585
+ status: error.status,
586
+ code: error.code,
587
+ message: error.message,
588
+ ...error.minimumCredits === void 0 ? {} : { minimumCredits: error.minimumCredits }
589
+ }
590
+ }));
591
+ process.exit(1);
592
+ }
593
+ fail(`Error ${error.status} (${error.code}): ${error.message}`);
594
+ }
581
595
  function globalConfig() {
582
596
  const g = program.opts();
583
597
  return resolveConfig({ token: g.token, projectId: g.project, baseUrl: g.baseUrl });
@@ -599,7 +613,7 @@ async function run(fn) {
599
613
  out(await fn(client()));
600
614
  } catch (err) {
601
615
  if (err instanceof ZkaoApiError) {
602
- fail(`Error ${err.status} (${err.code}): ${err.message}`);
616
+ failApi(err);
603
617
  }
604
618
  throw err;
605
619
  }
@@ -621,6 +635,13 @@ var toInt = (value) => {
621
635
  }
622
636
  return n;
623
637
  };
638
+ var positiveInteger = (value) => {
639
+ const n = Number(value);
640
+ if (!Number.isSafeInteger(n) || n < 1) {
641
+ throw new InvalidArgumentError("Expected a positive integer");
642
+ }
643
+ return n;
644
+ };
624
645
  program.command("login").description(
625
646
  "Authorize this CLI by approving it in your browser (device flow)"
626
647
  ).option("--no-browser", "print the URL instead of opening a browser").option(
@@ -665,7 +686,7 @@ program.command("whoami").description("Show which project and organization the c
665
686
  out(info);
666
687
  } catch (err) {
667
688
  if (err instanceof ZkaoApiError) {
668
- fail(`Error ${err.status} (${err.code}): ${err.message}`);
689
+ failApi(err);
669
690
  }
670
691
  throw err;
671
692
  }
@@ -922,6 +943,22 @@ scans.command("launch").description("Launch a scan").requiredOption("--repo <id>
922
943
  }
923
944
  );
924
945
  scans.command("cancel <scanId>").description("Cancel a running or queued scan").action((scanId) => run((c) => c.cancelScan(scanId)));
946
+ scans.command("resume-triage <scanId>").description("Resume budget-stopped triage with an explicitly authorized credit budget").requiredOption("--budget <credits>", "budget from the scan's triage.resume offer", positiveInteger).requiredOption("--idempotency-key <key>", "stable key to reuse with the same budget when retrying").action(
947
+ (scanId, opts) => run((c) => c.resumeTriage(scanId, { creditBudget: opts.budget }, { idempotencyKey: opts.idempotencyKey }))
948
+ );
949
+ scans.command("triage-get <scanId> <runId>").description("Get the status of one resumed triage run").action((scanId, runId) => run((c) => c.getTriageRun(scanId, runId)));
950
+ scans.command("triage-wait <scanId> <runId>").description("Wait for one triage run; then check the scan's triage completeness").option("--timeout <seconds>", "give up after this long", positiveInteger).action((scanId, runId, opts) => {
951
+ const controller = new AbortController();
952
+ const onSigint = () => controller.abort(new Error("Interrupted"));
953
+ process.once("SIGINT", onSigint);
954
+ return run(
955
+ (c) => c.waitForTriageRun(scanId, runId, {
956
+ timeoutMs: opts.timeout === void 0 ? void 0 : opts.timeout * 1e3,
957
+ signal: controller.signal,
958
+ onPoll: (current) => console.error(` triage ${current.id}: ${current.status}`)
959
+ }).finally(() => process.removeListener("SIGINT", onSigint))
960
+ );
961
+ });
925
962
  scans.command("publish <scanId>").description("Publish a completed scan as a public artifact").option("--password", "generate an access password").action(
926
963
  (scanId, opts) => run((c) => c.publishScan(scanId, { withPassword: opts.password }))
927
964
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zksecurity/zkao-cli",
3
- "version": "0.25.0-next.17",
3
+ "version": "0.28.0-next.19",
4
4
  "description": "Command-line interface for the zkao Project API",
5
5
  "license": "MIT",
6
6
  "author": "zkSecurity",
@@ -39,7 +39,7 @@
39
39
  "prepublishOnly": "node -e \"if (!(process.env.npm_config_user_agent || '').includes('bun/')) { console.error('Publish with bun publish: npm ships the literal workspace:* dependency and breaks installs.'); process.exit(1); }\""
40
40
  },
41
41
  "dependencies": {
42
- "@zksecurity/zkao-sdk": "0.25.0-next.17",
42
+ "@zksecurity/zkao-sdk": "0.28.0-next.19",
43
43
  "commander": "^12.1.0"
44
44
  },
45
45
  "devDependencies": {