@zksecurity/zkao-sdk 0.27.0-next.18 → 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
@@ -28,6 +28,13 @@ Every method is fully typed from the OpenAPI spec. Non-2xx responses throw
28
28
  Cancel a running or queued scan with `zkao.cancelScan(scanId)`; you are charged
29
29
  only for analysis already done and the rest of the reserved budget is released.
30
30
 
31
+ Check `scan.triage` before relying on the results of a completed scan.
32
+ Its `resume` offer provides the allowed credit budgets when triage stopped on budget.
33
+ Resume with `resumeTriage(scanId, { creditBudget }, { idempotencyKey })`.
34
+ Reuse the same key and budget when retrying that request.
35
+ Track the returned run with `getTriageRun` or `waitForTriageRun`.
36
+ Read the scan's `triage` again afterward to check for unfinished findings.
37
+
31
38
  Full docs, the CLI (`@zksecurity/zkao-cli`), and the OpenAPI contract:
32
39
  **https://github.com/zksecurity/zkao-sdk**
33
40
 
package/dist/index.d.ts CHANGED
@@ -280,6 +280,46 @@ interface paths {
280
280
  patch?: never;
281
281
  trace?: never;
282
282
  };
283
+ "/projects/{projectId}/scans/{scanId}/triage/resume": {
284
+ parameters: {
285
+ query?: never;
286
+ header?: never;
287
+ path?: never;
288
+ cookie?: never;
289
+ };
290
+ get?: never;
291
+ put?: never;
292
+ /**
293
+ * Resume triage after a budget stop
294
+ * @description Requires scope: `scans:launch`. The scan must be completed and settled, with unfinished findings and a latest triage run that stopped on budget. Uses the scan's settings and reserves the explicit budget in credits. The token's repository restrictions and spend allowance apply. Reusing the same idempotency key and budget returns the original run, including after it finishes, without reserving or spending again. A different budget with the same key returns 409. A new attempt requires a new key. Poll getTriageRun because the parent scan remains COMPLETED.
295
+ */
296
+ post: operations["resumeTriage"];
297
+ delete?: never;
298
+ options?: never;
299
+ head?: never;
300
+ patch?: never;
301
+ trace?: never;
302
+ };
303
+ "/projects/{projectId}/scans/{scanId}/triage/runs/{runId}": {
304
+ parameters: {
305
+ query?: never;
306
+ header?: never;
307
+ path?: never;
308
+ cookie?: never;
309
+ };
310
+ /**
311
+ * Get one triage run
312
+ * @description Requires scope: `read`. Follows this run independently of the scan status. A COMPLETED run can still leave findings unfinished. Check scan.triage after it ends. Failed attempts awaiting retry remain QUEUED.
313
+ */
314
+ get: operations["getTriageRun"];
315
+ put?: never;
316
+ post?: never;
317
+ delete?: never;
318
+ options?: never;
319
+ head?: never;
320
+ patch?: never;
321
+ trace?: never;
322
+ };
283
323
  "/projects/{projectId}/reports": {
284
324
  parameters: {
285
325
  query?: never;
@@ -850,7 +890,35 @@ interface components {
850
890
  /** @description Weighted completion. Each phase counts for its share of the scan budget, so this does not simply equal phasesCompleted / phasesTotal. */
851
891
  percent: number;
852
892
  };
893
+ TriageResumeBudget: {
894
+ minCredits: number;
895
+ recommendedCredits: number;
896
+ maxCredits: number;
897
+ };
898
+ /** @description Completeness of triage, independent of whether the scan succeeded. */
899
+ ScanTriage: {
900
+ /** @enum {string} */
901
+ status: "pending" | "running" | "complete" | "budget_exhausted" | "blocked";
902
+ untriagedCount: number;
903
+ activeRunId: string | null;
904
+ resume: components["schemas"]["TriageResumeBudget"] | null;
905
+ };
906
+ TriageRun: {
907
+ id: string;
908
+ scanId: string;
909
+ /** @enum {string} */
910
+ status: "QUEUED" | "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED";
911
+ /** @description Number of findings selected when this run started. */
912
+ findingCount: number;
913
+ /** Format: date-time */
914
+ createdAt: string;
915
+ /** Format: date-time */
916
+ completedAt: string | null;
917
+ /** @description Whether this run reached its budget cap. Check scan.triage for remaining work. */
918
+ budgetExhausted: boolean;
919
+ };
853
920
  ScanDetail: components["schemas"]["Scan"] & {
921
+ triage: components["schemas"]["ScanTriage"];
854
922
  branch?: string | null;
855
923
  /** @description Reserved budget for the scan, in credits. */
856
924
  creditBudget?: number | null;
@@ -1868,6 +1936,80 @@ interface operations {
1868
1936
  429: components["responses"]["RateLimited"];
1869
1937
  };
1870
1938
  };
1939
+ resumeTriage: {
1940
+ parameters: {
1941
+ query?: never;
1942
+ header: {
1943
+ /** @description Stable request key. Reuse it with the same budget when retrying. */
1944
+ "Idempotency-Key": string;
1945
+ };
1946
+ path: {
1947
+ projectId: components["parameters"]["ProjectId"];
1948
+ scanId: components["parameters"]["ScanId"];
1949
+ };
1950
+ cookie?: never;
1951
+ };
1952
+ requestBody: {
1953
+ content: {
1954
+ "application/json": {
1955
+ creditBudget: number;
1956
+ };
1957
+ };
1958
+ };
1959
+ responses: {
1960
+ /** @description The new or previously created triage run. */
1961
+ 200: {
1962
+ headers: {
1963
+ [name: string]: unknown;
1964
+ };
1965
+ content: {
1966
+ "application/json": {
1967
+ run: components["schemas"]["TriageRun"];
1968
+ replayed: boolean;
1969
+ };
1970
+ };
1971
+ };
1972
+ 400: components["responses"]["BadRequest"];
1973
+ 401: components["responses"]["Unauthorized"];
1974
+ 402: components["responses"]["InsufficientCredits"];
1975
+ 403: components["responses"]["Forbidden"];
1976
+ 404: components["responses"]["NotFound"];
1977
+ 409: components["responses"]["Conflict"];
1978
+ 429: components["responses"]["RateLimited"];
1979
+ };
1980
+ };
1981
+ getTriageRun: {
1982
+ parameters: {
1983
+ query?: never;
1984
+ header?: never;
1985
+ path: {
1986
+ projectId: components["parameters"]["ProjectId"];
1987
+ scanId: components["parameters"]["ScanId"];
1988
+ runId: string;
1989
+ };
1990
+ cookie?: never;
1991
+ };
1992
+ requestBody?: never;
1993
+ responses: {
1994
+ /** @description OK */
1995
+ 200: {
1996
+ headers: {
1997
+ /** @description Advisory seconds before polling an active run again. */
1998
+ "Retry-After"?: number;
1999
+ [name: string]: unknown;
2000
+ };
2001
+ content: {
2002
+ "application/json": {
2003
+ run: components["schemas"]["TriageRun"];
2004
+ };
2005
+ };
2006
+ };
2007
+ 401: components["responses"]["Unauthorized"];
2008
+ 403: components["responses"]["Forbidden"];
2009
+ 404: components["responses"]["NotFound"];
2010
+ 429: components["responses"]["RateLimited"];
2011
+ };
2012
+ };
1871
2013
  listReports: {
1872
2014
  parameters: {
1873
2015
  query?: {
@@ -2550,6 +2692,11 @@ type ScanPreset = Schemas["ScanPreset"];
2550
2692
  type LaunchScanRequest = Schemas["LaunchScanRequest"];
2551
2693
  type LaunchScanResult = Schemas["LaunchScanResult"];
2552
2694
  type CancelScanResult = Schemas["CancelScanResult"];
2695
+ type ScanTriage = Schemas["ScanTriage"];
2696
+ type TriageRun = Schemas["TriageRun"];
2697
+ type ResumeTriageOperation = paths["/projects/{projectId}/scans/{scanId}/triage/resume"]["post"];
2698
+ type ResumeTriageRequest = ResumeTriageOperation["requestBody"]["content"]["application/json"];
2699
+ type ResumeTriageResult = ResumeTriageOperation["responses"][200]["content"]["application/json"];
2553
2700
  type ChangeNote = Schemas["ChangeNote"];
2554
2701
  type Severity = Schemas["Severity"];
2555
2702
  type ResolutionStatus = Schemas["ResolutionStatus"];
@@ -2677,6 +2824,10 @@ type WaitForScanOptions = {
2677
2824
  /** Called with the latest detail on each non-terminal poll (for progress UI). */
2678
2825
  onPoll?: (scan: ScanDetail) => void;
2679
2826
  };
2827
+ type WaitForTriageRunOptions = Omit<WaitForScanOptions, "onPoll"> & {
2828
+ /** Called with the requested triage run on each non-terminal poll. */
2829
+ onPoll?: (run: TriageRun) => void;
2830
+ };
2680
2831
  /** Thrown for any non-2xx response, carrying the API error envelope. */
2681
2832
  declare class ZkaoApiError extends Error {
2682
2833
  readonly status: number;
@@ -2796,6 +2947,13 @@ declare class ZkaoClient {
2796
2947
  */
2797
2948
  waitForScan(scanId: string, opts?: WaitForScanOptions): Promise<ScanDetail>;
2798
2949
  launchScan(body: LaunchScanRequest): Promise<LaunchScanResult>;
2950
+ /** Resume budget-stopped triage. Reuse the key and budget when retrying. */
2951
+ resumeTriage(scanId: string, body: ResumeTriageRequest, opts: {
2952
+ idempotencyKey: string;
2953
+ }): Promise<ResumeTriageResult>;
2954
+ getTriageRun(scanId: string, runId: string): Promise<TriageRun>;
2955
+ /** Wait for one run. Read scan.triage afterward to check result completeness. */
2956
+ waitForTriageRun(scanId: string, runId: string, opts?: WaitForTriageRunOptions): Promise<TriageRun>;
2799
2957
  /**
2800
2958
  * Cancel a running or queued scan. Signals in-flight jobs to stop, marks the
2801
2959
  * scan CANCELLED, and releases its reserved credits. A scan already in a
@@ -2994,4 +3152,4 @@ declare class ZkaoClient {
2994
3152
  }): Promise<UsageMonthSummary[]>;
2995
3153
  }
2996
3154
 
2997
- export { type Advisory, type AdvisoryAffected, type AdvisoryAffectedInput, type AdvisoryContact, type AdvisoryContactInput, type AdvisoryDetail, type AdvisoryNotice, type AdvisoryStatus, type BillingBalance, type BillingSummary, type BillingUsage, type CancelScanResult, type ChangeNote, type ContactStatus, type ContactTier, type ContinuousTesting, DEFAULT_BASE_URL, type Finding, type FindingDetail, type FindingNote, type LaunchScanRequest, type LaunchScanResult, type ManualAuditRequest, type ManualAuditResult, type Paginated, type PublishArtifactResult, type RemoveContinuousTestingResult, type Report, type ReportStatus, type Repository, type RepositoryGuidance, type ResolutionReason, type ResolutionStatus, type Scan, type ScanDetail, type ScanPreset, type ScanStatus, type SetContinuousTestingRequest, type SetGuidanceResult, type Severity, TERMINAL_SCAN_STATUSES, type TokenInfo, type TriageStatus, type UsageEvent, type UsageEventType, type UsageMonthSummary, type WaitForRepositoryReadyOptions, type WaitForScanOptions, ZkaoApiError, ZkaoClient, type ZkaoClientOptions, type components, getTokenInfo, isTerminalScanStatus, normalizeBaseUrl, type paths, resolveBaseUrlFromEnv };
3155
+ export { type Advisory, type AdvisoryAffected, type AdvisoryAffectedInput, type AdvisoryContact, type AdvisoryContactInput, type AdvisoryDetail, type AdvisoryNotice, type AdvisoryStatus, type BillingBalance, type BillingSummary, type BillingUsage, type CancelScanResult, type ChangeNote, type ContactStatus, type ContactTier, type ContinuousTesting, DEFAULT_BASE_URL, type Finding, type FindingDetail, type FindingNote, type LaunchScanRequest, type LaunchScanResult, type ManualAuditRequest, type ManualAuditResult, type Paginated, type PublishArtifactResult, type RemoveContinuousTestingResult, type Report, type ReportStatus, type Repository, type RepositoryGuidance, type ResolutionReason, type ResolutionStatus, type ResumeTriageRequest, type ResumeTriageResult, type Scan, type ScanDetail, type ScanPreset, type ScanStatus, type ScanTriage, type SetContinuousTestingRequest, type SetGuidanceResult, type Severity, TERMINAL_SCAN_STATUSES, type TokenInfo, type TriageRun, type TriageStatus, type UsageEvent, type UsageEventType, type UsageMonthSummary, type WaitForRepositoryReadyOptions, type WaitForScanOptions, type WaitForTriageRunOptions, ZkaoApiError, ZkaoClient, type ZkaoClientOptions, type components, getTokenInfo, isTerminalScanStatus, normalizeBaseUrl, type paths, resolveBaseUrlFromEnv };
package/dist/index.js CHANGED
@@ -407,6 +407,52 @@ var ZkaoClient = class {
407
407
  });
408
408
  return unwrap(res);
409
409
  }
410
+ /** Resume budget-stopped triage. Reuse the key and budget when retrying. */
411
+ async resumeTriage(scanId, body, opts) {
412
+ const res = await this.http.POST("/projects/{projectId}/scans/{scanId}/triage/resume", {
413
+ params: {
414
+ path: { ...this.path, scanId },
415
+ header: { "Idempotency-Key": opts.idempotencyKey }
416
+ },
417
+ body
418
+ });
419
+ return unwrap(res);
420
+ }
421
+ async getTriageRun(scanId, runId) {
422
+ const res = await this.http.GET("/projects/{projectId}/scans/{scanId}/triage/runs/{runId}", {
423
+ params: { path: { ...this.path, scanId, runId } }
424
+ });
425
+ return unwrap(res).run;
426
+ }
427
+ /** Wait for one run. Read scan.triage afterward to check result completeness. */
428
+ async waitForTriageRun(scanId, runId, opts = {}) {
429
+ const intervalMs = opts.intervalMs ?? 5e3;
430
+ const maxIntervalMs = opts.maxIntervalMs ?? 3e4;
431
+ const timeoutMs = opts.timeoutMs ?? 60 * 60 * 1e3;
432
+ const deadline = Date.now() + timeoutMs;
433
+ for (let attempt = 0; ; attempt++) {
434
+ throwIfAborted(opts.signal);
435
+ const res = await this.http.GET("/projects/{projectId}/scans/{scanId}/triage/runs/{runId}", {
436
+ params: { path: { ...this.path, scanId, runId } },
437
+ signal: opts.signal
438
+ });
439
+ const retryAfterMs = parseRetryAfterMs(res.response.headers.get("retry-after"));
440
+ if (res.response.status !== 429) {
441
+ const run = unwrap(res).run;
442
+ if (run.status === "COMPLETED" || run.status === "FAILED" || run.status === "CANCELLED") {
443
+ return run;
444
+ }
445
+ opts.onPoll?.(run);
446
+ }
447
+ const backoffMs = Math.min(maxIntervalMs, Math.round(intervalMs * 1.5 ** attempt));
448
+ const baseMs = retryAfterMs ?? backoffMs;
449
+ const delayMs = baseMs + Math.round(Math.random() * baseMs * 0.2);
450
+ if (Date.now() + delayMs > deadline) {
451
+ throw new Error(`Timed out waiting for triage run ${runId} to finish after ${timeoutMs}ms`);
452
+ }
453
+ await sleep(delayMs, opts.signal);
454
+ }
455
+ }
410
456
  /**
411
457
  * Cancel a running or queued scan. Signals in-flight jobs to stop, marks the
412
458
  * scan CANCELLED, and releases its reserved credits. A scan already in a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zksecurity/zkao-sdk",
3
- "version": "0.27.0-next.18",
3
+ "version": "0.28.0-next.19",
4
4
  "description": "TypeScript SDK for the zkao Project API",
5
5
  "license": "MIT",
6
6
  "author": "zkSecurity",