@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 +7 -0
- package/dist/index.d.ts +159 -1
- package/dist/index.js +46 -0
- package/package.json +1 -1
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
|