@zksecurity/zkao-sdk 0.15.0-next.10 → 0.16.0-next.11

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
@@ -289,7 +289,9 @@ interface paths {
289
289
  };
290
290
  /**
291
291
  * Get an advisory
292
- * @description Requires scope: `read`. The advisory, the versions it affects, and the notices planned for it.
292
+ * @description Requires scope: `read`. The advisory, the software it concerns, the versions it affects, and the notices planned for it.
293
+ *
294
+ * `software` is what decides the audience: a contact is notified about an advisory only when they run some of it. `affected` is a separate statement about versions, and is often empty.
293
295
  *
294
296
  * A notice the plan is holding back carries `blockedReason`. The commonest one is that no affected range names a fixed version, which only the people who shipped the release can supply; record it in the app and the notice becomes schedulable.
295
297
  */
@@ -302,6 +304,66 @@ interface paths {
302
304
  patch?: never;
303
305
  trace?: never;
304
306
  };
307
+ "/projects/{projectId}/advisories/{publicId}/affected": {
308
+ parameters: {
309
+ query?: never;
310
+ header?: never;
311
+ path?: never;
312
+ cookie?: never;
313
+ };
314
+ get?: never;
315
+ /**
316
+ * Record which versions an advisory affects
317
+ * @description Requires scope: `advisories:write`. Replaces the whole set of affected ranges, so send what is affected now rather than a patch.
318
+ *
319
+ * `fixedIn` is the point of this endpoint. A patch notice stays blocked until some range names a fixed version, and only the people who shipped the release know it.
320
+ *
321
+ * Versions only. A range may name only software already on the advisory's `software`, and anything else is a `400`. Which software an advisory concerns decides who hears about it, and that is its own statement, made in the app: a call about versions does not change it in either direction.
322
+ *
323
+ * This call never sends anything. It records versions and recomputes the disclosure plan: a notice blocked for want of a fix becomes eligible to go, and one that loses its fix is blocked again, dropping any approval it was carrying so nobody approves wording a later fix rewrites. When an eligible notice is actually sent is governed by the programme's own settings, not by this call.
324
+ */
325
+ put: operations["replaceAdvisoryAffected"];
326
+ post?: never;
327
+ delete?: never;
328
+ options?: never;
329
+ head?: never;
330
+ patch?: never;
331
+ trace?: never;
332
+ };
333
+ "/projects/{projectId}/advisory-contacts": {
334
+ parameters: {
335
+ query?: never;
336
+ header?: never;
337
+ path?: never;
338
+ cookie?: never;
339
+ };
340
+ /**
341
+ * List the advisory contacts
342
+ * @description Requires scope: `contacts:read`. The programme's contact list, oldest first, which is the order to read it in when reconciling against a record kept elsewhere.
343
+ *
344
+ * Its own scope, not `read`: this list is other people's work addresses and the record of who learns about a vulnerability before the public does, so a routine pipeline token does not reach it.
345
+ *
346
+ * `software` on each row is what notices are matched on. A project with no security programme reads as an empty list.
347
+ */
348
+ get: operations["listAdvisoryContacts"];
349
+ put?: never;
350
+ /**
351
+ * Add an advisory contact
352
+ * @description Requires scope: `contacts:write`. Puts one address on the programme's contact list.
353
+ *
354
+ * `software` says which of the project's repositories this contact runs, and is required. It is what every notice is matched on: a contact who runs nothing is told nothing.
355
+ *
356
+ * The contact starts `PENDING_VERIFICATION`, and an unconfirmed address receives nothing embargoed. The confirmation mail is sent from the app, not by this call, so nothing is emailed to the address you send here.
357
+ *
358
+ * There is no endpoint that reads the contact list back. It is other people's work addresses and the record of who hears about a vulnerability early.
359
+ */
360
+ post: operations["addAdvisoryContact"];
361
+ delete?: never;
362
+ options?: never;
363
+ head?: never;
364
+ patch?: never;
365
+ trace?: never;
366
+ };
305
367
  "/projects/{projectId}/findings": {
306
368
  parameters: {
307
369
  query?: never;
@@ -868,9 +930,35 @@ interface components {
868
930
  description: string;
869
931
  impact: string;
870
932
  cwe?: string | null;
933
+ /** @description The software the advisory is about. A contact hears about it only when they run some of it. */
934
+ software: {
935
+ owner: string;
936
+ name: string;
937
+ }[];
871
938
  affected: components["schemas"]["AdvisoryAffected"][];
872
939
  notices: components["schemas"]["AdvisoryNotice"][];
873
940
  };
941
+ AdvisoryContact: {
942
+ id: string;
943
+ email: string;
944
+ organization: string;
945
+ tier: string;
946
+ /** @description `PENDING_VERIFICATION` until the contact confirms the address. An unconfirmed address receives nothing embargoed. */
947
+ status: string;
948
+ /** @description The software this contact runs, which notices are matched on. */
949
+ software: {
950
+ owner: string;
951
+ name: string;
952
+ }[];
953
+ /** Format: date-time */
954
+ createdAt: string;
955
+ };
956
+ PaginatedAdvisoryContacts: {
957
+ items: components["schemas"]["AdvisoryContact"][];
958
+ page: number;
959
+ limit: number;
960
+ total: number;
961
+ };
874
962
  PaginatedAdvisories: {
875
963
  items: components["schemas"]["Advisory"][];
876
964
  page: number;
@@ -1589,6 +1677,141 @@ interface operations {
1589
1677
  404: components["responses"]["NotFound"];
1590
1678
  };
1591
1679
  };
1680
+ replaceAdvisoryAffected: {
1681
+ parameters: {
1682
+ query?: never;
1683
+ header?: never;
1684
+ path: {
1685
+ projectId: components["parameters"]["ProjectId"];
1686
+ /** @description The advisory's readable identifier. */
1687
+ publicId: string;
1688
+ };
1689
+ cookie?: never;
1690
+ };
1691
+ requestBody: {
1692
+ content: {
1693
+ "application/json": {
1694
+ affected: {
1695
+ repository: {
1696
+ owner: string;
1697
+ name: string;
1698
+ };
1699
+ /** @description First version carrying the defect. */
1700
+ introducedIn: string;
1701
+ /** @description Version that closes the range, or null. */
1702
+ fixedIn?: string | null;
1703
+ }[];
1704
+ };
1705
+ };
1706
+ };
1707
+ responses: {
1708
+ /** @description OK */
1709
+ 200: {
1710
+ headers: {
1711
+ [name: string]: unknown;
1712
+ };
1713
+ content: {
1714
+ "application/json": {
1715
+ advisory: components["schemas"]["AdvisoryDetail"];
1716
+ };
1717
+ };
1718
+ };
1719
+ 400: components["responses"]["BadRequest"];
1720
+ 401: components["responses"]["Unauthorized"];
1721
+ 403: components["responses"]["Forbidden"];
1722
+ 404: components["responses"]["NotFound"];
1723
+ 409: components["responses"]["Conflict"];
1724
+ };
1725
+ };
1726
+ listAdvisoryContacts: {
1727
+ parameters: {
1728
+ query?: {
1729
+ page?: components["parameters"]["Page"];
1730
+ limit?: components["parameters"]["Limit"];
1731
+ tier?: "EMBARGO" | "DOWNSTREAM" | "ANNOUNCE";
1732
+ status?: "ACTIVE" | "PENDING_VERIFICATION" | "BOUNCED" | "UNSUBSCRIBED";
1733
+ };
1734
+ header?: never;
1735
+ path: {
1736
+ projectId: components["parameters"]["ProjectId"];
1737
+ };
1738
+ cookie?: never;
1739
+ };
1740
+ requestBody?: never;
1741
+ responses: {
1742
+ /** @description OK */
1743
+ 200: {
1744
+ headers: {
1745
+ [name: string]: unknown;
1746
+ };
1747
+ content: {
1748
+ "application/json": components["schemas"]["PaginatedAdvisoryContacts"];
1749
+ };
1750
+ };
1751
+ 400: components["responses"]["BadRequest"];
1752
+ 401: components["responses"]["Unauthorized"];
1753
+ 403: components["responses"]["Forbidden"];
1754
+ };
1755
+ };
1756
+ addAdvisoryContact: {
1757
+ parameters: {
1758
+ query?: never;
1759
+ header?: never;
1760
+ path: {
1761
+ projectId: components["parameters"]["ProjectId"];
1762
+ };
1763
+ cookie?: never;
1764
+ };
1765
+ requestBody: {
1766
+ content: {
1767
+ "application/json": {
1768
+ email: string;
1769
+ /** @description The organisation this contact speaks for. */
1770
+ organization: string;
1771
+ /**
1772
+ * @description How early this contact is told. `EMBARGO` hears first and alone, `DOWNSTREAM` joins once a patch exists, `ANNOUNCE` learns at public disclosure.
1773
+ * @enum {string}
1774
+ */
1775
+ tier: "EMBARGO" | "DOWNSTREAM" | "ANNOUNCE";
1776
+ /** @description The repositories this contact runs. At least one. */
1777
+ software: {
1778
+ owner: string;
1779
+ name: string;
1780
+ }[];
1781
+ name?: string | null;
1782
+ title?: string | null;
1783
+ notes?: string | null;
1784
+ tags?: string[];
1785
+ };
1786
+ };
1787
+ };
1788
+ responses: {
1789
+ /** @description Created */
1790
+ 201: {
1791
+ headers: {
1792
+ [name: string]: unknown;
1793
+ };
1794
+ content: {
1795
+ "application/json": {
1796
+ contact: components["schemas"]["AdvisoryContact"];
1797
+ };
1798
+ };
1799
+ };
1800
+ 400: components["responses"]["BadRequest"];
1801
+ 401: components["responses"]["Unauthorized"];
1802
+ 403: components["responses"]["Forbidden"];
1803
+ 404: components["responses"]["NotFound"];
1804
+ /** @description That address is already on the programme's contact list. */
1805
+ 409: {
1806
+ headers: {
1807
+ [name: string]: unknown;
1808
+ };
1809
+ content: {
1810
+ "application/json": components["schemas"]["Error"];
1811
+ };
1812
+ };
1813
+ };
1814
+ };
1592
1815
  listFindings: {
1593
1816
  parameters: {
1594
1817
  query?: {
@@ -2039,6 +2262,37 @@ type Report = Schemas["Report"];
2039
2262
  type ReportStatus = "NEW" | "TRIAGING" | "NEEDS_INFO" | "ACCEPTED" | "DUPLICATE" | "REJECTED";
2040
2263
  type Advisory = Schemas["Advisory"];
2041
2264
  type AdvisoryDetail = Schemas["AdvisoryDetail"];
2265
+ type AdvisoryAffected = Schemas["AdvisoryAffected"];
2266
+ /** One affected version line, as a caller states it. */
2267
+ type AdvisoryAffectedInput = {
2268
+ repository: {
2269
+ owner: string;
2270
+ name: string;
2271
+ };
2272
+ introducedIn: string;
2273
+ fixedIn?: string | null;
2274
+ };
2275
+ type AdvisoryNotice = Schemas["AdvisoryNotice"];
2276
+ type AdvisoryContact = Schemas["AdvisoryContact"];
2277
+ /** How early a contact is told. */
2278
+ type ContactTier = "EMBARGO" | "DOWNSTREAM" | "ANNOUNCE";
2279
+ /** Whether a contact can be written to. Only ACTIVE hears anything. */
2280
+ type ContactStatus = "ACTIVE" | "PENDING_VERIFICATION" | "BOUNCED" | "UNSUBSCRIBED";
2281
+ /** A contact as a caller states it. */
2282
+ type AdvisoryContactInput = {
2283
+ email: string;
2284
+ organization: string;
2285
+ tier: ContactTier;
2286
+ /** The repositories this contact runs. At least one. */
2287
+ software: {
2288
+ owner: string;
2289
+ name: string;
2290
+ }[];
2291
+ name?: string | null;
2292
+ title?: string | null;
2293
+ notes?: string | null;
2294
+ tags?: string[];
2295
+ };
2042
2296
  /** The statuses an advisory moves through. */
2043
2297
  type AdvisoryStatus = "DRAFT" | "SCHEDULED" | "UNDER_EMBARGO" | "PUBLISHED" | "WITHDRAWN";
2044
2298
  type UsageMonthSummary = Schemas["UsageMonthSummary"];
@@ -2222,13 +2476,62 @@ declare class ZkaoClient {
2222
2476
  status?: AdvisoryStatus;
2223
2477
  }): Promise<Paginated<Advisory>>;
2224
2478
  /**
2225
- * One advisory, the versions it affects, and the notices planned for it.
2479
+ * One advisory, the software it concerns, the versions it affects, and the
2480
+ * notices planned for it.
2481
+ *
2482
+ * `software` is what decides the audience: a contact is notified about an
2483
+ * advisory only when they run some of it. `affected` is a separate statement
2484
+ * about versions, and is often empty.
2226
2485
  *
2227
2486
  * A notice the plan is holding back carries `blockedReason`. The commonest
2228
2487
  * one is that no affected range names a fixed version, which only the people
2229
2488
  * who shipped the release can supply.
2230
2489
  */
2231
2490
  getAdvisory(publicId: string): Promise<AdvisoryDetail>;
2491
+ /**
2492
+ * Record which versions this advisory affects.
2493
+ *
2494
+ * Replaces the whole set, so send what is affected now rather than a patch.
2495
+ * `fixedIn` is the point: a patch notice stays blocked until some range
2496
+ * names a fixed version, and only the people who shipped the release know
2497
+ * it.
2498
+ *
2499
+ * Versions only. A range may name only software already on the advisory's
2500
+ * `software`, and anything else is a 400: which software an advisory
2501
+ * concerns decides who hears about it, and that is its own statement made
2502
+ * in the app.
2503
+ *
2504
+ * This call never sends anything. It records versions and recomputes the
2505
+ * plan; when an eligible notice is actually sent is the programme's
2506
+ * business.
2507
+ */
2508
+ replaceAdvisoryAffected(publicId: string, affected: AdvisoryAffectedInput[]): Promise<AdvisoryDetail>;
2509
+ /**
2510
+ * The programme's advisory contacts, oldest first.
2511
+ *
2512
+ * Needs `contacts:read`, which is held apart from `read`: this list is other
2513
+ * people's work addresses and the record of who learns about a vulnerability
2514
+ * before the public does. `software` on each row is what notices are matched
2515
+ * on. A project with no security programme reads as an empty list.
2516
+ */
2517
+ listAdvisoryContacts(opts?: {
2518
+ page?: number;
2519
+ limit?: number;
2520
+ tier?: ContactTier;
2521
+ status?: ContactStatus;
2522
+ }): Promise<Paginated<AdvisoryContact>>;
2523
+ /**
2524
+ * Put one address on the programme's advisory contact list.
2525
+ *
2526
+ * `software` says which of the project's repositories this contact runs, and
2527
+ * is required: it is what every notice is matched on, so a contact who runs
2528
+ * nothing is told nothing.
2529
+ *
2530
+ * The contact starts `PENDING_VERIFICATION`, and an unconfirmed address
2531
+ * receives nothing embargoed. Nothing is emailed by this call: the
2532
+ * confirmation mail is sent from the app.
2533
+ */
2534
+ addAdvisoryContact(contact: AdvisoryContactInput): Promise<AdvisoryContact>;
2232
2535
  /**
2233
2536
  * Reports the programme has received, newest first.
2234
2537
  *
@@ -2332,4 +2635,4 @@ declare class ZkaoClient {
2332
2635
  }): Promise<UsageMonthSummary[]>;
2333
2636
  }
2334
2637
 
2335
- 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 };
2638
+ 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, DEFAULT_BASE_URL, type Finding, type FindingDetail, type FindingNote, type LaunchScanRequest, type LaunchScanResult, type ManualAuditRequest, type ManualAuditResult, type Paginated, type PublishArtifactResult, type Report, type ReportStatus, 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
@@ -390,7 +390,12 @@ var ZkaoClient = class {
390
390
  return unwrap(res);
391
391
  }
392
392
  /**
393
- * One advisory, the versions it affects, and the notices planned for it.
393
+ * One advisory, the software it concerns, the versions it affects, and the
394
+ * notices planned for it.
395
+ *
396
+ * `software` is what decides the audience: a contact is notified about an
397
+ * advisory only when they run some of it. `affected` is a separate statement
398
+ * about versions, and is often empty.
394
399
  *
395
400
  * A notice the plan is holding back carries `blockedReason`. The commonest
396
401
  * one is that no affected range names a fixed version, which only the people
@@ -403,6 +408,76 @@ var ZkaoClient = class {
403
408
  );
404
409
  return unwrap(res).advisory;
405
410
  }
411
+ /**
412
+ * Record which versions this advisory affects.
413
+ *
414
+ * Replaces the whole set, so send what is affected now rather than a patch.
415
+ * `fixedIn` is the point: a patch notice stays blocked until some range
416
+ * names a fixed version, and only the people who shipped the release know
417
+ * it.
418
+ *
419
+ * Versions only. A range may name only software already on the advisory's
420
+ * `software`, and anything else is a 400: which software an advisory
421
+ * concerns decides who hears about it, and that is its own statement made
422
+ * in the app.
423
+ *
424
+ * This call never sends anything. It records versions and recomputes the
425
+ * plan; when an eligible notice is actually sent is the programme's
426
+ * business.
427
+ */
428
+ async replaceAdvisoryAffected(publicId, affected) {
429
+ const res = await this.http.PUT(
430
+ "/projects/{projectId}/advisories/{publicId}/affected",
431
+ {
432
+ params: { path: { ...this.path, publicId } },
433
+ body: { affected }
434
+ }
435
+ );
436
+ return unwrap(res).advisory;
437
+ }
438
+ /**
439
+ * The programme's advisory contacts, oldest first.
440
+ *
441
+ * Needs `contacts:read`, which is held apart from `read`: this list is other
442
+ * people's work addresses and the record of who learns about a vulnerability
443
+ * before the public does. `software` on each row is what notices are matched
444
+ * on. A project with no security programme reads as an empty list.
445
+ */
446
+ async listAdvisoryContacts(opts = {}) {
447
+ const res = await this.http.GET(
448
+ "/projects/{projectId}/advisory-contacts",
449
+ {
450
+ params: {
451
+ path: this.path,
452
+ query: {
453
+ page: opts.page,
454
+ limit: opts.limit,
455
+ tier: opts.tier,
456
+ status: opts.status
457
+ }
458
+ }
459
+ }
460
+ );
461
+ return unwrap(res);
462
+ }
463
+ /**
464
+ * Put one address on the programme's advisory contact list.
465
+ *
466
+ * `software` says which of the project's repositories this contact runs, and
467
+ * is required: it is what every notice is matched on, so a contact who runs
468
+ * nothing is told nothing.
469
+ *
470
+ * The contact starts `PENDING_VERIFICATION`, and an unconfirmed address
471
+ * receives nothing embargoed. Nothing is emailed by this call: the
472
+ * confirmation mail is sent from the app.
473
+ */
474
+ async addAdvisoryContact(contact) {
475
+ const res = await this.http.POST("/projects/{projectId}/advisory-contacts", {
476
+ params: { path: this.path },
477
+ body: contact
478
+ });
479
+ return unwrap(res).contact;
480
+ }
406
481
  // --- Incoming reports ---------------------------------------------------
407
482
  /**
408
483
  * Reports the programme has received, newest first.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zksecurity/zkao-sdk",
3
- "version": "0.15.0-next.10",
3
+ "version": "0.16.0-next.11",
4
4
  "description": "TypeScript SDK for the zkao Project API",
5
5
  "license": "MIT",
6
6
  "author": "zkSecurity",