@zksecurity/zkao-sdk 0.5.1 → 0.11.0-next.2

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 CHANGED
@@ -29,6 +29,26 @@ declare function resolveBaseUrlFromEnv(env?: Record<string, string | undefined>)
29
29
  * Do not make direct changes to the file.
30
30
  */
31
31
  interface paths {
32
+ "/token": {
33
+ parameters: {
34
+ query?: never;
35
+ header?: never;
36
+ path?: never;
37
+ cookie?: never;
38
+ };
39
+ /**
40
+ * The calling token and its project
41
+ * @description Any valid token may call this, whatever its scopes. Use it to learn which project (and organization) a token belongs to.
42
+ */
43
+ get: operations["getTokenInfo"];
44
+ put?: never;
45
+ post?: never;
46
+ delete?: never;
47
+ options?: never;
48
+ head?: never;
49
+ patch?: never;
50
+ trace?: never;
51
+ };
32
52
  "/projects/{projectId}/repositories": {
33
53
  parameters: {
34
54
  query?: never;
@@ -134,13 +154,21 @@ interface paths {
134
154
  * Launch a scan
135
155
  * @description Requires scope: `scans:launch`. Reserves `creditBudget` credits from the
136
156
  * project balance. The repo must be in the token's allowlist (when set) and
137
- * ACTIVE. Discover valid `presetRef` / `optInFlowIds` via the discovery
138
- * endpoints. Per-token spend limits are enforced, and the project must have
139
- * enough prepaid credits to cover the budget (otherwise `402`).
157
+ * ACTIVE. Discover valid `presetRef` values via `/scan-presets`. Each scan
158
+ * type runs a fixed set of flows. Per-token spend limits are enforced, and
159
+ * the project must have enough prepaid credits to cover the budget
160
+ * (otherwise `402`).
140
161
  *
141
162
  * A repository added moments ago may still be analyzing, in which case
142
163
  * this returns `409 repository_initializing`. Wait for its `readiness` to
143
164
  * be `ready` in `GET /repositories` and launch again.
165
+ *
166
+ * A diff scan preset audits only the change from `baseCommit` to the
167
+ * scanned commit, and requires `baseCommit`. Every other preset refuses
168
+ * it. A malformed, unknown, or misplaced base is a `400` with code
169
+ * `diff_base_required`, `diff_base_not_allowed`, or `diff_base_invalid`.
170
+ * A diff scan also needs an earlier full scan of the branch, and a
171
+ * change to audit (otherwise `422`).
144
172
  */
145
173
  post: operations["launchScan"];
146
174
  delete?: never;
@@ -369,26 +397,6 @@ interface paths {
369
397
  patch?: never;
370
398
  trace?: never;
371
399
  };
372
- "/projects/{projectId}/optional-flows": {
373
- parameters: {
374
- query?: never;
375
- header?: never;
376
- path?: never;
377
- cookie?: never;
378
- };
379
- /**
380
- * List opt-in flows available at launch
381
- * @description Requires scope: `read`. Pass the chosen ids as `optInFlowIds` when launching. A flow marked `rotating` may run without being asked for.
382
- */
383
- get: operations["listOptionalFlows"];
384
- put?: never;
385
- post?: never;
386
- delete?: never;
387
- options?: never;
388
- head?: never;
389
- patch?: never;
390
- trace?: never;
391
- };
392
400
  "/projects/{projectId}/billing/balance": {
393
401
  parameters: {
394
402
  query?: never;
@@ -397,8 +405,8 @@ interface paths {
397
405
  cookie?: never;
398
406
  };
399
407
  /**
400
- * Current prepaid credit balance
401
- * @description Requires scope: `read`. All amounts are in credits.
408
+ * Credits available to this project
409
+ * @description Requires scope: `read`. The organization's shared prepaid balance, available to this project and to the organization's other projects. All amounts are in credits.
402
410
  */
403
411
  get: operations["getBillingBalance"];
404
412
  put?: never;
@@ -417,8 +425,8 @@ interface paths {
417
425
  cookie?: never;
418
426
  };
419
427
  /**
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.
428
+ * Credit usage events attributed to this project
429
+ * @description Requires scope: `read`. Signed credit delta per ledger event attributed to this project; organization-wide movements such as a top-up made outside any project are not included. Defaults to the last 30 days; newest first; max 1000 rows.
422
430
  */
423
431
  get: operations["getBillingUsage"];
424
432
  put?: never;
@@ -437,8 +445,8 @@ interface paths {
437
445
  cookie?: never;
438
446
  };
439
447
  /**
440
- * Monthly spend and purchase summary
441
- * @description Requires scope: `read`. Per-month net scan spend and net purchases, in credits, newest first.
448
+ * Monthly spend and purchase summary for this project
449
+ * @description Requires scope: `read`. Per-month net scan spend and net purchases attributed to this project, in credits, newest first. Purchases land in the organization's shared balance.
442
450
  */
443
451
  get: operations["getBillingSummary"];
444
452
  put?: never;
@@ -452,12 +460,38 @@ interface paths {
452
460
  }
453
461
  interface components {
454
462
  schemas: {
463
+ /** @description The organization a project belongs to. Credits are held and billed at this level and shared by every project in it. */
464
+ Organization: {
465
+ id: string;
466
+ /** @description URL segment of the organization (`/orgs/<slug>`), unique across zkao. */
467
+ slug: string;
468
+ name: string;
469
+ };
470
+ TokenInfo: {
471
+ id: string;
472
+ name: string;
473
+ scopes: string[];
474
+ /** @description Repositories the token is restricted to. Empty means every repository of the project. */
475
+ repositoryIds: string[];
476
+ /** Format: date-time */
477
+ expiresAt: string | null;
478
+ /** @description Credits this token may spend. Null means no limit. */
479
+ spendLimitCredits: number | null;
480
+ project: {
481
+ id: string;
482
+ slug: string;
483
+ name: string;
484
+ organization: components["schemas"]["Organization"];
485
+ };
486
+ };
455
487
  BillingBalance: {
456
- /** @description Total prepaid credit balance. */
488
+ /** @description The organization whose shared balance this is. */
489
+ organization: components["schemas"]["Organization"];
490
+ /** @description The organization's total prepaid credit balance, shared by all of its projects. */
457
491
  balanceCredits: number;
458
- /** @description Balance minus credits reserved by in-flight scans. */
492
+ /** @description Balance minus credits reserved by the organization's in-flight scans. */
459
493
  availableCredits: number;
460
- /** @description Credits held by queued/running scans. */
494
+ /** @description Credits held by the organization's queued/running scans. */
461
495
  reservedCredits: number;
462
496
  };
463
497
  /** @enum {string} */
@@ -488,12 +522,14 @@ interface components {
488
522
  purchasedCredits: number;
489
523
  };
490
524
  BillingSummary: {
525
+ /** @description The organization whose shared balance the purchases were made into. */
526
+ organization: components["schemas"]["Organization"];
491
527
  months: components["schemas"]["UsageMonthSummary"][];
492
528
  };
493
529
  Error: {
494
530
  error: {
495
531
  /** @enum {string} */
496
- code: "unauthorized" | "forbidden" | "not_found" | "bad_request" | "conflict" | "insufficient_credits" | "repository_initializing" | "rate_limited" | "internal";
532
+ code: "unauthorized" | "forbidden" | "not_found" | "bad_request" | "conflict" | "insufficient_credits" | "repository_initializing" | "diff_base_required" | "diff_base_not_allowed" | "diff_base_invalid" | "diff_empty" | "diff_overview_missing" | "rate_limited" | "internal";
497
533
  message: string;
498
534
  };
499
535
  };
@@ -507,6 +543,8 @@ interface components {
507
543
  ScanStatus: "QUEUED" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED";
508
544
  Repository: {
509
545
  id: string;
546
+ /** @description URL segment of the repository inside its project (`/orgs/<org>/projects/<project>/repos/<slug>`). Unique per project. */
547
+ slug: string;
510
548
  owner: string;
511
549
  name: string;
512
550
  url: string;
@@ -524,6 +562,8 @@ interface components {
524
562
  status: components["schemas"]["ScanStatus"];
525
563
  repositoryId: string;
526
564
  commitHash?: string | null;
565
+ /** @description A diff scan's base, as the merge base SHA its change is measured from. Null for other scans. */
566
+ baseCommit?: string | null;
527
567
  commitMessage?: string | null;
528
568
  presetName?: string | null;
529
569
  /** Format: date-time */
@@ -564,6 +604,11 @@ interface components {
564
604
  severity: components["schemas"]["Severity"];
565
605
  category: string;
566
606
  triageStatus: components["schemas"]["TriageStatus"];
607
+ /**
608
+ * @description What backs a CONFIRMED verdict. POC means a proof of concept ran and demonstrated the issue. ANALYSIS means it was confirmed by code analysis alone. Null for other statuses or when not recorded.
609
+ * @enum {string|null}
610
+ */
611
+ confirmationEvidence?: "POC" | "ANALYSIS" | null;
567
612
  resolutionStatus: components["schemas"]["ResolutionStatus"];
568
613
  notesCount: number;
569
614
  };
@@ -610,23 +655,14 @@ interface components {
610
655
  ref: string;
611
656
  name: string;
612
657
  description?: string | null;
613
- /** @description Minimum budget for a launch that names no optInFlowIds. Adding a flow raises it. 0 = use the default floor. */
658
+ /** @description Minimum budget for a launch. 0 = use the default floor. */
614
659
  minCredits: number;
615
660
  modelTier: string;
616
661
  };
617
- OptionalFlow: {
618
- /** @description Pass in `optInFlowIds` when launching. */
619
- id: string;
620
- flowId: string;
621
- title: string;
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;
625
- };
626
662
  LaunchScanRequest: {
627
663
  repositoryId: string;
628
- /** @description Max budget for the scan, in credits. Reserved at launch. */
629
- creditBudget: number;
664
+ /** @description Max budget for the scan, in credits. Reserved at launch. Omit it to launch at the budget zkao recommends for this scan type and scope on this repository: sized from what past scans of it spent, half again the last budget when that scan ran short of it, or the scan type's minimum on the first. */
665
+ creditBudget?: number;
630
666
  /** @description A preset ref from /scan-presets. Defaults to the first active preset. */
631
667
  presetRef?: string;
632
668
  /** @description Branch to scan (resolved to its head commit server-side). Ignored if commitHash is set. */
@@ -634,8 +670,8 @@ interface components {
634
670
  /** @description Pin a specific commit SHA (7-40 hex chars). */
635
671
  commitHash?: string | null;
636
672
  commitMessage?: string | null;
637
- /** @description Optional-flow ids from /optional-flows, added to the scan on top of whatever a rotating group already contributes. */
638
- optInFlowIds?: string[];
673
+ /** @description What a diff scan's change is measured from: a commit SHA, branch, or tag. Required by a diff scan preset and refused by every other. The scan records the merge base of this and the scanned commit. */
674
+ baseCommit?: string | null;
639
675
  /** @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
676
  auditAreaKeys?: string[];
641
677
  /** @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. */
@@ -644,6 +680,8 @@ interface components {
644
680
  LaunchScanResult: {
645
681
  scanId: string;
646
682
  queued: boolean;
683
+ /** @description The budget the scan was launched with, in credits. */
684
+ creditBudget: number;
647
685
  };
648
686
  RepositoryGuidance: {
649
687
  repositoryId: string;
@@ -800,6 +838,15 @@ interface components {
800
838
  "application/json": components["schemas"]["Error"];
801
839
  };
802
840
  };
841
+ /** @description The diff scan cannot run on this repository yet. Code `diff_empty`: the base and the scanned commit have no change between them. Code `diff_overview_missing`: no earlier full scan of the branch (or the default branch) exists to compare against. Run a full scan first. */
842
+ DiffUnavailable: {
843
+ headers: {
844
+ [name: string]: unknown;
845
+ };
846
+ content: {
847
+ "application/json": components["schemas"]["Error"];
848
+ };
849
+ };
803
850
  /** @description The token lacks the required scope */
804
851
  Forbidden: {
805
852
  headers: {
@@ -853,6 +900,27 @@ interface components {
853
900
  pathItems: never;
854
901
  }
855
902
  interface operations {
903
+ getTokenInfo: {
904
+ parameters: {
905
+ query?: never;
906
+ header?: never;
907
+ path?: never;
908
+ cookie?: never;
909
+ };
910
+ requestBody?: never;
911
+ responses: {
912
+ /** @description OK */
913
+ 200: {
914
+ headers: {
915
+ [name: string]: unknown;
916
+ };
917
+ content: {
918
+ "application/json": components["schemas"]["TokenInfo"];
919
+ };
920
+ };
921
+ 401: components["responses"]["Unauthorized"];
922
+ };
923
+ };
856
924
  listRepositories: {
857
925
  parameters: {
858
926
  query?: never;
@@ -1087,6 +1155,7 @@ interface operations {
1087
1155
  403: components["responses"]["Forbidden"];
1088
1156
  404: components["responses"]["NotFound"];
1089
1157
  409: components["responses"]["RepositoryInitializing"];
1158
+ 422: components["responses"]["DiffUnavailable"];
1090
1159
  429: components["responses"]["RateLimited"];
1091
1160
  };
1092
1161
  };
@@ -1446,33 +1515,6 @@ interface operations {
1446
1515
  404: components["responses"]["NotFound"];
1447
1516
  };
1448
1517
  };
1449
- listOptionalFlows: {
1450
- parameters: {
1451
- query?: never;
1452
- header?: never;
1453
- path: {
1454
- projectId: components["parameters"]["ProjectId"];
1455
- };
1456
- cookie?: never;
1457
- };
1458
- requestBody?: never;
1459
- responses: {
1460
- /** @description OK */
1461
- 200: {
1462
- headers: {
1463
- [name: string]: unknown;
1464
- };
1465
- content: {
1466
- "application/json": {
1467
- optionalFlows: components["schemas"]["OptionalFlow"][];
1468
- };
1469
- };
1470
- };
1471
- 401: components["responses"]["Unauthorized"];
1472
- 403: components["responses"]["Forbidden"];
1473
- 404: components["responses"]["NotFound"];
1474
- };
1475
- };
1476
1518
  getBillingBalance: {
1477
1519
  parameters: {
1478
1520
  query?: never;
@@ -1565,7 +1607,6 @@ type Finding = Schemas["Finding"];
1565
1607
  type FindingDetail = Schemas["FindingDetail"];
1566
1608
  type FindingNote = Schemas["FindingNote"];
1567
1609
  type ScanPreset = Schemas["ScanPreset"];
1568
- type OptionalFlow = Schemas["OptionalFlow"];
1569
1610
  type LaunchScanRequest = Schemas["LaunchScanRequest"];
1570
1611
  type LaunchScanResult = Schemas["LaunchScanResult"];
1571
1612
  type CancelScanResult = Schemas["CancelScanResult"];
@@ -1581,6 +1622,7 @@ type AuditArea = Schemas["AuditArea"];
1581
1622
  type AuditAreaList = Schemas["AuditAreaList"];
1582
1623
  type DeleteAuditAreaResult = Schemas["DeleteAuditAreaResult"];
1583
1624
  type SetGuidanceResult = Schemas["SetGuidanceResult"];
1625
+ type TokenInfo = Schemas["TokenInfo"];
1584
1626
  type BillingBalance = Schemas["BillingBalance"];
1585
1627
  type BillingUsage = Schemas["BillingUsage"];
1586
1628
  type UsageEvent = Schemas["UsageEvent"];
@@ -1593,6 +1635,25 @@ type Paginated<T> = {
1593
1635
  limit: number;
1594
1636
  total: number;
1595
1637
  };
1638
+ /**
1639
+ * Body of `createManualAudit`. Not part of the published OpenAPI spec: the
1640
+ * endpoint needs the `admin` scope, which only a zkao site admin can grant.
1641
+ */
1642
+ type ManualAuditRequest = {
1643
+ /** Repository the audit covers. */
1644
+ repositoryId: string;
1645
+ /** Commit the audit reviewed (7-64 hex characters). */
1646
+ commitHash: string;
1647
+ commitMessage?: string | null;
1648
+ /** Findings YAML, as report-tool's `just export-findings <slug>` prints it. */
1649
+ findingsYaml: string;
1650
+ /** Report body markdown, shown on the scan page. */
1651
+ reportMarkdown?: string | null;
1652
+ };
1653
+ type ManualAuditResult = {
1654
+ scanId: string;
1655
+ findingsCreated: number;
1656
+ };
1596
1657
  type ZkaoClientOptions = {
1597
1658
  /** A project API token: `zkao_proj_<keyId>_<secret>`. */
1598
1659
  token: string;
@@ -1642,11 +1703,27 @@ declare class ZkaoApiError extends Error {
1642
1703
  * Typed client for one zkao project. Every call is scoped to the project the
1643
1704
  * token belongs to; see https://zkao.io/openapi/v1.yaml for the full contract.
1644
1705
  */
1706
+ /**
1707
+ * Which project (and organization) a token belongs to, plus its scopes and
1708
+ * limits. Needs no project id, so it works with a token whose project is
1709
+ * unknown. Any valid token may call it.
1710
+ */
1711
+ declare function getTokenInfo(options: Omit<ZkaoClientOptions, "projectId">): Promise<TokenInfo>;
1645
1712
  declare class ZkaoClient {
1646
1713
  private readonly http;
1647
1714
  private readonly projectId;
1715
+ private readonly baseUrl;
1716
+ private readonly token;
1717
+ private readonly fetchImpl;
1648
1718
  constructor(options: ZkaoClientOptions);
1719
+ /**
1720
+ * POST a JSON body to a project route that is not in the generated `paths`.
1721
+ * Same error envelope handling as the typed calls.
1722
+ */
1723
+ private postUntyped;
1649
1724
  private get path();
1725
+ /** The calling token, and the project and organization it belongs to. */
1726
+ getTokenInfo(): Promise<TokenInfo>;
1650
1727
  listRepositories(): Promise<Repository[]>;
1651
1728
  /**
1652
1729
  * Block until a repository is ready to scan, then return it.
@@ -1717,6 +1794,12 @@ declare class ZkaoClient {
1717
1794
  publishScan(scanId: string, opts?: {
1718
1795
  withPassword?: boolean;
1719
1796
  }): Promise<PublishArtifactResult>;
1797
+ /**
1798
+ * Record a zkSecurity audit report on the project as a manual audit: a
1799
+ * completed scan whose findings are pre-confirmed. Requires the `admin`
1800
+ * scope, which only a zkao site admin can grant; any other token gets 404.
1801
+ */
1802
+ createManualAudit(body: ManualAuditRequest): Promise<ManualAuditResult>;
1720
1803
  listFindings(opts?: {
1721
1804
  page?: number;
1722
1805
  limit?: number;
@@ -1757,7 +1840,6 @@ declare class ZkaoClient {
1757
1840
  withPassword?: boolean;
1758
1841
  }): Promise<PublishArtifactResult>;
1759
1842
  listScanPresets(): Promise<ScanPreset[]>;
1760
- listOptionalFlows(): Promise<OptionalFlow[]>;
1761
1843
  /**
1762
1844
  * Get the project's prepaid credit balance (requires the `read` scope). zkao
1763
1845
  * is pay-as-you-go: `balanceCredits` is the total, `reservedCredits` is held
@@ -1785,4 +1867,4 @@ declare class ZkaoClient {
1785
1867
  }): Promise<UsageMonthSummary[]>;
1786
1868
  }
1787
1869
 
1788
- 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 };
1870
+ 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 ManualAuditRequest, type ManualAuditResult, 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 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 };
package/dist/index.js CHANGED
@@ -99,20 +99,64 @@ function unwrap(result) {
99
99
  envelope?.error?.message ?? result.response.statusText
100
100
  );
101
101
  }
102
+ async function getTokenInfo(options) {
103
+ const http = createClient({
104
+ baseUrl: options.baseUrl ?? resolveBaseUrlFromEnv() ?? DEFAULT_BASE_URL,
105
+ headers: { Authorization: `Bearer ${options.token}` },
106
+ ...options.fetch ? { fetch: options.fetch } : {}
107
+ });
108
+ return unwrap(await http.GET("/token"));
109
+ }
102
110
  var ZkaoClient = class {
103
111
  http;
104
112
  projectId;
113
+ baseUrl;
114
+ token;
115
+ fetchImpl;
105
116
  constructor(options) {
106
117
  this.projectId = options.projectId;
118
+ this.baseUrl = options.baseUrl ?? resolveBaseUrlFromEnv() ?? DEFAULT_BASE_URL;
119
+ this.token = options.token;
120
+ this.fetchImpl = options.fetch ?? fetch;
107
121
  this.http = createClient({
108
- baseUrl: options.baseUrl ?? resolveBaseUrlFromEnv() ?? DEFAULT_BASE_URL,
109
- headers: { Authorization: `Bearer ${options.token}` },
122
+ baseUrl: this.baseUrl,
123
+ headers: { Authorization: `Bearer ${this.token}` },
110
124
  ...options.fetch ? { fetch: options.fetch } : {}
111
125
  });
112
126
  }
127
+ /**
128
+ * POST a JSON body to a project route that is not in the generated `paths`.
129
+ * Same error envelope handling as the typed calls.
130
+ */
131
+ async postUntyped(path, body) {
132
+ const url = `${this.baseUrl.replace(/\/+$/, "")}/projects/${encodeURIComponent(this.projectId)}${path}`;
133
+ const response = await this.fetchImpl(url, {
134
+ method: "POST",
135
+ headers: {
136
+ Authorization: `Bearer ${this.token}`,
137
+ "Content-Type": "application/json"
138
+ },
139
+ body: JSON.stringify(body)
140
+ });
141
+ let payload;
142
+ try {
143
+ payload = await response.json();
144
+ } catch {
145
+ payload = void 0;
146
+ }
147
+ if (response.ok && payload !== void 0) {
148
+ return payload;
149
+ }
150
+ return unwrap({ error: payload, response });
151
+ }
113
152
  get path() {
114
153
  return { projectId: this.projectId };
115
154
  }
155
+ // --- Token --------------------------------------------------------------
156
+ /** The calling token, and the project and organization it belongs to. */
157
+ async getTokenInfo() {
158
+ return unwrap(await this.http.GET("/token"));
159
+ }
116
160
  // --- Repositories -------------------------------------------------------
117
161
  async listRepositories() {
118
162
  const res = await this.http.GET("/projects/{projectId}/repositories", {
@@ -324,6 +368,14 @@ var ZkaoClient = class {
324
368
  });
325
369
  return unwrap(res);
326
370
  }
371
+ /**
372
+ * Record a zkSecurity audit report on the project as a manual audit: a
373
+ * completed scan whose findings are pre-confirmed. Requires the `admin`
374
+ * scope, which only a zkao site admin can grant; any other token gets 404.
375
+ */
376
+ async createManualAudit(body) {
377
+ return this.postUntyped("/manual-audits", body);
378
+ }
327
379
  // --- Findings -----------------------------------------------------------
328
380
  async listFindings(opts = {}) {
329
381
  const res = await this.http.GET("/projects/{projectId}/findings", {
@@ -391,12 +443,6 @@ var ZkaoClient = class {
391
443
  });
392
444
  return unwrap(res).presets;
393
445
  }
394
- async listOptionalFlows() {
395
- const res = await this.http.GET("/projects/{projectId}/optional-flows", {
396
- params: { path: this.path }
397
- });
398
- return unwrap(res).optionalFlows;
399
- }
400
446
  // --- Billing ------------------------------------------------------------
401
447
  /**
402
448
  * Get the project's prepaid credit balance (requires the `read` scope). zkao
@@ -474,6 +520,7 @@ export {
474
520
  TERMINAL_SCAN_STATUSES,
475
521
  ZkaoApiError,
476
522
  ZkaoClient,
523
+ getTokenInfo,
477
524
  isTerminalScanStatus,
478
525
  normalizeBaseUrl,
479
526
  resolveBaseUrlFromEnv
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zksecurity/zkao-sdk",
3
- "version": "0.5.1",
3
+ "version": "0.11.0-next.2",
4
4
  "description": "TypeScript SDK for the zkao Project API",
5
5
  "license": "MIT",
6
6
  "author": "zkSecurity",