@zksecurity/zkao-sdk 0.1.0 → 0.5.0
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/dist/index.d.ts +503 -6
- package/dist/index.js +147 -2
- package/package.json +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -73,6 +73,50 @@ interface paths {
|
|
|
73
73
|
patch?: never;
|
|
74
74
|
trace?: never;
|
|
75
75
|
};
|
|
76
|
+
"/projects/{projectId}/repositories/{repositoryId}/audit-areas": {
|
|
77
|
+
parameters: {
|
|
78
|
+
query?: never;
|
|
79
|
+
header?: never;
|
|
80
|
+
path?: never;
|
|
81
|
+
cookie?: never;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* List a repository's audit areas
|
|
85
|
+
* @description Requires scope: `read`. Audit areas are the named subsystems a scan can be scoped to (`auditAreaKeys` on launch). Each scan that maps the repository keeps the list current; sizes come from one branch's map, so an area that map no longer names is returned without one.
|
|
86
|
+
*/
|
|
87
|
+
get: operations["listAuditAreas"];
|
|
88
|
+
put?: never;
|
|
89
|
+
/**
|
|
90
|
+
* Add a custom audit area
|
|
91
|
+
* @description Requires scope: `guidance:write`. An area is a name and a description, never a file list: a scan resolves it against the code at the commit it runs on. The `key` is derived from the name and disambiguated on collision.
|
|
92
|
+
*/
|
|
93
|
+
post: operations["createAuditArea"];
|
|
94
|
+
delete?: never;
|
|
95
|
+
options?: never;
|
|
96
|
+
head?: never;
|
|
97
|
+
patch?: never;
|
|
98
|
+
trace?: never;
|
|
99
|
+
};
|
|
100
|
+
"/projects/{projectId}/repositories/{repositoryId}/audit-areas/{areaKey}": {
|
|
101
|
+
parameters: {
|
|
102
|
+
query?: never;
|
|
103
|
+
header?: never;
|
|
104
|
+
path?: never;
|
|
105
|
+
cookie?: never;
|
|
106
|
+
};
|
|
107
|
+
get?: never;
|
|
108
|
+
put?: never;
|
|
109
|
+
post?: never;
|
|
110
|
+
/**
|
|
111
|
+
* Delete a custom audit area
|
|
112
|
+
* @description Requires scope: `guidance:write`. Only an area with `source: custom` can be deleted; a discovered one is the map's own account of the repository and is refused with `409`. Scans that already ran keep the scope they ran with.
|
|
113
|
+
*/
|
|
114
|
+
delete: operations["deleteAuditArea"];
|
|
115
|
+
options?: never;
|
|
116
|
+
head?: never;
|
|
117
|
+
patch?: never;
|
|
118
|
+
trace?: never;
|
|
119
|
+
};
|
|
76
120
|
"/projects/{projectId}/scans": {
|
|
77
121
|
parameters: {
|
|
78
122
|
query?: never;
|
|
@@ -91,7 +135,12 @@ interface paths {
|
|
|
91
135
|
* @description Requires scope: `scans:launch`. Reserves `creditBudget` credits from the
|
|
92
136
|
* project balance. The repo must be in the token's allowlist (when set) and
|
|
93
137
|
* ACTIVE. Discover valid `presetRef` / `optInFlowIds` via the discovery
|
|
94
|
-
* endpoints. Per-token spend limits and the project
|
|
138
|
+
* endpoints. Per-token spend limits are enforced, and the project must have
|
|
139
|
+
* enough prepaid credits to cover the budget (otherwise `402`).
|
|
140
|
+
*
|
|
141
|
+
* A repository added moments ago may still be analyzing, in which case
|
|
142
|
+
* this returns `409 repository_initializing`. Wait for its `readiness` to
|
|
143
|
+
* be `ready` in `GET /repositories` and launch again.
|
|
95
144
|
*/
|
|
96
145
|
post: operations["launchScan"];
|
|
97
146
|
delete?: never;
|
|
@@ -329,7 +378,7 @@ interface paths {
|
|
|
329
378
|
};
|
|
330
379
|
/**
|
|
331
380
|
* List opt-in flows available at launch
|
|
332
|
-
* @description Requires scope: `read`. Pass the chosen ids as `optInFlowIds` when launching.
|
|
381
|
+
* @description Requires scope: `read`. Pass the chosen ids as `optInFlowIds` when launching. A flow marked `rotating` may run without being asked for.
|
|
333
382
|
*/
|
|
334
383
|
get: operations["listOptionalFlows"];
|
|
335
384
|
put?: never;
|
|
@@ -340,13 +389,111 @@ interface paths {
|
|
|
340
389
|
patch?: never;
|
|
341
390
|
trace?: never;
|
|
342
391
|
};
|
|
392
|
+
"/projects/{projectId}/billing/balance": {
|
|
393
|
+
parameters: {
|
|
394
|
+
query?: never;
|
|
395
|
+
header?: never;
|
|
396
|
+
path?: never;
|
|
397
|
+
cookie?: never;
|
|
398
|
+
};
|
|
399
|
+
/**
|
|
400
|
+
* Current prepaid credit balance
|
|
401
|
+
* @description Requires scope: `read`. All amounts are in credits.
|
|
402
|
+
*/
|
|
403
|
+
get: operations["getBillingBalance"];
|
|
404
|
+
put?: never;
|
|
405
|
+
post?: never;
|
|
406
|
+
delete?: never;
|
|
407
|
+
options?: never;
|
|
408
|
+
head?: never;
|
|
409
|
+
patch?: never;
|
|
410
|
+
trace?: never;
|
|
411
|
+
};
|
|
412
|
+
"/projects/{projectId}/billing/usage": {
|
|
413
|
+
parameters: {
|
|
414
|
+
query?: never;
|
|
415
|
+
header?: never;
|
|
416
|
+
path?: never;
|
|
417
|
+
cookie?: never;
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* Credit usage events
|
|
421
|
+
* @description Requires scope: `read`. Signed credit delta per ledger event. Defaults to the last 30 days; newest first; max 1000 rows.
|
|
422
|
+
*/
|
|
423
|
+
get: operations["getBillingUsage"];
|
|
424
|
+
put?: never;
|
|
425
|
+
post?: never;
|
|
426
|
+
delete?: never;
|
|
427
|
+
options?: never;
|
|
428
|
+
head?: never;
|
|
429
|
+
patch?: never;
|
|
430
|
+
trace?: never;
|
|
431
|
+
};
|
|
432
|
+
"/projects/{projectId}/billing/summary": {
|
|
433
|
+
parameters: {
|
|
434
|
+
query?: never;
|
|
435
|
+
header?: never;
|
|
436
|
+
path?: never;
|
|
437
|
+
cookie?: never;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* Monthly spend and purchase summary
|
|
441
|
+
* @description Requires scope: `read`. Per-month net scan spend and net purchases, in credits, newest first.
|
|
442
|
+
*/
|
|
443
|
+
get: operations["getBillingSummary"];
|
|
444
|
+
put?: never;
|
|
445
|
+
post?: never;
|
|
446
|
+
delete?: never;
|
|
447
|
+
options?: never;
|
|
448
|
+
head?: never;
|
|
449
|
+
patch?: never;
|
|
450
|
+
trace?: never;
|
|
451
|
+
};
|
|
343
452
|
}
|
|
344
453
|
interface components {
|
|
345
454
|
schemas: {
|
|
455
|
+
BillingBalance: {
|
|
456
|
+
/** @description Total prepaid credit balance. */
|
|
457
|
+
balanceCredits: number;
|
|
458
|
+
/** @description Balance minus credits reserved by in-flight scans. */
|
|
459
|
+
availableCredits: number;
|
|
460
|
+
/** @description Credits held by queued/running scans. */
|
|
461
|
+
reservedCredits: number;
|
|
462
|
+
};
|
|
463
|
+
/** @enum {string} */
|
|
464
|
+
UsageEventType: "SCAN_DEDUCTION" | "SCAN_REFUND" | "PURCHASE" | "STRIPE_REFUND" | "ADMIN_ADJUSTMENT";
|
|
465
|
+
UsageEvent: {
|
|
466
|
+
id: string;
|
|
467
|
+
/** Format: date-time */
|
|
468
|
+
at: string;
|
|
469
|
+
type: components["schemas"]["UsageEventType"];
|
|
470
|
+
/** @description Signed credit delta: negative = spent/clawed back, positive = added/refunded. */
|
|
471
|
+
credits: number;
|
|
472
|
+
scanId: string | null;
|
|
473
|
+
description: string;
|
|
474
|
+
};
|
|
475
|
+
BillingUsage: {
|
|
476
|
+
/** Format: date-time */
|
|
477
|
+
from: string;
|
|
478
|
+
/** Format: date-time */
|
|
479
|
+
to: string;
|
|
480
|
+
events: components["schemas"]["UsageEvent"][];
|
|
481
|
+
};
|
|
482
|
+
UsageMonthSummary: {
|
|
483
|
+
/** @description YYYY-MM (UTC). */
|
|
484
|
+
month: string;
|
|
485
|
+
/** @description Net scan spend (deductions less refunds), in credits. */
|
|
486
|
+
spentCredits: number;
|
|
487
|
+
/** @description Net purchases (purchases less clawbacks), in credits. */
|
|
488
|
+
purchasedCredits: number;
|
|
489
|
+
};
|
|
490
|
+
BillingSummary: {
|
|
491
|
+
months: components["schemas"]["UsageMonthSummary"][];
|
|
492
|
+
};
|
|
346
493
|
Error: {
|
|
347
494
|
error: {
|
|
348
495
|
/** @enum {string} */
|
|
349
|
-
code: "unauthorized" | "forbidden" | "not_found" | "bad_request" | "conflict" | "
|
|
496
|
+
code: "unauthorized" | "forbidden" | "not_found" | "bad_request" | "conflict" | "insufficient_credits" | "repository_initializing" | "rate_limited" | "internal";
|
|
350
497
|
message: string;
|
|
351
498
|
};
|
|
352
499
|
};
|
|
@@ -366,6 +513,11 @@ interface components {
|
|
|
366
513
|
defaultBranch?: string | null;
|
|
367
514
|
/** @description ACTIVE | MARKED_FOR_DELETION */
|
|
368
515
|
status: string;
|
|
516
|
+
/**
|
|
517
|
+
* @description Whether a scan can start on this repository. A newly added repository is `analyzing` until a one-time pass over it finishes; launching a scan meanwhile fails with `repository_initializing`. Poll this endpoint rather than retrying the launch blind.
|
|
518
|
+
* @enum {string}
|
|
519
|
+
*/
|
|
520
|
+
readiness: "ready" | "analyzing";
|
|
369
521
|
};
|
|
370
522
|
Scan: {
|
|
371
523
|
id: string;
|
|
@@ -380,6 +532,17 @@ interface components {
|
|
|
380
532
|
startedAt?: string | null;
|
|
381
533
|
/** Format: date-time */
|
|
382
534
|
completedAt?: string | null;
|
|
535
|
+
/** @description Phase progress while the scan is in flight. Null once the scan reaches a terminal state, and null before it has been dispatched (no phases exist yet). */
|
|
536
|
+
progress?: components["schemas"]["ScanProgress"] | null;
|
|
537
|
+
};
|
|
538
|
+
/** @description How far a running scan has got through its phases. Deliberately not a time estimate: a phase's duration moves with the guidance it was given, the repository, and the model that ran it. */
|
|
539
|
+
ScanProgress: {
|
|
540
|
+
/** @description Phases that reached a terminal state (completed, failed, or skipped). */
|
|
541
|
+
phasesCompleted: number;
|
|
542
|
+
/** @description Phases this scan will run, fixed when it was dispatched. */
|
|
543
|
+
phasesTotal: number;
|
|
544
|
+
/** @description Weighted completion. Each phase counts for its share of the scan budget, so this does not simply equal phasesCompleted / phasesTotal. */
|
|
545
|
+
percent: number;
|
|
383
546
|
};
|
|
384
547
|
ScanDetail: components["schemas"]["Scan"] & {
|
|
385
548
|
branch?: string | null;
|
|
@@ -457,6 +620,8 @@ interface components {
|
|
|
457
620
|
flowId: string;
|
|
458
621
|
title: string;
|
|
459
622
|
description: string;
|
|
623
|
+
/** @description True when this flow belongs to a group the preset rotates through. Some of the group runs on every scan without being asked for, and which members depends on the repository. Naming it in `optInFlowIds` adds it whether or not the rotation picked it, and raises the scan's minimum budget. */
|
|
624
|
+
rotating: boolean;
|
|
460
625
|
};
|
|
461
626
|
LaunchScanRequest: {
|
|
462
627
|
repositoryId: string;
|
|
@@ -469,8 +634,10 @@ interface components {
|
|
|
469
634
|
/** @description Pin a specific commit SHA (7-40 hex chars). */
|
|
470
635
|
commitHash?: string | null;
|
|
471
636
|
commitMessage?: string | null;
|
|
472
|
-
/** @description Optional-flow ids from /optional-flows. */
|
|
637
|
+
/** @description Optional-flow ids from /optional-flows, added to the scan on top of whatever a rotating group already contributes. */
|
|
473
638
|
optInFlowIds?: string[];
|
|
639
|
+
/** @description Area keys from /audit-areas to scope this scan to. Omit or send an empty array to scan the whole repository. A key the repository's current map no longer names fails the launch rather than being dropped, so a scan budgeted for one subsystem never silently runs against everything. */
|
|
640
|
+
auditAreaKeys?: string[];
|
|
474
641
|
/** @description Guidance for this scan only, replacing the repository's configured guidance layer (it is still layered over any committed zkao.md). Omit the field to inherit the repository's guidance; send null to scan with no guidance layer. */
|
|
475
642
|
guidance?: string | null;
|
|
476
643
|
};
|
|
@@ -501,6 +668,44 @@ interface components {
|
|
|
501
668
|
/** @description True when the content already matched (no revision recorded). */
|
|
502
669
|
unchanged: boolean;
|
|
503
670
|
};
|
|
671
|
+
AuditArea: {
|
|
672
|
+
/** @description Stable slug, unique per repository. Pass it in `auditAreaKeys` when launching a scan. */
|
|
673
|
+
key: string;
|
|
674
|
+
name: string;
|
|
675
|
+
description: string | null;
|
|
676
|
+
/**
|
|
677
|
+
* @description `discovered` was named by a scan's map of the repository; `custom` was added through this API or the app.
|
|
678
|
+
* @enum {string}
|
|
679
|
+
*/
|
|
680
|
+
source: "discovered" | "custom";
|
|
681
|
+
/** @description Whether the branch's latest map still names this area. */
|
|
682
|
+
inLatestMap: boolean;
|
|
683
|
+
/** @description Files this area covers at that map. Null when the map does not name it. */
|
|
684
|
+
files: number | null;
|
|
685
|
+
/** @description Lines this area covers at that map. Null when the map does not name it. */
|
|
686
|
+
lines: number | null;
|
|
687
|
+
};
|
|
688
|
+
AuditAreaList: {
|
|
689
|
+
repositoryId: string;
|
|
690
|
+
/** @description Branch the sizes were read from. */
|
|
691
|
+
branch: string | null;
|
|
692
|
+
/** @description Whether that branch has a stored map at all. */
|
|
693
|
+
mapped: boolean;
|
|
694
|
+
totalFiles: number | null;
|
|
695
|
+
totalLines: number | null;
|
|
696
|
+
/** @description The map's own audit order first, then the areas it no longer names. */
|
|
697
|
+
areas: components["schemas"]["AuditArea"][];
|
|
698
|
+
};
|
|
699
|
+
CreateAuditAreaRequest: {
|
|
700
|
+
name: string;
|
|
701
|
+
/** @description What this part of the code does. */
|
|
702
|
+
description?: string | null;
|
|
703
|
+
};
|
|
704
|
+
DeleteAuditAreaResult: {
|
|
705
|
+
repositoryId: string;
|
|
706
|
+
key: string;
|
|
707
|
+
deleted: boolean;
|
|
708
|
+
};
|
|
504
709
|
CancelScanResult: {
|
|
505
710
|
scanId: string;
|
|
506
711
|
/** @description Terminal status after cancellation (always CANCELLED). */
|
|
@@ -532,6 +737,14 @@ interface components {
|
|
|
532
737
|
findingId: string;
|
|
533
738
|
resolutionStatus: components["schemas"]["ResolutionStatus"];
|
|
534
739
|
};
|
|
740
|
+
/**
|
|
741
|
+
* @description Short code for why a finding is being closed, chosen from the set offered for the `resolutionStatus` it is sent with; a code belonging to a different status is rejected with 400. Ignored for the open statuses (`NOT_STARTED`, `IN_PROGRESS`) and when `note` is also given. It is not stored as a field: it is recorded as a comment on the finding stating what was chosen, which is returned by the notes endpoints.
|
|
742
|
+
*
|
|
743
|
+
* Codes per status. `RESOLVED`: fixed_in_code, fixed_upstream, code_removed. `MITIGATED`: compensating_control, limited_exposure, monitored. `FALSE_POSITIVE`: not_reachable, guarded_elsewhere, intended_behavior, misread_code, bad_assumption. `WONT_FIX`: risk_accepted, out_of_scope, not_worth_fixing, code_being_removed. `DUPLICATE`: duplicate_of_finding, same_root_cause.
|
|
744
|
+
* @example not_reachable
|
|
745
|
+
* @enum {string}
|
|
746
|
+
*/
|
|
747
|
+
ResolutionReason: "fixed_in_code" | "fixed_upstream" | "code_removed" | "compensating_control" | "limited_exposure" | "monitored" | "not_reachable" | "guarded_elsewhere" | "intended_behavior" | "misread_code" | "bad_assumption" | "risk_accepted" | "out_of_scope" | "not_worth_fixing" | "code_being_removed" | "duplicate_of_finding" | "same_root_cause";
|
|
535
748
|
PublishFindingRequest: {
|
|
536
749
|
/** @description A note id on the finding to pin as the published note. */
|
|
537
750
|
noteId?: string;
|
|
@@ -569,6 +782,24 @@ interface components {
|
|
|
569
782
|
"application/json": components["schemas"]["Error"];
|
|
570
783
|
};
|
|
571
784
|
};
|
|
785
|
+
/** @description The project does not have enough prepaid credits to cover the scan budget. Top up credits and retry. (code `insufficient_credits`) */
|
|
786
|
+
InsufficientCredits: {
|
|
787
|
+
headers: {
|
|
788
|
+
[name: string]: unknown;
|
|
789
|
+
};
|
|
790
|
+
content: {
|
|
791
|
+
"application/json": components["schemas"]["Error"];
|
|
792
|
+
};
|
|
793
|
+
};
|
|
794
|
+
/** @description The repository is still being analyzed and cannot be scanned yet. The same request succeeds once `GET /repositories` reports its `readiness` as `ready`. (code `repository_initializing`) */
|
|
795
|
+
RepositoryInitializing: {
|
|
796
|
+
headers: {
|
|
797
|
+
[name: string]: unknown;
|
|
798
|
+
};
|
|
799
|
+
content: {
|
|
800
|
+
"application/json": components["schemas"]["Error"];
|
|
801
|
+
};
|
|
802
|
+
};
|
|
572
803
|
/** @description The token lacks the required scope */
|
|
573
804
|
Forbidden: {
|
|
574
805
|
headers: {
|
|
@@ -706,6 +937,97 @@ interface operations {
|
|
|
706
937
|
409: components["responses"]["Conflict"];
|
|
707
938
|
};
|
|
708
939
|
};
|
|
940
|
+
listAuditAreas: {
|
|
941
|
+
parameters: {
|
|
942
|
+
query?: {
|
|
943
|
+
/** @description Branch whose map the sizes come from. Defaults to the repository's default branch. */
|
|
944
|
+
branch?: string;
|
|
945
|
+
};
|
|
946
|
+
header?: never;
|
|
947
|
+
path: {
|
|
948
|
+
projectId: components["parameters"]["ProjectId"];
|
|
949
|
+
repositoryId: components["parameters"]["RepositoryId"];
|
|
950
|
+
};
|
|
951
|
+
cookie?: never;
|
|
952
|
+
};
|
|
953
|
+
requestBody?: never;
|
|
954
|
+
responses: {
|
|
955
|
+
/** @description OK */
|
|
956
|
+
200: {
|
|
957
|
+
headers: {
|
|
958
|
+
[name: string]: unknown;
|
|
959
|
+
};
|
|
960
|
+
content: {
|
|
961
|
+
"application/json": components["schemas"]["AuditAreaList"];
|
|
962
|
+
};
|
|
963
|
+
};
|
|
964
|
+
401: components["responses"]["Unauthorized"];
|
|
965
|
+
403: components["responses"]["Forbidden"];
|
|
966
|
+
404: components["responses"]["NotFound"];
|
|
967
|
+
};
|
|
968
|
+
};
|
|
969
|
+
createAuditArea: {
|
|
970
|
+
parameters: {
|
|
971
|
+
query?: never;
|
|
972
|
+
header?: never;
|
|
973
|
+
path: {
|
|
974
|
+
projectId: components["parameters"]["ProjectId"];
|
|
975
|
+
repositoryId: components["parameters"]["RepositoryId"];
|
|
976
|
+
};
|
|
977
|
+
cookie?: never;
|
|
978
|
+
};
|
|
979
|
+
requestBody: {
|
|
980
|
+
content: {
|
|
981
|
+
"application/json": components["schemas"]["CreateAuditAreaRequest"];
|
|
982
|
+
};
|
|
983
|
+
};
|
|
984
|
+
responses: {
|
|
985
|
+
/** @description Created */
|
|
986
|
+
201: {
|
|
987
|
+
headers: {
|
|
988
|
+
[name: string]: unknown;
|
|
989
|
+
};
|
|
990
|
+
content: {
|
|
991
|
+
"application/json": {
|
|
992
|
+
area: components["schemas"]["AuditArea"];
|
|
993
|
+
};
|
|
994
|
+
};
|
|
995
|
+
};
|
|
996
|
+
400: components["responses"]["BadRequest"];
|
|
997
|
+
401: components["responses"]["Unauthorized"];
|
|
998
|
+
403: components["responses"]["Forbidden"];
|
|
999
|
+
404: components["responses"]["NotFound"];
|
|
1000
|
+
409: components["responses"]["Conflict"];
|
|
1001
|
+
};
|
|
1002
|
+
};
|
|
1003
|
+
deleteAuditArea: {
|
|
1004
|
+
parameters: {
|
|
1005
|
+
query?: never;
|
|
1006
|
+
header?: never;
|
|
1007
|
+
path: {
|
|
1008
|
+
projectId: components["parameters"]["ProjectId"];
|
|
1009
|
+
repositoryId: components["parameters"]["RepositoryId"];
|
|
1010
|
+
areaKey: string;
|
|
1011
|
+
};
|
|
1012
|
+
cookie?: never;
|
|
1013
|
+
};
|
|
1014
|
+
requestBody?: never;
|
|
1015
|
+
responses: {
|
|
1016
|
+
/** @description OK */
|
|
1017
|
+
200: {
|
|
1018
|
+
headers: {
|
|
1019
|
+
[name: string]: unknown;
|
|
1020
|
+
};
|
|
1021
|
+
content: {
|
|
1022
|
+
"application/json": components["schemas"]["DeleteAuditAreaResult"];
|
|
1023
|
+
};
|
|
1024
|
+
};
|
|
1025
|
+
401: components["responses"]["Unauthorized"];
|
|
1026
|
+
403: components["responses"]["Forbidden"];
|
|
1027
|
+
404: components["responses"]["NotFound"];
|
|
1028
|
+
409: components["responses"]["Conflict"];
|
|
1029
|
+
};
|
|
1030
|
+
};
|
|
709
1031
|
listScans: {
|
|
710
1032
|
parameters: {
|
|
711
1033
|
query?: {
|
|
@@ -760,8 +1082,10 @@ interface operations {
|
|
|
760
1082
|
};
|
|
761
1083
|
400: components["responses"]["BadRequest"];
|
|
762
1084
|
401: components["responses"]["Unauthorized"];
|
|
1085
|
+
402: components["responses"]["InsufficientCredits"];
|
|
763
1086
|
403: components["responses"]["Forbidden"];
|
|
764
1087
|
404: components["responses"]["NotFound"];
|
|
1088
|
+
409: components["responses"]["RepositoryInitializing"];
|
|
765
1089
|
429: components["responses"]["RateLimited"];
|
|
766
1090
|
};
|
|
767
1091
|
};
|
|
@@ -1000,6 +1324,7 @@ interface operations {
|
|
|
1000
1324
|
"application/json": {
|
|
1001
1325
|
resolutionStatus: components["schemas"]["ResolutionStatus"];
|
|
1002
1326
|
note?: components["schemas"]["ChangeNote"];
|
|
1327
|
+
reason?: components["schemas"]["ResolutionReason"];
|
|
1003
1328
|
};
|
|
1004
1329
|
};
|
|
1005
1330
|
};
|
|
@@ -1135,6 +1460,88 @@ interface operations {
|
|
|
1135
1460
|
404: components["responses"]["NotFound"];
|
|
1136
1461
|
};
|
|
1137
1462
|
};
|
|
1463
|
+
getBillingBalance: {
|
|
1464
|
+
parameters: {
|
|
1465
|
+
query?: never;
|
|
1466
|
+
header?: never;
|
|
1467
|
+
path: {
|
|
1468
|
+
projectId: components["parameters"]["ProjectId"];
|
|
1469
|
+
};
|
|
1470
|
+
cookie?: never;
|
|
1471
|
+
};
|
|
1472
|
+
requestBody?: never;
|
|
1473
|
+
responses: {
|
|
1474
|
+
/** @description OK */
|
|
1475
|
+
200: {
|
|
1476
|
+
headers: {
|
|
1477
|
+
[name: string]: unknown;
|
|
1478
|
+
};
|
|
1479
|
+
content: {
|
|
1480
|
+
"application/json": components["schemas"]["BillingBalance"];
|
|
1481
|
+
};
|
|
1482
|
+
};
|
|
1483
|
+
401: components["responses"]["Unauthorized"];
|
|
1484
|
+
403: components["responses"]["Forbidden"];
|
|
1485
|
+
404: components["responses"]["NotFound"];
|
|
1486
|
+
};
|
|
1487
|
+
};
|
|
1488
|
+
getBillingUsage: {
|
|
1489
|
+
parameters: {
|
|
1490
|
+
query?: {
|
|
1491
|
+
from?: string;
|
|
1492
|
+
to?: string;
|
|
1493
|
+
limit?: number;
|
|
1494
|
+
};
|
|
1495
|
+
header?: never;
|
|
1496
|
+
path: {
|
|
1497
|
+
projectId: components["parameters"]["ProjectId"];
|
|
1498
|
+
};
|
|
1499
|
+
cookie?: never;
|
|
1500
|
+
};
|
|
1501
|
+
requestBody?: never;
|
|
1502
|
+
responses: {
|
|
1503
|
+
/** @description OK */
|
|
1504
|
+
200: {
|
|
1505
|
+
headers: {
|
|
1506
|
+
[name: string]: unknown;
|
|
1507
|
+
};
|
|
1508
|
+
content: {
|
|
1509
|
+
"application/json": components["schemas"]["BillingUsage"];
|
|
1510
|
+
};
|
|
1511
|
+
};
|
|
1512
|
+
400: components["responses"]["BadRequest"];
|
|
1513
|
+
401: components["responses"]["Unauthorized"];
|
|
1514
|
+
403: components["responses"]["Forbidden"];
|
|
1515
|
+
404: components["responses"]["NotFound"];
|
|
1516
|
+
};
|
|
1517
|
+
};
|
|
1518
|
+
getBillingSummary: {
|
|
1519
|
+
parameters: {
|
|
1520
|
+
query?: {
|
|
1521
|
+
months?: number;
|
|
1522
|
+
};
|
|
1523
|
+
header?: never;
|
|
1524
|
+
path: {
|
|
1525
|
+
projectId: components["parameters"]["ProjectId"];
|
|
1526
|
+
};
|
|
1527
|
+
cookie?: never;
|
|
1528
|
+
};
|
|
1529
|
+
requestBody?: never;
|
|
1530
|
+
responses: {
|
|
1531
|
+
/** @description OK */
|
|
1532
|
+
200: {
|
|
1533
|
+
headers: {
|
|
1534
|
+
[name: string]: unknown;
|
|
1535
|
+
};
|
|
1536
|
+
content: {
|
|
1537
|
+
"application/json": components["schemas"]["BillingSummary"];
|
|
1538
|
+
};
|
|
1539
|
+
};
|
|
1540
|
+
401: components["responses"]["Unauthorized"];
|
|
1541
|
+
403: components["responses"]["Forbidden"];
|
|
1542
|
+
404: components["responses"]["NotFound"];
|
|
1543
|
+
};
|
|
1544
|
+
};
|
|
1138
1545
|
}
|
|
1139
1546
|
|
|
1140
1547
|
type Schemas = components["schemas"];
|
|
@@ -1152,11 +1559,21 @@ type CancelScanResult = Schemas["CancelScanResult"];
|
|
|
1152
1559
|
type ChangeNote = Schemas["ChangeNote"];
|
|
1153
1560
|
type Severity = Schemas["Severity"];
|
|
1154
1561
|
type ResolutionStatus = Schemas["ResolutionStatus"];
|
|
1562
|
+
type ResolutionReason = Schemas["ResolutionReason"];
|
|
1155
1563
|
type TriageStatus = Schemas["TriageStatus"];
|
|
1156
1564
|
type ScanStatus = Schemas["ScanStatus"];
|
|
1157
1565
|
type PublishArtifactResult = Schemas["PublishArtifactResult"];
|
|
1158
1566
|
type RepositoryGuidance = Schemas["RepositoryGuidance"];
|
|
1567
|
+
type AuditArea = Schemas["AuditArea"];
|
|
1568
|
+
type AuditAreaList = Schemas["AuditAreaList"];
|
|
1569
|
+
type DeleteAuditAreaResult = Schemas["DeleteAuditAreaResult"];
|
|
1159
1570
|
type SetGuidanceResult = Schemas["SetGuidanceResult"];
|
|
1571
|
+
type BillingBalance = Schemas["BillingBalance"];
|
|
1572
|
+
type BillingUsage = Schemas["BillingUsage"];
|
|
1573
|
+
type UsageEvent = Schemas["UsageEvent"];
|
|
1574
|
+
type UsageEventType = Schemas["UsageEventType"];
|
|
1575
|
+
type BillingSummary = Schemas["BillingSummary"];
|
|
1576
|
+
type UsageMonthSummary = Schemas["UsageMonthSummary"];
|
|
1160
1577
|
type Paginated<T> = {
|
|
1161
1578
|
items: T[];
|
|
1162
1579
|
page: number;
|
|
@@ -1180,6 +1597,16 @@ type ZkaoClientOptions = {
|
|
|
1180
1597
|
/** Terminal scan statuses: polling can stop once a scan reaches one of these. */
|
|
1181
1598
|
declare const TERMINAL_SCAN_STATUSES: readonly ScanStatus[];
|
|
1182
1599
|
declare function isTerminalScanStatus(status: ScanStatus): boolean;
|
|
1600
|
+
type WaitForRepositoryReadyOptions = {
|
|
1601
|
+
/** First poll delay, in ms (default 5000). Grows with backoff up to maxIntervalMs. */
|
|
1602
|
+
intervalMs?: number;
|
|
1603
|
+
/** Cap on the poll delay, in ms (default 30000). */
|
|
1604
|
+
maxIntervalMs?: number;
|
|
1605
|
+
/** Give up after this long, in ms (default 30m). Throws on timeout. */
|
|
1606
|
+
timeoutMs?: number;
|
|
1607
|
+
/** Abort the wait (e.g. on Ctrl-C). Rejects with the abort reason. */
|
|
1608
|
+
signal?: AbortSignal;
|
|
1609
|
+
};
|
|
1183
1610
|
type WaitForScanOptions = {
|
|
1184
1611
|
/** First poll delay, in ms (default 5000). Grows with backoff up to maxIntervalMs. */
|
|
1185
1612
|
intervalMs?: number;
|
|
@@ -1208,6 +1635,15 @@ declare class ZkaoClient {
|
|
|
1208
1635
|
constructor(options: ZkaoClientOptions);
|
|
1209
1636
|
private get path();
|
|
1210
1637
|
listRepositories(): Promise<Repository[]>;
|
|
1638
|
+
/**
|
|
1639
|
+
* Block until a repository is ready to scan, then return it.
|
|
1640
|
+
*
|
|
1641
|
+
* A repository added moments ago is still being analyzed, and launching a
|
|
1642
|
+
* scan against it fails with `repository_initializing`. Call this between
|
|
1643
|
+
* adding a repository and launching its first scan rather than retrying the
|
|
1644
|
+
* launch and swallowing the error.
|
|
1645
|
+
*/
|
|
1646
|
+
waitForRepositoryReady(repositoryId: string, opts?: WaitForRepositoryReadyOptions): Promise<Repository>;
|
|
1211
1647
|
/** Read a repository's configured guidance (requires the `read` scope). */
|
|
1212
1648
|
getRepositoryGuidance(repositoryId: string): Promise<RepositoryGuidance>;
|
|
1213
1649
|
/**
|
|
@@ -1220,6 +1656,30 @@ declare class ZkaoClient {
|
|
|
1220
1656
|
setRepositoryGuidance(repositoryId: string, content: string | null, opts?: {
|
|
1221
1657
|
expectedContent?: string | null;
|
|
1222
1658
|
}): Promise<SetGuidanceResult>;
|
|
1659
|
+
/**
|
|
1660
|
+
* List a repository's audit areas (requires the `read` scope).
|
|
1661
|
+
*
|
|
1662
|
+
* An area is a named subsystem a scan can be scoped to: pass its `key` in
|
|
1663
|
+
* `auditAreaKeys` when launching. Sizes come from one branch's map, so an
|
|
1664
|
+
* area that map no longer names is returned without one. Defaults to the
|
|
1665
|
+
* repository's default branch.
|
|
1666
|
+
*/
|
|
1667
|
+
listAuditAreas(repositoryId: string, opts?: {
|
|
1668
|
+
branch?: string;
|
|
1669
|
+
}): Promise<AuditAreaList>;
|
|
1670
|
+
/**
|
|
1671
|
+
* Add a custom audit area (requires the `guidance:write` scope).
|
|
1672
|
+
*
|
|
1673
|
+
* An area is a name and a description, never a file list: a scan resolves it
|
|
1674
|
+
* against the code at the commit it runs on. The returned `key` is derived
|
|
1675
|
+
* from the name.
|
|
1676
|
+
*/
|
|
1677
|
+
createAuditArea(repositoryId: string, name: string, description?: string | null): Promise<AuditArea>;
|
|
1678
|
+
/**
|
|
1679
|
+
* Delete a custom audit area (requires the `guidance:write` scope). An area
|
|
1680
|
+
* a scan's map named is refused with a `409`.
|
|
1681
|
+
*/
|
|
1682
|
+
deleteAuditArea(repositoryId: string, areaKey: string): Promise<DeleteAuditAreaResult>;
|
|
1223
1683
|
listScans(opts?: {
|
|
1224
1684
|
page?: number;
|
|
1225
1685
|
limit?: number;
|
|
@@ -1263,7 +1723,19 @@ declare class ZkaoClient {
|
|
|
1263
1723
|
userSeverity?: Severity | null;
|
|
1264
1724
|
effectiveSeverity: Severity;
|
|
1265
1725
|
}>;
|
|
1266
|
-
|
|
1726
|
+
/**
|
|
1727
|
+
* Change a finding's resolution status (requires the `findings:write` scope).
|
|
1728
|
+
*
|
|
1729
|
+
* `note` attaches free text in the same call. `reason` picks a catalog code
|
|
1730
|
+
* instead, recorded as a generated comment; the codes offered depend on the
|
|
1731
|
+
* status, and a code from another status is rejected with 400. A `note` takes
|
|
1732
|
+
* precedence: pass one or the other. Both are ignored for the open statuses
|
|
1733
|
+
* (`NOT_STARTED`, `IN_PROGRESS`).
|
|
1734
|
+
*/
|
|
1735
|
+
setFindingResolution(findingId: string, resolutionStatus: ResolutionStatus, opts?: {
|
|
1736
|
+
note?: ChangeNote;
|
|
1737
|
+
reason?: ResolutionReason;
|
|
1738
|
+
}): Promise<{
|
|
1267
1739
|
findingId: string;
|
|
1268
1740
|
resolutionStatus: ResolutionStatus;
|
|
1269
1741
|
}>;
|
|
@@ -1273,6 +1745,31 @@ declare class ZkaoClient {
|
|
|
1273
1745
|
}): Promise<PublishArtifactResult>;
|
|
1274
1746
|
listScanPresets(): Promise<ScanPreset[]>;
|
|
1275
1747
|
listOptionalFlows(): Promise<OptionalFlow[]>;
|
|
1748
|
+
/**
|
|
1749
|
+
* Get the project's prepaid credit balance (requires the `read` scope). zkao
|
|
1750
|
+
* is pay-as-you-go: `balanceCredits` is the total, `reservedCredits` is held
|
|
1751
|
+
* by active scans, and `availableCredits` is what remains for new scans.
|
|
1752
|
+
*/
|
|
1753
|
+
getBillingBalance(): Promise<BillingBalance>;
|
|
1754
|
+
/**
|
|
1755
|
+
* List credit-ledger movements for reconciliation (requires the `read`
|
|
1756
|
+
* scope). `credits` on each event is signed (negative = spent). Defaults to
|
|
1757
|
+
* the last 30 days when `from`/`to` are omitted; the range actually used is
|
|
1758
|
+
* echoed back on the response.
|
|
1759
|
+
*/
|
|
1760
|
+
getBillingUsage(opts?: {
|
|
1761
|
+
from?: string;
|
|
1762
|
+
to?: string;
|
|
1763
|
+
limit?: number;
|
|
1764
|
+
}): Promise<BillingUsage>;
|
|
1765
|
+
/**
|
|
1766
|
+
* Per-calendar-month (UTC) totals of net credits spent on scans and net
|
|
1767
|
+
* credits purchased (requires the `read` scope). Quiet months are returned as
|
|
1768
|
+
* zeros; newest month first.
|
|
1769
|
+
*/
|
|
1770
|
+
getBillingSummary(opts?: {
|
|
1771
|
+
months?: number;
|
|
1772
|
+
}): Promise<UsageMonthSummary[]>;
|
|
1276
1773
|
}
|
|
1277
1774
|
|
|
1278
|
-
export { type CancelScanResult, type ChangeNote, DEFAULT_BASE_URL, type Finding, type FindingDetail, type FindingNote, type LaunchScanRequest, type LaunchScanResult, type OptionalFlow, type Paginated, type PublishArtifactResult, type Repository, type ResolutionStatus, type Scan, type ScanDetail, type ScanPreset, type ScanStatus, type Severity, TERMINAL_SCAN_STATUSES, type TriageStatus, type WaitForScanOptions, ZkaoApiError, ZkaoClient, type ZkaoClientOptions, type components, isTerminalScanStatus, normalizeBaseUrl, type paths, resolveBaseUrlFromEnv };
|
|
1775
|
+
export { type BillingBalance, type BillingSummary, type BillingUsage, type CancelScanResult, type ChangeNote, DEFAULT_BASE_URL, type Finding, type FindingDetail, type FindingNote, type LaunchScanRequest, type LaunchScanResult, type OptionalFlow, type Paginated, type PublishArtifactResult, type Repository, type RepositoryGuidance, type ResolutionReason, type ResolutionStatus, type Scan, type ScanDetail, type ScanPreset, type ScanStatus, type SetGuidanceResult, type Severity, TERMINAL_SCAN_STATUSES, type TriageStatus, type UsageEvent, type UsageEventType, type UsageMonthSummary, type WaitForRepositoryReadyOptions, type WaitForScanOptions, ZkaoApiError, ZkaoClient, type ZkaoClientOptions, type components, isTerminalScanStatus, normalizeBaseUrl, type paths, resolveBaseUrlFromEnv };
|
package/dist/index.js
CHANGED
|
@@ -120,6 +120,55 @@ var ZkaoClient = class {
|
|
|
120
120
|
});
|
|
121
121
|
return unwrap(res).repositories;
|
|
122
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Block until a repository is ready to scan, then return it.
|
|
125
|
+
*
|
|
126
|
+
* A repository added moments ago is still being analyzed, and launching a
|
|
127
|
+
* scan against it fails with `repository_initializing`. Call this between
|
|
128
|
+
* adding a repository and launching its first scan rather than retrying the
|
|
129
|
+
* launch and swallowing the error.
|
|
130
|
+
*/
|
|
131
|
+
async waitForRepositoryReady(repositoryId, opts = {}) {
|
|
132
|
+
const intervalMs = opts.intervalMs ?? 5e3;
|
|
133
|
+
const maxIntervalMs = opts.maxIntervalMs ?? 3e4;
|
|
134
|
+
const timeoutMs = opts.timeoutMs ?? 30 * 60 * 1e3;
|
|
135
|
+
const deadline = Date.now() + timeoutMs;
|
|
136
|
+
for (let attempt = 0; ; attempt++) {
|
|
137
|
+
throwIfAborted(opts.signal);
|
|
138
|
+
const res = await this.http.GET("/projects/{projectId}/repositories", {
|
|
139
|
+
params: { path: this.path },
|
|
140
|
+
signal: opts.signal
|
|
141
|
+
});
|
|
142
|
+
const retryAfterMs = parseRetryAfterMs(
|
|
143
|
+
res.response.headers.get("retry-after")
|
|
144
|
+
);
|
|
145
|
+
if (res.response.status !== 429) {
|
|
146
|
+
const repository = unwrap(res).repositories.find(
|
|
147
|
+
(candidate) => candidate.id === repositoryId
|
|
148
|
+
);
|
|
149
|
+
if (!repository) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Repository ${repositoryId} is not in this project (or this token's allowlist)`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (repository.readiness === "ready") {
|
|
155
|
+
return repository;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const backoffMs = Math.min(
|
|
159
|
+
maxIntervalMs,
|
|
160
|
+
Math.round(intervalMs * 1.5 ** attempt)
|
|
161
|
+
);
|
|
162
|
+
const baseMs = retryAfterMs ?? backoffMs;
|
|
163
|
+
const delayMs = baseMs + Math.round(Math.random() * baseMs * 0.2);
|
|
164
|
+
if (Date.now() + delayMs > deadline) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Timed out waiting for repository ${repositoryId} to be ready after ${timeoutMs}ms`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
await sleep(delayMs, opts.signal);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
123
172
|
/** Read a repository's configured guidance (requires the `read` scope). */
|
|
124
173
|
async getRepositoryGuidance(repositoryId) {
|
|
125
174
|
const res = await this.http.GET(
|
|
@@ -145,6 +194,55 @@ var ZkaoClient = class {
|
|
|
145
194
|
);
|
|
146
195
|
return unwrap(res);
|
|
147
196
|
}
|
|
197
|
+
// --- Audit areas --------------------------------------------------------
|
|
198
|
+
/**
|
|
199
|
+
* List a repository's audit areas (requires the `read` scope).
|
|
200
|
+
*
|
|
201
|
+
* An area is a named subsystem a scan can be scoped to: pass its `key` in
|
|
202
|
+
* `auditAreaKeys` when launching. Sizes come from one branch's map, so an
|
|
203
|
+
* area that map no longer names is returned without one. Defaults to the
|
|
204
|
+
* repository's default branch.
|
|
205
|
+
*/
|
|
206
|
+
async listAuditAreas(repositoryId, opts = {}) {
|
|
207
|
+
const res = await this.http.GET(
|
|
208
|
+
"/projects/{projectId}/repositories/{repositoryId}/audit-areas",
|
|
209
|
+
{
|
|
210
|
+
params: {
|
|
211
|
+
path: { ...this.path, repositoryId },
|
|
212
|
+
query: opts.branch === void 0 ? {} : { branch: opts.branch }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
return unwrap(res);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Add a custom audit area (requires the `guidance:write` scope).
|
|
220
|
+
*
|
|
221
|
+
* An area is a name and a description, never a file list: a scan resolves it
|
|
222
|
+
* against the code at the commit it runs on. The returned `key` is derived
|
|
223
|
+
* from the name.
|
|
224
|
+
*/
|
|
225
|
+
async createAuditArea(repositoryId, name, description) {
|
|
226
|
+
const res = await this.http.POST(
|
|
227
|
+
"/projects/{projectId}/repositories/{repositoryId}/audit-areas",
|
|
228
|
+
{
|
|
229
|
+
params: { path: { ...this.path, repositoryId } },
|
|
230
|
+
body: { name, description: description ?? null }
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
return unwrap(res).area;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Delete a custom audit area (requires the `guidance:write` scope). An area
|
|
237
|
+
* a scan's map named is refused with a `409`.
|
|
238
|
+
*/
|
|
239
|
+
async deleteAuditArea(repositoryId, areaKey) {
|
|
240
|
+
const res = await this.http.DELETE(
|
|
241
|
+
"/projects/{projectId}/repositories/{repositoryId}/audit-areas/{areaKey}",
|
|
242
|
+
{ params: { path: { ...this.path, repositoryId, areaKey } } }
|
|
243
|
+
);
|
|
244
|
+
return unwrap(res);
|
|
245
|
+
}
|
|
148
246
|
// --- Scans --------------------------------------------------------------
|
|
149
247
|
async listScans(opts = {}) {
|
|
150
248
|
const res = await this.http.GET("/projects/{projectId}/scans", {
|
|
@@ -263,10 +361,19 @@ var ZkaoClient = class {
|
|
|
263
361
|
});
|
|
264
362
|
return unwrap(res);
|
|
265
363
|
}
|
|
266
|
-
|
|
364
|
+
/**
|
|
365
|
+
* Change a finding's resolution status (requires the `findings:write` scope).
|
|
366
|
+
*
|
|
367
|
+
* `note` attaches free text in the same call. `reason` picks a catalog code
|
|
368
|
+
* instead, recorded as a generated comment; the codes offered depend on the
|
|
369
|
+
* status, and a code from another status is rejected with 400. A `note` takes
|
|
370
|
+
* precedence: pass one or the other. Both are ignored for the open statuses
|
|
371
|
+
* (`NOT_STARTED`, `IN_PROGRESS`).
|
|
372
|
+
*/
|
|
373
|
+
async setFindingResolution(findingId, resolutionStatus, opts = {}) {
|
|
267
374
|
const res = await this.http.PATCH("/projects/{projectId}/findings/{findingId}/resolution", {
|
|
268
375
|
params: { path: { ...this.path, findingId } },
|
|
269
|
-
body: { resolutionStatus, note }
|
|
376
|
+
body: { resolutionStatus, note: opts.note, reason: opts.reason }
|
|
270
377
|
});
|
|
271
378
|
return unwrap(res);
|
|
272
379
|
}
|
|
@@ -290,6 +397,44 @@ var ZkaoClient = class {
|
|
|
290
397
|
});
|
|
291
398
|
return unwrap(res).optionalFlows;
|
|
292
399
|
}
|
|
400
|
+
// --- Billing ------------------------------------------------------------
|
|
401
|
+
/**
|
|
402
|
+
* Get the project's prepaid credit balance (requires the `read` scope). zkao
|
|
403
|
+
* is pay-as-you-go: `balanceCredits` is the total, `reservedCredits` is held
|
|
404
|
+
* by active scans, and `availableCredits` is what remains for new scans.
|
|
405
|
+
*/
|
|
406
|
+
async getBillingBalance() {
|
|
407
|
+
const res = await this.http.GET("/projects/{projectId}/billing/balance", {
|
|
408
|
+
params: { path: this.path }
|
|
409
|
+
});
|
|
410
|
+
return unwrap(res);
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* List credit-ledger movements for reconciliation (requires the `read`
|
|
414
|
+
* scope). `credits` on each event is signed (negative = spent). Defaults to
|
|
415
|
+
* the last 30 days when `from`/`to` are omitted; the range actually used is
|
|
416
|
+
* echoed back on the response.
|
|
417
|
+
*/
|
|
418
|
+
async getBillingUsage(opts = {}) {
|
|
419
|
+
const res = await this.http.GET("/projects/{projectId}/billing/usage", {
|
|
420
|
+
params: {
|
|
421
|
+
path: this.path,
|
|
422
|
+
query: { from: opts.from, to: opts.to, limit: opts.limit }
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
return unwrap(res);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Per-calendar-month (UTC) totals of net credits spent on scans and net
|
|
429
|
+
* credits purchased (requires the `read` scope). Quiet months are returned as
|
|
430
|
+
* zeros; newest month first.
|
|
431
|
+
*/
|
|
432
|
+
async getBillingSummary(opts = {}) {
|
|
433
|
+
const res = await this.http.GET("/projects/{projectId}/billing/summary", {
|
|
434
|
+
params: { path: this.path, query: { months: opts.months } }
|
|
435
|
+
});
|
|
436
|
+
return unwrap(res).months;
|
|
437
|
+
}
|
|
293
438
|
};
|
|
294
439
|
function throwIfAborted(signal) {
|
|
295
440
|
if (signal?.aborted) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zksecurity/zkao-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "TypeScript SDK for the zkao Project API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "zkSecurity",
|
|
@@ -29,7 +29,11 @@
|
|
|
29
29
|
"import": "./dist/index.js"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
-
"files": [
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
33
37
|
"engines": {
|
|
34
38
|
"node": ">=18"
|
|
35
39
|
},
|