@artifact-keeper/sdk 1.1.9-rc.1 → 1.2.1

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/src/types.gen.ts CHANGED
@@ -198,6 +198,14 @@ export type ArtifactLabelsListResponse = {
198
198
  };
199
199
 
200
200
  export type ArtifactListResponse = {
201
+ /**
202
+ * Maven component grouping. Only present when `group_by=maven_component`.
203
+ */
204
+ components?: Array<MavenComponentResponse> | null;
205
+ /**
206
+ * Docker tag grouping. Only present when `group_by=docker_tag`.
207
+ */
208
+ docker_tags?: Array<DockerTagResponse> | null;
201
209
  items: Array<ArtifactResponse>;
202
210
  pagination: Pagination;
203
211
  };
@@ -210,6 +218,21 @@ export type ArtifactMetadataResponse = {
210
218
  };
211
219
 
212
220
  export type ArtifactResponse = {
221
+ /**
222
+ * When the proxy cache entry for this artifact was last written.
223
+ * Only populated for Remote (proxy) repositories whose proxy service is
224
+ * configured AND that have a cache-metadata blob for this path. None
225
+ * for Local / Virtual / Staging repos and for Remote repos whose cache
226
+ * hasn't been populated yet (e.g. an artifact that exists as a DB row
227
+ * from a direct upload but has never been fetched through the proxy).
228
+ * (#1541)
229
+ */
230
+ cache_cached_at?: string | null;
231
+ /**
232
+ * When the proxy cache entry for this artifact will expire and be
233
+ * re-validated against upstream. Same gating as `cache_cached_at`. (#1541)
234
+ */
235
+ cache_expires_at?: string | null;
213
236
  checksum_sha256: string;
214
237
  content_type: string;
215
238
  created_at: string;
@@ -247,6 +270,14 @@ export type AssessmentResult = {
247
270
  };
248
271
 
249
272
  export type AssignRepoRequest = {
273
+ /**
274
+ * Optional JSONB filter constraining which artifacts in the repository
275
+ * get replicated. Shape: `{"include_patterns": ["^v\\d+\\."], "exclude_patterns": [".*-SNAPSHOT$"]}`.
276
+ * Null/absent means replicate everything.
277
+ */
278
+ replication_filter: {
279
+ [key: string]: unknown;
280
+ };
250
281
  replication_mode?: string | null;
251
282
  replication_schedule?: string | null;
252
283
  repository_id: string;
@@ -257,6 +288,25 @@ export type AssignRoleRequest = {
257
288
  role_id: string;
258
289
  };
259
290
 
291
+ /**
292
+ * Authentication provider availability.
293
+ */
294
+ export type AuthConfig = {
295
+ /**
296
+ * Whether an LDAP directory is configured.
297
+ */
298
+ ldap_enabled: boolean;
299
+ /**
300
+ * Whether an OIDC provider is configured.
301
+ */
302
+ oidc_enabled: boolean;
303
+ /**
304
+ * Whether SAML SSO is configured (derived from the SSO admin settings in the DB,
305
+ * but for this endpoint we report whether the OIDC issuer is set as a proxy).
306
+ */
307
+ sso_enabled: boolean;
308
+ };
309
+
260
310
  export type BackupListResponse = {
261
311
  items: Array<BackupResponse>;
262
312
  total: number;
@@ -384,7 +434,11 @@ export type BulkPromoteRequest = {
384
434
  artifact_ids: Array<string>;
385
435
  notes?: string | null;
386
436
  skip_policy_check?: boolean;
387
- target_repository: string;
437
+ /**
438
+ * Target release repository key. When omitted, the staging repository's
439
+ * linked release target (from `repository_config`) is used instead.
440
+ */
441
+ target_repository?: string | null;
388
442
  };
389
443
 
390
444
  export type BulkPromotionResponse = {
@@ -646,6 +700,19 @@ export type CreateConnectionRequest = {
646
700
  url: string;
647
701
  };
648
702
 
703
+ export type CreateEmailSubscriptionRequest = {
704
+ enabled?: boolean;
705
+ /**
706
+ * Event-type tokens to listen for. Must be drawn from `VALID_EVENT_TYPES`.
707
+ */
708
+ event_types: Array<string>;
709
+ /**
710
+ * Email addresses to deliver matching events to. Bounded length;
711
+ * see `MAX_RECIPIENTS_PER_SUBSCRIPTION` for the operator-facing limit.
712
+ */
713
+ recipients: Array<string>;
714
+ };
715
+
649
716
  export type CreateGateRequest = {
650
717
  action?: string;
651
718
  description?: string | null;
@@ -719,7 +786,17 @@ export type CreateOidcConfigRequest = {
719
786
  client_secret: string;
720
787
  is_enabled?: boolean | null;
721
788
  issuer_url: string;
789
+ /**
790
+ * When `true`, OIDC group claim values are reflected as Artifact Keeper
791
+ * group memberships (auto-creating groups on first sight). Defaults to
792
+ * `false` to preserve legacy role-mapping behavior.
793
+ */
794
+ map_groups_to_groups?: boolean | null;
722
795
  name: string;
796
+ /**
797
+ * Enable PKCE (S256) on the authorization request. Defaults to `true`.
798
+ */
799
+ pkce_enabled?: boolean | null;
723
800
  scopes?: Array<string> | null;
724
801
  };
725
802
 
@@ -733,7 +810,7 @@ export type CreatePermissionRequest = {
733
810
 
734
811
  export type CreatePolicyRequest = {
735
812
  block_on_fail: boolean;
736
- block_unscanned: boolean;
813
+ block_unscanned?: boolean;
737
814
  max_artifact_age_days?: number | null;
738
815
  max_severity: string;
739
816
  min_staging_hours?: number | null;
@@ -742,7 +819,51 @@ export type CreatePolicyRequest = {
742
819
  require_signature?: boolean;
743
820
  };
744
821
 
822
+ /**
823
+ * Request to create an access token scoped to a repository.
824
+ */
825
+ export type CreateRepoTokenRequest = {
826
+ /**
827
+ * Optional human-readable description.
828
+ */
829
+ description?: string | null;
830
+ /**
831
+ * Number of days until the token expires (1-365). Omit for no expiration.
832
+ */
833
+ expires_in_days?: number | null;
834
+ /**
835
+ * Display name for the token.
836
+ */
837
+ name: string;
838
+ /**
839
+ * Permission scopes for the token.
840
+ */
841
+ scopes: Array<string>;
842
+ };
843
+
844
+ /**
845
+ * Response returned when a repository token is created. The `token` field
846
+ * contains the plaintext value and is only shown once.
847
+ */
848
+ export type CreateRepoTokenResponse = {
849
+ id: string;
850
+ name: string;
851
+ repository_key: string;
852
+ /**
853
+ * The full token value (only returned at creation time).
854
+ */
855
+ token: string;
856
+ };
857
+
745
858
  export type CreateRepositoryRequest = {
859
+ /**
860
+ * Alias for `is_public`. When set to true, anonymous users can download
861
+ * artifacts from this repository without authentication. Useful for remote
862
+ * (pull-through cache) repositories that proxy public upstream registries.
863
+ * If both `is_public` and `allow_anonymous_access` are provided,
864
+ * `allow_anonymous_access` takes precedence.
865
+ */
866
+ allow_anonymous_access?: boolean | null;
746
867
  description?: string | null;
747
868
  format: string;
748
869
  /**
@@ -764,6 +885,12 @@ export type CreateRepositoryRequest = {
764
885
  */
765
886
  member_repos?: Array<CreateVirtualMemberInput> | null;
766
887
  name: string;
888
+ /**
889
+ * When true, direct user uploads to this repository are rejected:
890
+ * artifacts must arrive via the promotion path. Admin-only to set.
891
+ * Defaults to false (no behavior change for existing repositories).
892
+ */
893
+ promotion_only?: boolean | null;
767
894
  quota_bytes?: number | null;
768
895
  repo_type: string;
769
896
  /**
@@ -830,10 +957,36 @@ export type CreateServiceAccountRequest = {
830
957
  };
831
958
 
832
959
  export type CreateSessionRequest = {
960
+ /**
961
+ * Source artifact metadata for peer replication.
962
+ */
963
+ artifact_metadata?: unknown;
964
+ /**
965
+ * Source artifact metadata format for peer replication.
966
+ */
967
+ artifact_metadata_format?: string | null;
968
+ /**
969
+ * Source artifact metadata properties for peer replication.
970
+ */
971
+ artifact_metadata_properties?: unknown;
972
+ /**
973
+ * Artifact name to persist when the upload completes.
974
+ *
975
+ * Optional for regular client uploads. Peer replication sets this from
976
+ * the source artifact row so chunked replication preserves metadata.
977
+ */
978
+ artifact_name?: string | null;
833
979
  /**
834
980
  * Path within the repository (e.g. "images/vm.ova")
835
981
  */
836
982
  artifact_path: string;
983
+ /**
984
+ * Artifact version to persist when the upload completes.
985
+ *
986
+ * Optional for regular client uploads. Peer replication sets this from
987
+ * the source artifact row so chunked replication preserves metadata.
988
+ */
989
+ artifact_version?: string | null;
837
990
  /**
838
991
  * Expected SHA256 checksum of the complete file
839
992
  */
@@ -846,6 +999,14 @@ export type CreateSessionRequest = {
846
999
  * MIME content type (default "application/octet-stream")
847
1000
  */
848
1001
  content_type?: string | null;
1002
+ /**
1003
+ * Source package description for peer replication.
1004
+ */
1005
+ package_description?: string | null;
1006
+ /**
1007
+ * Source package catalog metadata for peer replication.
1008
+ */
1009
+ package_metadata?: unknown;
849
1010
  /**
850
1011
  * Repository key (e.g. "my-repo")
851
1012
  */
@@ -869,6 +1030,13 @@ export type CreateSyncPolicyPayload = {
869
1030
  };
870
1031
  description?: string;
871
1032
  enabled?: boolean;
1033
+ /**
1034
+ * Convenience glob filter (e.g. `"*.tar.gz"`). When set, it is folded
1035
+ * into `artifact_filter.include_paths` so only matching artifact paths
1036
+ * are eligible for sync. Ignored if `artifact_filter.include_paths` is
1037
+ * already provided.
1038
+ */
1039
+ filter?: string | null;
872
1040
  name: string;
873
1041
  peer_selector?: {
874
1042
  [key: string]: unknown;
@@ -931,12 +1099,27 @@ export type CreateVirtualMemberInput = {
931
1099
  };
932
1100
 
933
1101
  export type CreateWebhookRequest = {
1102
+ /**
1103
+ * Pinned event payload version. Defaults to "2026-04-01" when omitted.
1104
+ * Must match a value in `SUPPORTED_EVENT_VERSIONS` or the request is
1105
+ * rejected with HTTP 422.
1106
+ */
1107
+ event_schema_version?: string | null;
934
1108
  events: Array<string>;
935
1109
  headers?: {
936
1110
  [key: string]: unknown;
937
1111
  } | null;
938
1112
  name: string;
1113
+ /**
1114
+ * Payload layout for the target platform (default: generic).
1115
+ */
1116
+ payload_template?: PayloadTemplate;
939
1117
  repository_id?: string | null;
1118
+ /**
1119
+ * Optional caller-supplied secret. When omitted the server generates a
1120
+ * fresh `whsec_*` secret. Either way the raw value is returned in the
1121
+ * 201 response body exactly once and is unrecoverable thereafter.
1122
+ */
940
1123
  secret?: string | null;
941
1124
  url: string;
942
1125
  };
@@ -1006,17 +1189,47 @@ export type CveTimelineEntry = {
1006
1189
 
1007
1190
  /**
1008
1191
  * CVE trends summary.
1192
+ *
1193
+ * #1446: the security-tests `cve-history` suite probes the trends body for
1194
+ * any of `total`, `count`, `critical`, or `high` to confirm the response
1195
+ * carries aggregate counts (PR #1385 fixed `cve-history` but the trends
1196
+ * shape was not aligned). The original field set (`total_cves`,
1197
+ * `critical_count`, ...) is retained for openapi consumers; the bare
1198
+ * `total`/`critical`/`high`/`medium`/`low` aliases are added alongside so
1199
+ * both shape contracts are satisfied without breaking existing clients.
1200
+ * `#[serde(default)]` keeps deserialization working when the alias fields
1201
+ * are absent (older payloads, tests that build the struct via field init).
1009
1202
  */
1010
1203
  export type CveTrends = {
1011
1204
  acknowledged_cves: number;
1012
1205
  avg_days_to_fix?: number | null;
1206
+ /**
1207
+ * Alias of `critical_count` (#1446).
1208
+ */
1209
+ critical?: number;
1013
1210
  critical_count: number;
1014
1211
  fixed_cves: number;
1212
+ /**
1213
+ * Alias of `high_count` (#1446).
1214
+ */
1215
+ high?: number;
1015
1216
  high_count: number;
1217
+ /**
1218
+ * Alias of `low_count` (#1446).
1219
+ */
1220
+ low?: number;
1016
1221
  low_count: number;
1222
+ /**
1223
+ * Alias of `medium_count` (#1446).
1224
+ */
1225
+ medium?: number;
1017
1226
  medium_count: number;
1018
1227
  open_cves: number;
1019
1228
  timeline: Array<CveTimelineEntry>;
1229
+ /**
1230
+ * Alias of `total_cves` (#1446).
1231
+ */
1232
+ total?: number;
1020
1233
  total_cves: number;
1021
1234
  };
1022
1235
 
@@ -1074,6 +1287,79 @@ export type DiscoverablePeerResponse = {
1074
1287
  status: string;
1075
1288
  };
1076
1289
 
1290
+ /**
1291
+ * A Docker/OCI tag grouped by (image, tag).
1292
+ *
1293
+ * `total_size_bytes` is the server-side aggregation of the manifest body
1294
+ * plus every referenced layer blob. This is what the UI should display
1295
+ * as the on-disk image size; the previous client-side aggregation that
1296
+ * only summed the manifest body itself reported a few kilobytes for
1297
+ * images that are hundreds of megabytes on disk (artifact-keeper#1193).
1298
+ *
1299
+ * For multi-arch image indexes the size is the sum across all per-arch
1300
+ * child manifests recorded in `oci_manifest_refs`, so an `amd64+arm64`
1301
+ * index reports the combined storage cost.
1302
+ */
1303
+ export type DockerTagResponse = {
1304
+ /**
1305
+ * Representative manifest artifact ID.
1306
+ */
1307
+ id: string;
1308
+ /**
1309
+ * Image name (no registry host, no tag). Maps to the OCI v2 `<name>`
1310
+ * path segment, which may include slashes (e.g. `library/postgres`).
1311
+ */
1312
+ image: string;
1313
+ /**
1314
+ * Whether this manifest is a multi-arch image index.
1315
+ */
1316
+ is_index: boolean;
1317
+ /**
1318
+ * Last push (or update) timestamp from the underlying `oci_tags` row.
1319
+ */
1320
+ last_pushed_at: string;
1321
+ /**
1322
+ * Number of layer blobs referenced by the manifest. For image indexes
1323
+ * this is the sum of layer counts across child manifests. `0` when
1324
+ * the manifest could not be parsed.
1325
+ */
1326
+ layer_count: number;
1327
+ /**
1328
+ * Manifest content digest (e.g. `sha256:abcdef...`).
1329
+ */
1330
+ manifest_digest: string;
1331
+ /**
1332
+ * Repository key this tag belongs to.
1333
+ */
1334
+ repository_key: string;
1335
+ /**
1336
+ * Rolled-up scan status across all scanners configured for this
1337
+ * artifact. `None` when the artifact has never been scanned.
1338
+ *
1339
+ * Values surface the aggregate state, not a single scanner's row
1340
+ * (see #1497). One of:
1341
+ *
1342
+ * * `pending` / `running` -- at least one scanner is still in flight
1343
+ * * `completed` -- every per-scan-type latest row is `completed`
1344
+ * * `failed` -- every per-scan-type latest row is `failed`
1345
+ * * `partial` -- mixed: at least one `completed` AND at least one
1346
+ * `failed`. A green generic scanner (e.g. grype) no longer hides
1347
+ * a failed format-native scanner (e.g. incus) behind a
1348
+ * `completed` label.
1349
+ */
1350
+ scan_status?: string | null;
1351
+ /**
1352
+ * Tag string (e.g. `16-alpine`). Never a `sha256:...` digest;
1353
+ * digest-only references are filtered out of the grouping.
1354
+ */
1355
+ tag: string;
1356
+ /**
1357
+ * Total size in bytes of the manifest plus all referenced layer blobs.
1358
+ * For image indexes, this sums across child manifests.
1359
+ */
1360
+ total_size_bytes: number;
1361
+ };
1362
+
1077
1363
  /**
1078
1364
  * Download trend data point.
1079
1365
  */
@@ -1275,8 +1561,31 @@ export type DtProjectMetrics = {
1275
1561
  vulnerabilities?: number | null;
1276
1562
  };
1277
1563
 
1564
+ /**
1565
+ * Dependency-Track integration status surfaced to the frontend.
1566
+ *
1567
+ * `healthy` is the boolean the existing UI already binds to. The new
1568
+ * `error_status` and `error_message` fields let the UI distinguish a
1569
+ * genuine "DT replied OK with no findings" state from "DT is down or
1570
+ * misconfigured" (issue #963). When `healthy = true` both error fields
1571
+ * are None; when `healthy = false`:
1572
+ * - `error_status = Some(401)`: auth failure (check API key)
1573
+ * - `error_status = Some(5xx)`: upstream is broken
1574
+ * - `error_status = None`: transport failure (DT pod unreachable)
1575
+ * - `error_message`: operator-facing failure description
1576
+ */
1278
1577
  export type DtStatusResponse = {
1279
1578
  enabled: boolean;
1579
+ /**
1580
+ * Human-readable explanation when `healthy = false`. Safe to surface
1581
+ * in the UI; does not leak credentials.
1582
+ */
1583
+ error_message?: string | null;
1584
+ /**
1585
+ * Upstream HTTP status if the health probe got a response, else None.
1586
+ * Only populated when `healthy = false`.
1587
+ */
1588
+ error_status?: number | null;
1280
1589
  healthy: boolean;
1281
1590
  url?: string | null;
1282
1591
  };
@@ -1295,6 +1604,20 @@ export type DtVulnerability = {
1295
1604
  vulnId: string;
1296
1605
  };
1297
1606
 
1607
+ export type EmailSubscriptionListResponse = {
1608
+ subscriptions: Array<EmailSubscriptionResponse>;
1609
+ };
1610
+
1611
+ export type EmailSubscriptionResponse = {
1612
+ created_at: string;
1613
+ enabled: boolean;
1614
+ event_types: Array<string>;
1615
+ id: string;
1616
+ recipients: Array<string>;
1617
+ repository_id?: string | null;
1618
+ updated_at: string;
1619
+ };
1620
+
1298
1621
  /**
1299
1622
  * Standard error response body returned by all endpoints on failure.
1300
1623
  */
@@ -1371,6 +1694,13 @@ export type FindingResponse = {
1371
1694
  title: string;
1372
1695
  };
1373
1696
 
1697
+ /**
1698
+ * Response for force password change
1699
+ */
1700
+ export type ForcePasswordChangeResponse = {
1701
+ message: string;
1702
+ };
1703
+
1374
1704
  /**
1375
1705
  * Format handler response with additional computed fields.
1376
1706
  */
@@ -1517,7 +1847,7 @@ export type GrowthSummary = {
1517
1847
  export type HealthChecks = {
1518
1848
  database: CheckStatus;
1519
1849
  ldap?: null | CheckStatus;
1520
- meilisearch?: null | CheckStatus;
1850
+ opensearch?: null | CheckStatus;
1521
1851
  security_scanner?: null | CheckStatus;
1522
1852
  storage: CheckStatus;
1523
1853
  };
@@ -1584,6 +1914,23 @@ export type InstallFromLocalRequest = {
1584
1914
  path: string;
1585
1915
  };
1586
1916
 
1917
+ export type InvalidateCacheQuery = {
1918
+ /**
1919
+ * Artifact path to evict from the proxy cache. Same shape as the path
1920
+ * segment of `GET /api/v1/repositories/{key}/artifacts/{path}`.
1921
+ * Path-traversal segments such as `..` are rejected by
1922
+ * `ProxyService::cache_storage_key` (covered by
1923
+ * `test_invalidate_cache_by_key_rejects_invalid_path`).
1924
+ */
1925
+ path: string;
1926
+ };
1927
+
1928
+ export type InvalidateCacheResponse = {
1929
+ invalidated: boolean;
1930
+ path: string;
1931
+ repository_key: string;
1932
+ };
1933
+
1587
1934
  export type IssueResponse = {
1588
1935
  artifact_id: string;
1589
1936
  category: string;
@@ -1701,6 +2048,19 @@ export type LifecyclePolicy = {
1701
2048
  };
1702
2049
 
1703
2050
  export type ListArtifactsQuery = {
2051
+ /**
2052
+ * Server-side artifact grouping.
2053
+ *
2054
+ * Supported values:
2055
+ * - `maven_component`: Maven/Gradle artifacts are grouped by
2056
+ * groupId, artifactId, and version. Individual files (jar, pom,
2057
+ * checksums) appear in the `artifact_files` array of each component.
2058
+ * - `docker_tag`: Docker/OCI artifacts are grouped by (image, tag),
2059
+ * with `total_size_bytes` summed across the manifest config and
2060
+ * referenced layer blobs. The grouped rows are returned in the
2061
+ * `docker_tags` array.
2062
+ */
2063
+ group_by?: string | null;
1704
2064
  page?: number | null;
1705
2065
  path_prefix?: string | null;
1706
2066
  per_page?: number | null;
@@ -1802,6 +2162,55 @@ export type MatchedRepoSchema = {
1802
2162
  key: string;
1803
2163
  };
1804
2164
 
2165
+ /**
2166
+ * A Maven component grouped by GAV (groupId, artifactId, version).
2167
+ *
2168
+ * Each component collects the individual files (jar, pom, checksums, etc.)
2169
+ * that share the same Maven coordinates.
2170
+ */
2171
+ export type MavenComponentResponse = {
2172
+ /**
2173
+ * Individual filenames belonging to this component.
2174
+ */
2175
+ artifact_files: Array<string>;
2176
+ /**
2177
+ * Maven artifactId (e.g. `junit-jupiter-api`).
2178
+ */
2179
+ artifact_id: string;
2180
+ /**
2181
+ * Earliest creation timestamp among the component files.
2182
+ */
2183
+ created_at: string;
2184
+ /**
2185
+ * Total download count across all files in this component.
2186
+ */
2187
+ download_count: number;
2188
+ /**
2189
+ * Repository format (always `maven` or `gradle`).
2190
+ */
2191
+ format: string;
2192
+ /**
2193
+ * Maven groupId with dots (e.g. `org.junit.jupiter`).
2194
+ */
2195
+ group_id: string;
2196
+ /**
2197
+ * Representative artifact ID (the first file in the group).
2198
+ */
2199
+ id: string;
2200
+ /**
2201
+ * Repository key this component belongs to.
2202
+ */
2203
+ repository_key: string;
2204
+ /**
2205
+ * Total size in bytes across all files in this component.
2206
+ */
2207
+ size_bytes: number;
2208
+ /**
2209
+ * Maven version string (e.g. `5.11.0`).
2210
+ */
2211
+ version: string;
2212
+ };
2213
+
1805
2214
  export type MembersRequest = {
1806
2215
  user_ids: Array<string>;
1807
2216
  };
@@ -1928,6 +2337,83 @@ export type NetworkProfileBody = {
1928
2337
  sync_window_timezone?: string | null;
1929
2338
  };
1930
2339
 
2340
+ /**
2341
+ * Read-only OCI blob storage footprint report (issue #1408).
2342
+ *
2343
+ * This is a **reporting-only** view. It performs no deletion and takes no
2344
+ * locks. It surfaces how much storage the tracked `oci_blobs` rows
2345
+ * account for so operators can see the magnitude of un-reclaimed blob
2346
+ * layers before any garbage-collection mechanism is enabled.
2347
+ *
2348
+ * It deliberately does NOT attempt to classify which blobs are
2349
+ * "reclaimable orphans": that requires a manifest -> blob reference table
2350
+ * that does not yet exist in the schema, and any per-`(repository_id,
2351
+ * digest)` orphan heuristic would mis-handle the cross-repo dedup case
2352
+ * (multiple `oci_blobs` rows, one physical object) and report in-use
2353
+ * blobs as reclaimable. The numbers here are exact aggregates only.
2354
+ */
2355
+ export type OciBlobFootprintReport = {
2356
+ /**
2357
+ * Distinct digests older than `grace_hours` (eligible to be *considered*
2358
+ * by a future GC sweep once a reference table exists). Reporting only.
2359
+ */
2360
+ aged_distinct_digests: number;
2361
+ /**
2362
+ * Physical bytes (distinct-digest) older than `grace_hours`.
2363
+ */
2364
+ aged_physical_bytes: number;
2365
+ /**
2366
+ * Number of distinct blob digests (content-addressed identities). When
2367
+ * this is smaller than `total_blob_rows`, the difference is cross-repo
2368
+ * deduplication: rows that share one physical storage object.
2369
+ */
2370
+ distinct_digests: number;
2371
+ /**
2372
+ * Grace window (hours) applied to the `aged_*` figures below.
2373
+ */
2374
+ grace_hours: number;
2375
+ /**
2376
+ * Sum of `size_bytes` over every `oci_blobs` row. Double-counts
2377
+ * deduplicated blobs once per referencing repository.
2378
+ */
2379
+ logical_bytes: number;
2380
+ /**
2381
+ * Per-repository logical footprint, largest `logical_bytes` first.
2382
+ */
2383
+ per_repository: Array<OciBlobRepoFootprint>;
2384
+ /**
2385
+ * Sum of `size_bytes` counting each distinct digest exactly once. This
2386
+ * approximates the physical bytes occupied in the storage backend.
2387
+ */
2388
+ physical_bytes: number;
2389
+ /**
2390
+ * Total number of `oci_blobs` rows across all repositories.
2391
+ */
2392
+ total_blob_rows: number;
2393
+ };
2394
+
2395
+ /**
2396
+ * Per-repository row in the OCI blob footprint report.
2397
+ */
2398
+ export type OciBlobRepoFootprint = {
2399
+ /**
2400
+ * Number of `oci_blobs` rows attributed to this repository.
2401
+ */
2402
+ blob_rows: number;
2403
+ /**
2404
+ * Sum of `oci_blobs.size_bytes` for this repository's rows. Because OCI
2405
+ * blob storage is content-addressed and deduplicated across repos, the
2406
+ * same physical bytes can be counted under more than one repository
2407
+ * here; see [`OciBlobFootprintReport::physical_bytes`] for the
2408
+ * dedup-aware total.
2409
+ */
2410
+ logical_bytes: number;
2411
+ /**
2412
+ * Repository id owning these `oci_blobs` rows.
2413
+ */
2414
+ repository_id: string;
2415
+ };
2416
+
1931
2417
  export type OidcConfigResponse = {
1932
2418
  attribute_mapping: {
1933
2419
  [key: string]: unknown;
@@ -1939,7 +2425,9 @@ export type OidcConfigResponse = {
1939
2425
  id: string;
1940
2426
  is_enabled: boolean;
1941
2427
  issuer_url: string;
2428
+ map_groups_to_groups: boolean;
1942
2429
  name: string;
2430
+ pkce_enabled: boolean;
1943
2431
  scopes: Array<string>;
1944
2432
  updated_at: string;
1945
2433
  };
@@ -2040,6 +2528,15 @@ export type PaginationInfo = {
2040
2528
  total_pages: number;
2041
2529
  };
2042
2530
 
2531
+ /**
2532
+ * Supported webhook payload templates.
2533
+ *
2534
+ * Controls how the outgoing JSON body is structured when delivering a
2535
+ * webhook. The `Generic` variant preserves backward compatibility with the
2536
+ * original flat JSON format.
2537
+ */
2538
+ export type PayloadTemplate = 'generic' | 'slack' | 'microsoft_teams' | 'discord' | 'mattermost';
2539
+
2043
2540
  export type PeerInstanceListResponse = {
2044
2541
  items: Array<PeerInstanceResponse>;
2045
2542
  total: number;
@@ -2139,6 +2636,23 @@ export type PermissionRow = {
2139
2636
  updated_at: string;
2140
2637
  };
2141
2638
 
2639
+ /**
2640
+ * Fine-grained permissions enforcement status.
2641
+ */
2642
+ export type PermissionsConfig = {
2643
+ /**
2644
+ * Whether those rules are actively enforced on API requests.
2645
+ * The permission-check middleware and handler guards are wired in,
2646
+ * so this is `true` when the server is running.
2647
+ */
2648
+ enforcement_enabled: boolean;
2649
+ /**
2650
+ * Whether the permissions table (from migration 018) has any rows.
2651
+ * When true, an administrator has configured permission rules.
2652
+ */
2653
+ rules_exist: boolean;
2654
+ };
2655
+
2142
2656
  export type PluginConfigResponse = {
2143
2657
  config: {
2144
2658
  [key: string]: unknown;
@@ -2181,6 +2695,26 @@ export type PluginResponse = {
2181
2695
  version: string;
2182
2696
  };
2183
2697
 
2698
+ /**
2699
+ * Plugin signature-verification (supply-chain) policy status.
2700
+ *
2701
+ * Exposes only booleans — never the trusted key material itself — so frontends
2702
+ * and operators can see whether unsigned plugin installs are rejected and
2703
+ * whether a trusted publisher key has been provisioned.
2704
+ */
2705
+ export type PluginSigningConfig = {
2706
+ /**
2707
+ * Whether a valid signature is required to install a WASM plugin.
2708
+ */
2709
+ required: boolean;
2710
+ /**
2711
+ * Whether an operator trusted public key has been configured. When
2712
+ * `required` is true but this is false, every install is rejected
2713
+ * (fail-closed).
2714
+ */
2715
+ trusted_key_configured: boolean;
2716
+ };
2717
+
2184
2718
  /**
2185
2719
  * Plugin status
2186
2720
  */
@@ -2278,8 +2812,12 @@ export type ProbeBody = {
2278
2812
  export type PromoteArtifactRequest = {
2279
2813
  notes?: string | null;
2280
2814
  skip_policy_check?: boolean;
2281
- target_repository: string;
2282
- };
2815
+ /**
2816
+ * Target release repository key. When omitted, the staging repository's
2817
+ * linked release target (from `repository_config`) is used instead.
2818
+ */
2819
+ target_repository?: string | null;
2820
+ };
2283
2821
 
2284
2822
  export type PromotionHistoryEntry = {
2285
2823
  artifact_id: string;
@@ -2341,6 +2879,50 @@ export type PromotionRuleResponse = {
2341
2879
  updated_at: string;
2342
2880
  };
2343
2881
 
2882
+ /**
2883
+ * Body for declaring that a locally-owned PyPI project tracks an upstream one.
2884
+ */
2885
+ export type PypiTrackRequest = {
2886
+ /**
2887
+ * Upstream Simple index project URL this local project tracks, e.g.
2888
+ * `https://pypi.org/simple/acme-sdk/`. Recorded and emitted as the PEP 708
2889
+ * `tracks` value.
2890
+ */
2891
+ tracks_url: string;
2892
+ };
2893
+
2894
+ /**
2895
+ * A single PEP 708 `tracks` declaration.
2896
+ */
2897
+ export type PypiTrackResponse = {
2898
+ /**
2899
+ * PEP 503 normalized project name.
2900
+ */
2901
+ normalized_name: string;
2902
+ repository_key: string;
2903
+ tracks_url: string;
2904
+ };
2905
+
2906
+ /**
2907
+ * All `tracks` declarations on a repository.
2908
+ */
2909
+ export type PypiTracksListResponse = {
2910
+ items: Array<PypiTrackResponse>;
2911
+ };
2912
+
2913
+ export type QuarantineActionResponse = {
2914
+ artifact_id: string;
2915
+ message: string;
2916
+ new_status: string;
2917
+ };
2918
+
2919
+ export type QuarantineStatusResponse = {
2920
+ artifact_id: string;
2921
+ is_blocked: boolean;
2922
+ quarantine_status?: string | null;
2923
+ quarantine_until?: string | null;
2924
+ };
2925
+
2344
2926
  export type QuickSearchResponse = {
2345
2927
  results: Array<SearchResultItem>;
2346
2928
  };
@@ -2392,6 +2974,13 @@ export type RejectArtifactRequest = {
2392
2974
  reason: string;
2393
2975
  };
2394
2976
 
2977
+ export type RejectRequest = {
2978
+ /**
2979
+ * Optional reason for rejection.
2980
+ */
2981
+ reason?: string | null;
2982
+ };
2983
+
2395
2984
  export type RejectionResponse = {
2396
2985
  artifact_id: string;
2397
2986
  reason: string;
@@ -2400,6 +2989,21 @@ export type RejectionResponse = {
2400
2989
  source: string;
2401
2990
  };
2402
2991
 
2992
+ export type ReleaseTargetResponse = {
2993
+ /**
2994
+ * Whether this staging repository has a linked release target.
2995
+ */
2996
+ linked: boolean;
2997
+ /**
2998
+ * The release repository ID, if linked.
2999
+ */
3000
+ release_repository_id?: string | null;
3001
+ /**
3002
+ * The release repository key, if linked.
3003
+ */
3004
+ release_repository_key?: string | null;
3005
+ };
3006
+
2403
3007
  export type RemoteInstanceResponse = {
2404
3008
  created_at: string;
2405
3009
  id: string;
@@ -2436,6 +3040,30 @@ export type RepoSelectorSchema = {
2436
3040
  match_repos?: Array<string>;
2437
3041
  };
2438
3042
 
3043
+ /**
3044
+ * List of tokens configured on a repository.
3045
+ */
3046
+ export type RepoTokenListResponse = {
3047
+ items: Array<RepoTokenResponse>;
3048
+ };
3049
+
3050
+ /**
3051
+ * Summary of a repository-scoped token.
3052
+ */
3053
+ export type RepoTokenResponse = {
3054
+ created_at: string;
3055
+ created_by?: string | null;
3056
+ description?: string | null;
3057
+ expires_at?: string | null;
3058
+ id: string;
3059
+ is_expired: boolean;
3060
+ is_revoked: boolean;
3061
+ last_used_at?: string | null;
3062
+ name: string;
3063
+ scopes: Array<string>;
3064
+ token_prefix: string;
3065
+ };
3066
+
2439
3067
  export type RepositoryAssessment = {
2440
3068
  artifact_count: number;
2441
3069
  compatibility: string;
@@ -2452,6 +3080,12 @@ export type RepositoryListResponse = {
2452
3080
  };
2453
3081
 
2454
3082
  export type RepositoryResponse = {
3083
+ /**
3084
+ * Whether anonymous (unauthenticated) downloads are allowed. This is
3085
+ * always equal to `is_public` and provided as a convenience alias so
3086
+ * the semantics are clear for remote (pull-through cache) repositories.
3087
+ */
3088
+ allow_anonymous_access: boolean;
2455
3089
  created_at: string;
2456
3090
  description?: string | null;
2457
3091
  format: string;
@@ -2459,6 +3093,21 @@ export type RepositoryResponse = {
2459
3093
  is_public: boolean;
2460
3094
  key: string;
2461
3095
  name: string;
3096
+ /**
3097
+ * When true, direct user uploads are rejected; artifacts must be promoted.
3098
+ */
3099
+ promotion_only: boolean;
3100
+ /**
3101
+ * Configured quarantine hold duration in minutes, read back from
3102
+ * `repository_config` (#1770 B). `None` when unset.
3103
+ */
3104
+ quarantine_duration_minutes?: number | null;
3105
+ /**
3106
+ * Whether the Package Age / quarantine policy is enabled for this
3107
+ * repository, read back from `repository_config` (#1770 B). `None` when
3108
+ * the repository has no explicit setting (the global default applies).
3109
+ */
3110
+ quarantine_enabled?: boolean | null;
2462
3111
  quota_bytes?: number | null;
2463
3112
  repo_type: string;
2464
3113
  storage_used_bytes: number;
@@ -2509,6 +3158,30 @@ export type RepositoryStorageBreakdown = {
2509
3158
  storage_bytes: number;
2510
3159
  };
2511
3160
 
3161
+ export type RescanForInventoryRequest = {
3162
+ /**
3163
+ * Maximum number of artifacts to enqueue in this call. Operators
3164
+ * run the endpoint repeatedly to drain large backfills without
3165
+ * stalling a single HTTP worker; the handler returns the actual
3166
+ * number enqueued so the caller can detect when work is done.
3167
+ * Defaults to 100. Hard-capped at 1000 to avoid pathological inputs.
3168
+ */
3169
+ limit?: number | null;
3170
+ };
3171
+
3172
+ export type RescanForInventoryResponse = {
3173
+ /**
3174
+ * Number of artifacts whose latest scan had no inventory rows and
3175
+ * for which a rescan was enqueued in this call.
3176
+ */
3177
+ artifacts_enqueued: number;
3178
+ /**
3179
+ * Echo of the requested (or defaulted) limit, useful for clients
3180
+ * driving the loop programmatically.
3181
+ */
3182
+ limit: number;
3183
+ };
3184
+
2512
3185
  /**
2513
3186
  * Response for password reset
2514
3187
  */
@@ -2546,6 +3219,43 @@ export type RoleResponse = {
2546
3219
  permissions: Array<string>;
2547
3220
  };
2548
3221
 
3222
+ /**
3223
+ * Response returned by the rotate-secret endpoint.
3224
+ */
3225
+ export type RotateWebhookSecretResponse = {
3226
+ id: string;
3227
+ /**
3228
+ * When the previously active secret stops being accepted.
3229
+ */
3230
+ previous_secret_expires_at: string;
3231
+ /**
3232
+ * Raw signing secret produced by this rotation. Shown exactly once.
3233
+ */
3234
+ secret: string;
3235
+ secret_digest: string;
3236
+ };
3237
+
3238
+ /**
3239
+ * A single routing rule that maps an incoming path to a rewritten path.
3240
+ */
3241
+ export type RoutingRule = {
3242
+ /**
3243
+ * Regex pattern matched against the full request path.
3244
+ * Use capture groups to extract portions for the rewrite template.
3245
+ */
3246
+ path_pattern: string;
3247
+ /**
3248
+ * Rewrite template. Use `$1`, `$2`, etc. to reference captured groups
3249
+ * from `path_pattern`.
3250
+ */
3251
+ rewrite_to: string;
3252
+ };
3253
+
3254
+ export type RoutingRulesResponse = {
3255
+ repository_key: string;
3256
+ rules: Array<RoutingRule>;
3257
+ };
3258
+
2549
3259
  export type RuleEvaluationResponse = {
2550
3260
  passed: boolean;
2551
3261
  rule_id: string;
@@ -2568,6 +3278,14 @@ export type RuleResponse = {
2568
3278
  version_constraint: string;
2569
3279
  };
2570
3280
 
3281
+ /**
3282
+ * Result of `POST /:id/repositories/:repo_id/sync` (run-now trigger).
3283
+ */
3284
+ export type RunNowResponse = {
3285
+ status: string;
3286
+ tasks_queued: number;
3287
+ };
3288
+
2571
3289
  export type SamlAcsForm = {
2572
3290
  RelayState?: string | null;
2573
3291
  SAMLResponse: string;
@@ -2646,15 +3364,47 @@ export type ScanResponse = {
2646
3364
  high_count: number;
2647
3365
  id: string;
2648
3366
  info_count: number;
3367
+ /**
3368
+ * True when the row was synthesized by the dedup path (`copy_scan_results`)
3369
+ * because a prior scan with the same `(checksum_sha256, scan_type)` pair
3370
+ * already existed within the dedup TTL. No scanner was actually invoked
3371
+ * for this row; counts and findings were copied from `source_scan_id`.
3372
+ */
3373
+ is_reused: boolean;
2649
3374
  low_count: number;
2650
3375
  medium_count: number;
2651
3376
  repository_id: string;
2652
3377
  scan_type: string;
2653
3378
  scanner_version?: string | null;
3379
+ /**
3380
+ * When `is_reused` is true, the `id` of the source scan whose results
3381
+ * were copied. Useful for distinguishing "fresh scan" from "deduped
3382
+ * satisfaction" in release-gate provenance checks. None for original
3383
+ * (non-reused) scans.
3384
+ */
3385
+ source_scan_id?: string | null;
2654
3386
  started_at?: string | null;
2655
3387
  status: string;
2656
3388
  };
2657
3389
 
3390
+ /**
3391
+ * Scanner availability flags.
3392
+ */
3393
+ export type ScannersConfig = {
3394
+ /**
3395
+ * Whether the Dependency-Track integration is configured.
3396
+ */
3397
+ dependency_track_enabled: boolean;
3398
+ /**
3399
+ * Whether the OpenSCAP compliance scanner is configured.
3400
+ */
3401
+ openscap_enabled: boolean;
3402
+ /**
3403
+ * Whether the Trivy vulnerability scanner is configured.
3404
+ */
3405
+ trivy_enabled: boolean;
3406
+ };
3407
+
2658
3408
  export type ScoreResponse = {
2659
3409
  acknowledged_count: number;
2660
3410
  calculated_at: string;
@@ -2759,6 +3509,22 @@ export type SetPeerLabelsRequest = {
2759
3509
  labels: Array<PeerLabelEntrySchema>;
2760
3510
  };
2761
3511
 
3512
+ export type SetReleaseTargetRequest = {
3513
+ /**
3514
+ * Repository key of the release (local) repository to link.
3515
+ * Pass `null` or omit to remove the link.
3516
+ */
3517
+ release_repository_key?: string | null;
3518
+ };
3519
+
3520
+ export type SetRoutingRulesRequest = {
3521
+ /**
3522
+ * Ordered list of routing rules. Each rule specifies a regex pattern and
3523
+ * a rewrite template. Rules are evaluated in order during proxy requests.
3524
+ */
3525
+ rules: Array<RoutingRule>;
3526
+ };
3527
+
2762
3528
  /**
2763
3529
  * Response body for the setup status endpoint.
2764
3530
  */
@@ -2798,6 +3564,33 @@ export type SigningKeyPublic = {
2798
3564
  uid_name?: string | null;
2799
3565
  };
2800
3566
 
3567
+ /**
3568
+ * Request body for the SMTP test endpoint.
3569
+ */
3570
+ export type SmtpTestRequest = {
3571
+ /**
3572
+ * Recipient email address for the test message.
3573
+ *
3574
+ * Accepts `recipient` as an alias for backward compatibility with Web UI
3575
+ * versions <= 1.1.3, which send `{"recipient": "..."}`.
3576
+ */
3577
+ to: string;
3578
+ };
3579
+
3580
+ /**
3581
+ * Response from the SMTP test endpoint.
3582
+ */
3583
+ export type SmtpTestResponse = {
3584
+ /**
3585
+ * Human-readable status message.
3586
+ */
3587
+ message: string;
3588
+ /**
3589
+ * Whether the test email was sent successfully.
3590
+ */
3591
+ success: boolean;
3592
+ };
3593
+
2801
3594
  export type SourceConnectionRow = {
2802
3595
  auth_type: string;
2803
3596
  created_at: string;
@@ -2900,6 +3693,23 @@ export type SubmitResponse = {
2900
3693
  marked_submitted: number;
2901
3694
  };
2902
3695
 
3696
+ /**
3697
+ * Detailed subscription view (mode, schedule, filter) for a single (peer, repo) pair.
3698
+ */
3699
+ export type SubscriptionResponse = {
3700
+ created_at: string;
3701
+ id: string;
3702
+ last_replicated_at?: string | null;
3703
+ peer_instance_id: string;
3704
+ replication_filter: {
3705
+ [key: string]: unknown;
3706
+ };
3707
+ replication_mode?: string | null;
3708
+ replication_schedule?: string | null;
3709
+ repository_id: string;
3710
+ sync_enabled: boolean;
3711
+ };
3712
+
2903
3713
  export type SuggestResponse = {
2904
3714
  suggestions: Array<string>;
2905
3715
  };
@@ -2925,6 +3735,12 @@ export type SyncPolicyResponse = {
2925
3735
  created_at: string;
2926
3736
  description: string;
2927
3737
  enabled: boolean;
3738
+ /**
3739
+ * Convenience glob filter, mirrored from `artifact_filter.include_paths`.
3740
+ * Round-trips the single-pattern shorthand accepted on create
3741
+ * (e.g. `"*.tar.gz"`). Empty when no include pattern is set.
3742
+ */
3743
+ filter: string;
2928
3744
  id: string;
2929
3745
  name: string;
2930
3746
  peer_selector: {
@@ -2942,11 +3758,82 @@ export type SyncPolicyResponse = {
2942
3758
  export type SyncTaskResponse = {
2943
3759
  artifact_id: string;
2944
3760
  artifact_size: number;
3761
+ /**
3762
+ * When the task was enqueued. Lets clients tell a freshly-scheduled task
3763
+ * apart from a stale queue entry (used by the replication-schedule check).
3764
+ * Serialized as whole-second RFC3339 with a `Z` suffix
3765
+ * (e.g. `2026-05-29T12:34:56Z`) so simple ISO8601 parsers can consume it.
3766
+ */
3767
+ created_at: string;
2945
3768
  id: string;
2946
3769
  priority: number;
3770
+ /**
3771
+ * When the worker began transferring, if it has started. Same format as
3772
+ * `created_at`.
3773
+ */
3774
+ started_at?: string | null;
3775
+ /**
3776
+ * Task status (e.g. "pending"). Listing currently returns pending tasks.
3777
+ */
3778
+ status: string;
2947
3779
  storage_key: string;
2948
3780
  };
2949
3781
 
3782
+ /**
3783
+ * Public runtime configuration values.
3784
+ *
3785
+ * This response intentionally omits all secrets, credentials, and internal
3786
+ * connection strings. Only values useful for UI/client behavior are included.
3787
+ */
3788
+ export type SystemConfigResponse = {
3789
+ /**
3790
+ * Authentication provider availability.
3791
+ */
3792
+ auth: AuthConfig;
3793
+ /**
3794
+ * Whether the instance is running in demo mode (writes blocked).
3795
+ */
3796
+ demo_mode: boolean;
3797
+ /**
3798
+ * Whether anonymous (unauthenticated) access is permitted at all (issue #850).
3799
+ * When `false`, the server rejects all unauthenticated requests except for
3800
+ * the login, setup, health, and OCI challenge endpoints. Frontends should
3801
+ * hide UI affordances that imply public access (e.g. the "public repo"
3802
+ * toggle) and redirect unauthenticated users to the login page.
3803
+ */
3804
+ guest_access_enabled: boolean;
3805
+ /**
3806
+ * Maximum upload size in bytes (0 means no limit).
3807
+ */
3808
+ max_upload_size_bytes: number;
3809
+ /**
3810
+ * OIDC issuer URL, if configured. This is public information needed by
3811
+ * clients to initiate the OIDC flow.
3812
+ */
3813
+ oidc_issuer?: string | null;
3814
+ /**
3815
+ * Fine-grained permissions enforcement status. Permission rules can be
3816
+ * managed via /api/v1/permissions and are actively enforced.
3817
+ */
3818
+ permissions: PermissionsConfig;
3819
+ /**
3820
+ * Plugin signature-verification (supply-chain) policy status.
3821
+ */
3822
+ plugin_signing: PluginSigningConfig;
3823
+ /**
3824
+ * Scanner availability.
3825
+ */
3826
+ scanners: ScannersConfig;
3827
+ /**
3828
+ * Search engine type: "opensearch" when configured, "database" otherwise.
3829
+ */
3830
+ search_engine: string;
3831
+ /**
3832
+ * Storage backend type (e.g. "filesystem", "s3", "gcs", "azure").
3833
+ */
3834
+ storage_backend: string;
3835
+ };
3836
+
2950
3837
  export type SystemSettings = {
2951
3838
  allow_anonymous_download: boolean;
2952
3839
  audit_retention_days: number;
@@ -3134,12 +4021,45 @@ export type TriggerChecksResponse = {
3134
4021
 
3135
4022
  export type TriggerScanRequest = {
3136
4023
  artifact_id?: string | null;
4024
+ /**
4025
+ * Skip the hash-based scan dedup short-circuit when running this scan.
4026
+ *
4027
+ * Defaults to `false`. Normal trigger calls dedup against prior
4028
+ * completed scans for the same checksum + scan_type so a freshly
4029
+ * uploaded byte-identical artifact reuses the existing result instead
4030
+ * of re-running the scanner. When `true`, that dedup is skipped: the
4031
+ * scanner runs against the bytes again and writes a fresh
4032
+ * `scan_results` row. Use this to recover from a silently-broken
4033
+ * prior scan (e.g. an extraction bug producing a completed,
4034
+ * zero-finding row that masks the real findings until the dedup TTL
4035
+ * expires; see #1469). Costs an extra scan run, so leave it unset
4036
+ * for routine trigger calls.
4037
+ *
4038
+ * **Admin only.** Setting this to `true` bypasses the dedup short-
4039
+ * circuit and fans out unbounded scanner work per artifact. The
4040
+ * `trigger_scan` handler rejects this field with 403 for non-admin
4041
+ * callers, since a non-admin force-rescan path would be a DoS
4042
+ * amplifier (the pre-existing `force=true` was naturally rate-limited
4043
+ * by dedup; `bypass_dedup` removes that safety).
4044
+ */
4045
+ bypass_dedup?: boolean | null;
3137
4046
  repository_id?: string | null;
3138
4047
  };
3139
4048
 
3140
4049
  export type TriggerScanResponse = {
3141
4050
  artifacts_queued: number;
3142
4051
  message: string;
4052
+ /**
4053
+ * Scan result IDs created (one per active scanner) when triggering an
4054
+ * artifact-level scan. Empty for repository-level scans (where the
4055
+ * per-artifact rows are created inside the spawned worker) and for
4056
+ * artifact-level triggers when no scanners are configured.
4057
+ *
4058
+ * Clients (and the release-gate test in artifact-keeper-test#58) should
4059
+ * poll `GET /api/v1/security/scans/{id}` against these IDs rather than
4060
+ * guessing the most-recent scan from `GET /artifacts/{id}/scans`.
4061
+ */
4062
+ scan_result_ids?: Array<string>;
3143
4063
  };
3144
4064
 
3145
4065
  /**
@@ -3211,15 +4131,29 @@ export type UpdateLdapConfigRequest = {
3211
4131
  };
3212
4132
 
3213
4133
  export type UpdateOidcConfigRequest = {
4134
+ /**
4135
+ * Partial update for `attribute_mapping`. Keys present in this object
4136
+ * overwrite the matching keys in the stored mapping. Keys not present
4137
+ * are preserved. To remove a key, set it to `null`. To replace the
4138
+ * whole mapping atomically, set `attribute_mapping_replace = true`.
4139
+ * (See issue #1191.)
4140
+ */
3214
4141
  attribute_mapping?: {
3215
4142
  [key: string]: unknown;
3216
4143
  } | null;
4144
+ /**
4145
+ * When `true`, treat `attribute_mapping` as a wholesale replacement
4146
+ * (legacy behavior). Defaults to `false` — partial merge.
4147
+ */
4148
+ attribute_mapping_replace?: boolean | null;
3217
4149
  auto_create_users?: boolean | null;
3218
4150
  client_id?: string | null;
3219
4151
  client_secret?: string | null;
3220
4152
  is_enabled?: boolean | null;
3221
4153
  issuer_url?: string | null;
4154
+ map_groups_to_groups?: boolean | null;
3222
4155
  name?: string | null;
4156
+ pkce_enabled?: boolean | null;
3223
4157
  scopes?: Array<string> | null;
3224
4158
  };
3225
4159
 
@@ -3229,18 +4163,45 @@ export type UpdatePluginConfigRequest = {
3229
4163
  };
3230
4164
  };
3231
4165
 
4166
+ /**
4167
+ * Partial-update payload for `PUT /security/policies/{id}`.
4168
+ *
4169
+ * Every field is `Option<T>` so clients can send any subset of mutable
4170
+ * columns; omitted fields leave the existing row value untouched. The
4171
+ * previous shape required all of `name`, `max_severity`, `block_unscanned`,
4172
+ * `block_on_fail`, `is_enabled` on every call. That was incompatible with
4173
+ * the release-gate `scan-policy-crud` test (and external callers) which
4174
+ * PATCH a subset like `{max_severity, is_enabled}`; under the strict shape
4175
+ * the request was rejected as a 422 and the boolean toggle silently never
4176
+ * took effect on a follow-up GET. See #1374.
4177
+ *
4178
+ * For `min_staging_hours` / `max_artifact_age_days` the field is the inner
4179
+ * nullable `i32`; "not provided" leaves the column untouched. Explicit
4180
+ * `null` to clear those columns is not currently supported; the release
4181
+ * gate only mutates the bool/enum fields, so the narrower semantics are
4182
+ * sufficient and we avoid an ambiguous JSON contract.
4183
+ */
3232
4184
  export type UpdatePolicyRequest = {
3233
- block_on_fail: boolean;
3234
- block_unscanned: boolean;
3235
- is_enabled: boolean;
4185
+ block_on_fail?: boolean | null;
4186
+ block_unscanned?: boolean | null;
4187
+ is_enabled?: boolean | null;
3236
4188
  max_artifact_age_days?: number | null;
3237
- max_severity: string;
4189
+ max_severity?: string | null;
3238
4190
  min_staging_hours?: number | null;
3239
- name: string;
3240
- require_signature?: boolean;
4191
+ name?: string | null;
4192
+ require_signature?: boolean | null;
3241
4193
  };
3242
4194
 
3243
4195
  export type UpdateRepositoryRequest = {
4196
+ /**
4197
+ * Alias for `is_public`. When set to true, anonymous users can download
4198
+ * artifacts without authentication. Useful for remote (pull-through cache)
4199
+ * repositories that proxy public upstream registries. Write operations
4200
+ * (upload, delete) still require authentication regardless of this setting.
4201
+ * If both `is_public` and `allow_anonymous_access` are provided,
4202
+ * `allow_anonymous_access` takes precedence.
4203
+ */
4204
+ allow_anonymous_access?: boolean | null;
3244
4205
  description?: string | null;
3245
4206
  /**
3246
4207
  * Update the Cargo index upstream URL (stored in `repository_config`).
@@ -3250,7 +4211,31 @@ export type UpdateRepositoryRequest = {
3250
4211
  is_public?: boolean | null;
3251
4212
  key?: string | null;
3252
4213
  name?: string | null;
4214
+ /**
4215
+ * When provided, enables/disables the `promotion_only` policy for this
4216
+ * repository (admin-only). When omitted, the flag is left unchanged.
4217
+ */
4218
+ promotion_only?: boolean | null;
4219
+ /**
4220
+ * Quarantine hold duration in minutes for this repository.
4221
+ * Stored in `repository_config` under `quarantine_duration_minutes`.
4222
+ */
4223
+ quarantine_duration_minutes?: number | null;
4224
+ /**
4225
+ * Enable or disable quarantine period for this repository.
4226
+ * When enabled, newly uploaded artifacts are held until scanned.
4227
+ * Stored in `repository_config` under `quarantine_enabled`.
4228
+ */
4229
+ quarantine_enabled?: boolean | null;
3253
4230
  quota_bytes?: number | null;
4231
+ /**
4232
+ * Link this staging repository to a release (local) repository.
4233
+ * Promotions from this staging repo will default to the linked release repo,
4234
+ * and promotions to any other repo will be rejected.
4235
+ * Pass an empty string to remove the link.
4236
+ * Stored in `repository_config` under `release_repository_id`.
4237
+ */
4238
+ release_repository_key?: string | null;
3254
4239
  };
3255
4240
 
3256
4241
  export type UpdateRuleRequest = {
@@ -3336,13 +4321,25 @@ export type UpsertLicensePolicyRequest = {
3336
4321
 
3337
4322
  /**
3338
4323
  * Request to create or update a scan configuration.
4324
+ *
4325
+ * Every field is optional so a `PUT /repositories/{key}/security` can carry
4326
+ * any subset of mutable columns; fields the client omits keep their existing
4327
+ * value (or fall back to the documented default when the row does not exist
4328
+ * yet). The previous shape required all of `scan_enabled`, `scan_on_upload`,
4329
+ * `scan_on_proxy`, `block_on_policy_violation`, `severity_threshold` on every
4330
+ * call. That was the #1374 bug class on a second entity: a partial PUT (for
4331
+ * example just `{scan_enabled: true}`) either bounced as a 422 or, worse,
4332
+ * silently reset every other column to its default so a follow-up GET showed
4333
+ * the untouched fields stale. The upsert is now a read-modify-write that
4334
+ * merges the patch over the existing row, so multiple fields persist together
4335
+ * and an omitted field is never clobbered. See #1374 / B11.
3339
4336
  */
3340
4337
  export type UpsertScanConfigRequest = {
3341
- block_on_policy_violation: boolean;
3342
- scan_enabled: boolean;
3343
- scan_on_proxy: boolean;
3344
- scan_on_upload: boolean;
3345
- severity_threshold: string;
4338
+ block_on_policy_violation?: boolean | null;
4339
+ scan_enabled?: boolean | null;
4340
+ scan_on_proxy?: boolean | null;
4341
+ scan_on_upload?: boolean | null;
4342
+ severity_threshold?: string | null;
3346
4343
  };
3347
4344
 
3348
4345
  export type UpstreamAuthRequest = {
@@ -3433,6 +4430,12 @@ export type WebhookListResponse = {
3433
4430
 
3434
4431
  export type WebhookResponse = {
3435
4432
  created_at: string;
4433
+ /**
4434
+ * Pinned event payload version (e.g. "2026-04-01"). Determines the
4435
+ * shape of the rendered payload and the value sent in the
4436
+ * `X-ArtifactKeeper-Event-Version` header.
4437
+ */
4438
+ event_schema_version: string;
3436
4439
  events: Array<string>;
3437
4440
  headers?: {
3438
4441
  [key: string]: unknown;
@@ -3441,10 +4444,42 @@ export type WebhookResponse = {
3441
4444
  is_enabled: boolean;
3442
4445
  last_triggered_at?: string | null;
3443
4446
  name: string;
4447
+ payload_template: PayloadTemplate;
3444
4448
  repository_id?: string | null;
4449
+ /**
4450
+ * Short non-reversible identifier for the current signing secret
4451
+ * (`whsec_...abcd`), suitable for display in operator UIs. The raw
4452
+ * secret is never returned by GET or LIST.
4453
+ */
4454
+ secret_digest?: string | null;
4455
+ /**
4456
+ * True while a previous secret is still accepted by the retry path
4457
+ * during a rotation overlap window.
4458
+ */
4459
+ secret_rotation_active?: boolean;
3445
4460
  url: string;
3446
4461
  };
3447
4462
 
4463
+ /**
4464
+ * Response returned exactly once when a webhook is created or its secret
4465
+ * is rotated. The raw `secret` value is not retrievable afterwards.
4466
+ */
4467
+ export type WebhookSecretCreatedResponse = WebhookResponse & {
4468
+ /**
4469
+ * Raw signing secret. Display this to the operator immediately and
4470
+ * instruct them to record it; the server retains only the encrypted
4471
+ * form and a short digest.
4472
+ *
4473
+ * Absent when the webhook was created without a signing secret. This
4474
+ * happens when no secret was supplied and the deployment has no
4475
+ * `AK_WEBHOOK_SECRET_KEY` configured: rather than fail the create with
4476
+ * a 500, the webhook is stored unsigned and deliveries omit the
4477
+ * signature header. Configure the key and rotate the secret later to
4478
+ * enable signing.
4479
+ */
4480
+ secret?: string | null;
4481
+ };
4482
+
3448
4483
  export type GetStaleArtifactsData = {
3449
4484
  body?: never;
3450
4485
  path?: never;
@@ -3707,6 +4742,10 @@ export type CancelBackupErrors = {
3707
4742
  * Backup not found
3708
4743
  */
3709
4744
  404: unknown;
4745
+ /**
4746
+ * Backup is not in a cancellable state
4747
+ */
4748
+ 409: unknown;
3710
4749
  /**
3711
4750
  * Internal server error
3712
4751
  */
@@ -4066,21 +5105,51 @@ export type TriggerReindexResponses = {
4066
5105
 
4067
5106
  export type TriggerReindexResponse = TriggerReindexResponses[keyof TriggerReindexResponses];
4068
5107
 
4069
- export type TriggerSearchReindexData = {
4070
- body?: never;
5108
+ export type RescanForInventoryData = {
5109
+ /**
5110
+ * Optional; empty body uses defaults
5111
+ */
5112
+ body: RescanForInventoryRequest;
4071
5113
  path?: never;
4072
5114
  query?: never;
4073
- url: '/api/v1/admin/search/reindex';
5115
+ url: '/api/v1/admin/rescan-for-inventory';
4074
5116
  };
4075
5117
 
4076
- export type TriggerSearchReindexErrors = {
5118
+ export type RescanForInventoryErrors = {
4077
5119
  /**
4078
- * Meilisearch is not configured
5120
+ * Admin privileges required
4079
5121
  */
4080
- 500: unknown;
5122
+ 403: unknown;
5123
+ /**
5124
+ * Scanner service not configured
5125
+ */
5126
+ 503: unknown;
4081
5127
  };
4082
5128
 
4083
- export type TriggerSearchReindexResponses = {
5129
+ export type RescanForInventoryResponses = {
5130
+ /**
5131
+ * Rescans enqueued
5132
+ */
5133
+ 200: RescanForInventoryResponse;
5134
+ };
5135
+
5136
+ export type RescanForInventoryResponse2 = RescanForInventoryResponses[keyof RescanForInventoryResponses];
5137
+
5138
+ export type TriggerSearchReindexData = {
5139
+ body?: never;
5140
+ path?: never;
5141
+ query?: never;
5142
+ url: '/api/v1/admin/search/reindex';
5143
+ };
5144
+
5145
+ export type TriggerSearchReindexErrors = {
5146
+ /**
5147
+ * Search engine is not configured
5148
+ */
5149
+ 500: unknown;
5150
+ };
5151
+
5152
+ export type TriggerSearchReindexResponses = {
4084
5153
  /**
4085
5154
  * Reindex started in background
4086
5155
  */
@@ -4135,6 +5204,37 @@ export type UpdateSettingsResponses = {
4135
5204
 
4136
5205
  export type UpdateSettingsResponse = UpdateSettingsResponses[keyof UpdateSettingsResponses];
4137
5206
 
5207
+ export type SendTestEmailData = {
5208
+ body: SmtpTestRequest;
5209
+ path?: never;
5210
+ query?: never;
5211
+ url: '/api/v1/admin/smtp/test';
5212
+ };
5213
+
5214
+ export type SendTestEmailErrors = {
5215
+ /**
5216
+ * Invalid request (e.g. bad email address)
5217
+ */
5218
+ 400: unknown;
5219
+ /**
5220
+ * Admin privileges required
5221
+ */
5222
+ 403: unknown;
5223
+ /**
5224
+ * SMTP not configured
5225
+ */
5226
+ 503: unknown;
5227
+ };
5228
+
5229
+ export type SendTestEmailResponses = {
5230
+ /**
5231
+ * Test email sent successfully
5232
+ */
5233
+ 200: SmtpTestResponse;
5234
+ };
5235
+
5236
+ export type SendTestEmailResponse = SendTestEmailResponses[keyof SendTestEmailResponses];
5237
+
4138
5238
  export type ListLdapData = {
4139
5239
  body?: never;
4140
5240
  path?: never;
@@ -4802,6 +5902,28 @@ export type RunStorageGcResponses = {
4802
5902
 
4803
5903
  export type RunStorageGcResponse = RunStorageGcResponses[keyof RunStorageGcResponses];
4804
5904
 
5905
+ export type OciBlobReportData = {
5906
+ body?: never;
5907
+ path?: never;
5908
+ query?: {
5909
+ /**
5910
+ * Grace window in hours used to compute the `aged_*` figures. Defaults
5911
+ * to 24h; non-positive or out-of-range values are clamped server-side.
5912
+ */
5913
+ grace_hours?: number | null;
5914
+ };
5915
+ url: '/api/v1/admin/storage-gc/oci-blob-report';
5916
+ };
5917
+
5918
+ export type OciBlobReportResponses = {
5919
+ /**
5920
+ * OCI blob footprint report
5921
+ */
5922
+ 200: OciBlobFootprintReport;
5923
+ };
5924
+
5925
+ export type OciBlobReportResponse = OciBlobReportResponses[keyof OciBlobReportResponses];
5926
+
4805
5927
  export type ListCrashesData = {
4806
5928
  body?: never;
4807
5929
  path?: never;
@@ -5362,7 +6484,7 @@ export type LoginResponses = {
5362
6484
  export type LoginResponse2 = LoginResponses[keyof LoginResponses];
5363
6485
 
5364
6486
  export type LogoutData = {
5365
- body?: never;
6487
+ body?: RefreshTokenRequest;
5366
6488
  path?: never;
5367
6489
  query?: never;
5368
6490
  url: '/api/v1/auth/logout';
@@ -5494,9 +6616,12 @@ export type OidcCallbackData = {
5494
6616
  */
5495
6617
  id: string;
5496
6618
  };
5497
- query: {
5498
- code: string;
5499
- state: string;
6619
+ query?: {
6620
+ code?: string | null;
6621
+ state?: string | null;
6622
+ error?: string | null;
6623
+ error_description?: string | null;
6624
+ error_uri?: string | null;
5500
6625
  };
5501
6626
  url: '/api/v1/auth/sso/oidc/{id}/callback';
5502
6627
  };
@@ -5506,6 +6631,10 @@ export type OidcCallbackErrors = {
5506
6631
  * Invalid callback parameters
5507
6632
  */
5508
6633
  400: ErrorResponse;
6634
+ /**
6635
+ * IdP error or invalid/expired SSO state
6636
+ */
6637
+ 401: ErrorResponse;
5509
6638
  };
5510
6639
 
5511
6640
  export type OidcCallbackError = OidcCallbackErrors[keyof OidcCallbackErrors];
@@ -6453,6 +7582,10 @@ export type ListGroupsData = {
6453
7582
  };
6454
7583
 
6455
7584
  export type ListGroupsErrors = {
7585
+ /**
7586
+ * Authentication required
7587
+ */
7588
+ 401: unknown;
6456
7589
  /**
6457
7590
  * Internal server error
6458
7591
  */
@@ -6476,6 +7609,14 @@ export type CreateGroupData = {
6476
7609
  };
6477
7610
 
6478
7611
  export type CreateGroupErrors = {
7612
+ /**
7613
+ * Authentication required
7614
+ */
7615
+ 401: unknown;
7616
+ /**
7617
+ * Insufficient permissions
7618
+ */
7619
+ 403: unknown;
6479
7620
  /**
6480
7621
  * Group name already exists
6481
7622
  */
@@ -6508,6 +7649,14 @@ export type DeleteGroupData = {
6508
7649
  };
6509
7650
 
6510
7651
  export type DeleteGroupErrors = {
7652
+ /**
7653
+ * Authentication required
7654
+ */
7655
+ 401: unknown;
7656
+ /**
7657
+ * Insufficient permissions
7658
+ */
7659
+ 403: unknown;
6511
7660
  /**
6512
7661
  * Group not found
6513
7662
  */
@@ -6547,6 +7696,10 @@ export type GetGroupData = {
6547
7696
  };
6548
7697
 
6549
7698
  export type GetGroupErrors = {
7699
+ /**
7700
+ * Authentication required
7701
+ */
7702
+ 401: unknown;
6550
7703
  /**
6551
7704
  * Group not found
6552
7705
  */
@@ -6579,6 +7732,14 @@ export type UpdateGroupData = {
6579
7732
  };
6580
7733
 
6581
7734
  export type UpdateGroupErrors = {
7735
+ /**
7736
+ * Authentication required
7737
+ */
7738
+ 401: unknown;
7739
+ /**
7740
+ * Insufficient permissions
7741
+ */
7742
+ 403: unknown;
6582
7743
  /**
6583
7744
  * Group not found
6584
7745
  */
@@ -6611,6 +7772,14 @@ export type RemoveMembersData = {
6611
7772
  };
6612
7773
 
6613
7774
  export type RemoveMembersErrors = {
7775
+ /**
7776
+ * Authentication required
7777
+ */
7778
+ 401: unknown;
7779
+ /**
7780
+ * Insufficient permissions
7781
+ */
7782
+ 403: unknown;
6614
7783
  /**
6615
7784
  * Group not found
6616
7785
  */
@@ -6641,6 +7810,14 @@ export type AddMembersData = {
6641
7810
  };
6642
7811
 
6643
7812
  export type AddMembersErrors = {
7813
+ /**
7814
+ * Authentication required
7815
+ */
7816
+ 401: unknown;
7817
+ /**
7818
+ * Insufficient permissions
7819
+ */
7820
+ 403: unknown;
6644
7821
  /**
6645
7822
  * Group not found
6646
7823
  */
@@ -8108,6 +9285,78 @@ export type UnassignRepoResponses = {
8108
9285
  200: unknown;
8109
9286
  };
8110
9287
 
9288
+ export type GetSubscriptionData = {
9289
+ body?: never;
9290
+ path: {
9291
+ /**
9292
+ * Peer instance ID
9293
+ */
9294
+ id: string;
9295
+ /**
9296
+ * Repository ID
9297
+ */
9298
+ repo_id: string;
9299
+ };
9300
+ query?: never;
9301
+ url: '/api/v1/peers/{id}/repositories/{repo_id}';
9302
+ };
9303
+
9304
+ export type GetSubscriptionErrors = {
9305
+ /**
9306
+ * Subscription not found
9307
+ */
9308
+ 404: unknown;
9309
+ /**
9310
+ * Internal server error
9311
+ */
9312
+ 500: unknown;
9313
+ };
9314
+
9315
+ export type GetSubscriptionResponses = {
9316
+ /**
9317
+ * Subscription details
9318
+ */
9319
+ 200: SubscriptionResponse;
9320
+ };
9321
+
9322
+ export type GetSubscriptionResponse = GetSubscriptionResponses[keyof GetSubscriptionResponses];
9323
+
9324
+ export type RunSubscriptionNowData = {
9325
+ body?: never;
9326
+ path: {
9327
+ /**
9328
+ * Peer instance ID
9329
+ */
9330
+ id: string;
9331
+ /**
9332
+ * Repository ID
9333
+ */
9334
+ repo_id: string;
9335
+ };
9336
+ query?: never;
9337
+ url: '/api/v1/peers/{id}/repositories/{repo_id}/sync';
9338
+ };
9339
+
9340
+ export type RunSubscriptionNowErrors = {
9341
+ /**
9342
+ * Subscription not found
9343
+ */
9344
+ 404: unknown;
9345
+ /**
9346
+ * Internal server error
9347
+ */
9348
+ 500: unknown;
9349
+ };
9350
+
9351
+ export type RunSubscriptionNowResponses = {
9352
+ /**
9353
+ * Sync tasks queued
9354
+ */
9355
+ 202: RunNowResponse;
9356
+ };
9357
+
9358
+ export type RunSubscriptionNowResponse = RunSubscriptionNowResponses[keyof RunSubscriptionNowResponses];
9359
+
8111
9360
  export type TriggerSyncData = {
8112
9361
  body?: never;
8113
9362
  path: {
@@ -9177,6 +10426,74 @@ export type PromotionHistoryResponses = {
9177
10426
 
9178
10427
  export type PromotionHistoryResponse2 = PromotionHistoryResponses[keyof PromotionHistoryResponses];
9179
10428
 
10429
+ export type GetReleaseTargetData = {
10430
+ body?: never;
10431
+ path: {
10432
+ /**
10433
+ * Staging repository key
10434
+ */
10435
+ key: string;
10436
+ };
10437
+ query?: never;
10438
+ url: '/api/v1/promotion/repositories/{key}/release-target';
10439
+ };
10440
+
10441
+ export type GetReleaseTargetErrors = {
10442
+ /**
10443
+ * Repository not found
10444
+ */
10445
+ 404: ErrorResponse;
10446
+ /**
10447
+ * Repository is not a staging repository
10448
+ */
10449
+ 422: ErrorResponse;
10450
+ };
10451
+
10452
+ export type GetReleaseTargetError = GetReleaseTargetErrors[keyof GetReleaseTargetErrors];
10453
+
10454
+ export type GetReleaseTargetResponses = {
10455
+ /**
10456
+ * Release target information
10457
+ */
10458
+ 200: ReleaseTargetResponse;
10459
+ };
10460
+
10461
+ export type GetReleaseTargetResponse = GetReleaseTargetResponses[keyof GetReleaseTargetResponses];
10462
+
10463
+ export type SetReleaseTargetData = {
10464
+ body: SetReleaseTargetRequest;
10465
+ path: {
10466
+ /**
10467
+ * Staging repository key
10468
+ */
10469
+ key: string;
10470
+ };
10471
+ query?: never;
10472
+ url: '/api/v1/promotion/repositories/{key}/release-target';
10473
+ };
10474
+
10475
+ export type SetReleaseTargetErrors = {
10476
+ /**
10477
+ * Repository not found
10478
+ */
10479
+ 404: ErrorResponse;
10480
+ /**
10481
+ * Validation error
10482
+ */
10483
+ 422: ErrorResponse;
10484
+ };
10485
+
10486
+ export type SetReleaseTargetError = SetReleaseTargetErrors[keyof SetReleaseTargetErrors];
10487
+
10488
+ export type SetReleaseTargetResponses = {
10489
+ /**
10490
+ * Release target updated
10491
+ */
10492
+ 200: ReleaseTargetResponse;
10493
+ };
10494
+
10495
+ export type SetReleaseTargetResponse = SetReleaseTargetResponses[keyof SetReleaseTargetResponses];
10496
+
9180
10497
  export type ListChecksData = {
9181
10498
  body?: never;
9182
10499
  path?: never;
@@ -9582,77 +10899,197 @@ export type SuppressIssueResponses = {
9582
10899
 
9583
10900
  export type SuppressIssueResponse = SuppressIssueResponses[keyof SuppressIssueResponses];
9584
10901
 
9585
- export type ListRepositoriesData = {
10902
+ export type GetQuarantineStatusData = {
9586
10903
  body?: never;
9587
- path?: never;
9588
- query?: {
9589
- page?: number | null;
9590
- per_page?: number | null;
9591
- format?: string | null;
9592
- type?: string | null;
9593
- q?: string | null;
10904
+ path: {
10905
+ /**
10906
+ * Artifact ID
10907
+ */
10908
+ artifact_id: string;
9594
10909
  };
9595
- url: '/api/v1/repositories';
9596
- };
9597
-
9598
- export type ListRepositoriesResponses = {
9599
- /**
9600
- * List of repositories
9601
- */
9602
- 200: RepositoryListResponse;
9603
- };
9604
-
9605
- export type ListRepositoriesResponse = ListRepositoriesResponses[keyof ListRepositoriesResponses];
9606
-
9607
- export type CreateRepositoryData = {
9608
- body: CreateRepositoryRequest;
9609
- path?: never;
9610
10910
  query?: never;
9611
- url: '/api/v1/repositories';
10911
+ url: '/api/v1/quarantine/{artifact_id}';
9612
10912
  };
9613
10913
 
9614
- export type CreateRepositoryErrors = {
10914
+ export type GetQuarantineStatusErrors = {
9615
10915
  /**
9616
10916
  * Authentication required
9617
10917
  */
9618
10918
  401: unknown;
9619
10919
  /**
9620
- * Repository key already exists
10920
+ * Artifact not found
9621
10921
  */
9622
- 409: unknown;
10922
+ 404: unknown;
9623
10923
  };
9624
10924
 
9625
- export type CreateRepositoryResponses = {
10925
+ export type GetQuarantineStatusResponses = {
9626
10926
  /**
9627
- * Repository created
10927
+ * Quarantine status
9628
10928
  */
9629
- 200: RepositoryResponse;
10929
+ 200: QuarantineStatusResponse;
9630
10930
  };
9631
10931
 
9632
- export type CreateRepositoryResponse = CreateRepositoryResponses[keyof CreateRepositoryResponses];
10932
+ export type GetQuarantineStatusResponse = GetQuarantineStatusResponses[keyof GetQuarantineStatusResponses];
9633
10933
 
9634
- export type DeleteRepositoryData = {
9635
- body?: never;
10934
+ export type RejectQuarantinedArtifactData = {
10935
+ body: RejectRequest;
9636
10936
  path: {
9637
10937
  /**
9638
- * Repository key
10938
+ * Artifact ID
9639
10939
  */
9640
- key: string;
10940
+ artifact_id: string;
9641
10941
  };
9642
10942
  query?: never;
9643
- url: '/api/v1/repositories/{key}';
10943
+ url: '/api/v1/quarantine/{artifact_id}/reject';
9644
10944
  };
9645
10945
 
9646
- export type DeleteRepositoryErrors = {
10946
+ export type RejectQuarantinedArtifactErrors = {
9647
10947
  /**
9648
10948
  * Authentication required
9649
10949
  */
9650
10950
  401: unknown;
9651
10951
  /**
9652
- * Repository not found
10952
+ * Admin access required
9653
10953
  */
9654
- 404: unknown;
9655
- };
10954
+ 403: unknown;
10955
+ /**
10956
+ * Artifact not found
10957
+ */
10958
+ 404: unknown;
10959
+ /**
10960
+ * Artifact is not in quarantined state
10961
+ */
10962
+ 409: unknown;
10963
+ };
10964
+
10965
+ export type RejectQuarantinedArtifactResponses = {
10966
+ /**
10967
+ * Artifact rejected
10968
+ */
10969
+ 200: QuarantineActionResponse;
10970
+ };
10971
+
10972
+ export type RejectQuarantinedArtifactResponse = RejectQuarantinedArtifactResponses[keyof RejectQuarantinedArtifactResponses];
10973
+
10974
+ export type ReleaseArtifactData = {
10975
+ body?: never;
10976
+ path: {
10977
+ /**
10978
+ * Artifact ID
10979
+ */
10980
+ artifact_id: string;
10981
+ };
10982
+ query?: never;
10983
+ url: '/api/v1/quarantine/{artifact_id}/release';
10984
+ };
10985
+
10986
+ export type ReleaseArtifactErrors = {
10987
+ /**
10988
+ * Authentication required
10989
+ */
10990
+ 401: unknown;
10991
+ /**
10992
+ * Admin access required
10993
+ */
10994
+ 403: unknown;
10995
+ /**
10996
+ * Artifact not found
10997
+ */
10998
+ 404: unknown;
10999
+ /**
11000
+ * Artifact is not in quarantined state
11001
+ */
11002
+ 409: unknown;
11003
+ };
11004
+
11005
+ export type ReleaseArtifactResponses = {
11006
+ /**
11007
+ * Artifact released
11008
+ */
11009
+ 200: QuarantineActionResponse;
11010
+ };
11011
+
11012
+ export type ReleaseArtifactResponse = ReleaseArtifactResponses[keyof ReleaseArtifactResponses];
11013
+
11014
+ export type ListRepositoriesData = {
11015
+ body?: never;
11016
+ path?: never;
11017
+ query?: {
11018
+ page?: number | null;
11019
+ per_page?: number | null;
11020
+ format?: string | null;
11021
+ type?: string | null;
11022
+ q?: string | null;
11023
+ };
11024
+ url: '/api/v1/repositories';
11025
+ };
11026
+
11027
+ export type ListRepositoriesResponses = {
11028
+ /**
11029
+ * List of repositories
11030
+ */
11031
+ 200: RepositoryListResponse;
11032
+ };
11033
+
11034
+ export type ListRepositoriesResponse = ListRepositoriesResponses[keyof ListRepositoriesResponses];
11035
+
11036
+ export type CreateRepositoryData = {
11037
+ body: CreateRepositoryRequest;
11038
+ path?: never;
11039
+ query?: never;
11040
+ url: '/api/v1/repositories';
11041
+ };
11042
+
11043
+ export type CreateRepositoryErrors = {
11044
+ /**
11045
+ * Authentication required
11046
+ */
11047
+ 401: unknown;
11048
+ /**
11049
+ * Insufficient permissions
11050
+ */
11051
+ 403: unknown;
11052
+ /**
11053
+ * Repository key already exists
11054
+ */
11055
+ 409: unknown;
11056
+ };
11057
+
11058
+ export type CreateRepositoryResponses = {
11059
+ /**
11060
+ * Repository created
11061
+ */
11062
+ 200: RepositoryResponse;
11063
+ };
11064
+
11065
+ export type CreateRepositoryResponse = CreateRepositoryResponses[keyof CreateRepositoryResponses];
11066
+
11067
+ export type DeleteRepositoryData = {
11068
+ body?: never;
11069
+ path: {
11070
+ /**
11071
+ * Repository key
11072
+ */
11073
+ key: string;
11074
+ };
11075
+ query?: never;
11076
+ url: '/api/v1/repositories/{key}';
11077
+ };
11078
+
11079
+ export type DeleteRepositoryErrors = {
11080
+ /**
11081
+ * Authentication required
11082
+ */
11083
+ 401: unknown;
11084
+ /**
11085
+ * Insufficient permissions
11086
+ */
11087
+ 403: unknown;
11088
+ /**
11089
+ * Repository not found
11090
+ */
11091
+ 404: unknown;
11092
+ };
9656
11093
 
9657
11094
  export type DeleteRepositoryResponses = {
9658
11095
  /**
@@ -9706,6 +11143,10 @@ export type UpdateRepositoryErrors = {
9706
11143
  * Authentication required
9707
11144
  */
9708
11145
  401: unknown;
11146
+ /**
11147
+ * Insufficient permissions
11148
+ */
11149
+ 403: unknown;
9709
11150
  /**
9710
11151
  * Repository not found
9711
11152
  */
@@ -9738,6 +11179,19 @@ export type ListArtifactsData = {
9738
11179
  per_page?: number | null;
9739
11180
  q?: string | null;
9740
11181
  path_prefix?: string | null;
11182
+ /**
11183
+ * Server-side artifact grouping.
11184
+ *
11185
+ * Supported values:
11186
+ * - `maven_component`: Maven/Gradle artifacts are grouped by
11187
+ * groupId, artifactId, and version. Individual files (jar, pom,
11188
+ * checksums) appear in the `artifact_files` array of each component.
11189
+ * - `docker_tag`: Docker/OCI artifacts are grouped by (image, tag),
11190
+ * with `total_size_bytes` summed across the manifest config and
11191
+ * referenced layer blobs. The grouped rows are returned in the
11192
+ * `docker_tags` array.
11193
+ */
11194
+ group_by?: string | null;
9741
11195
  };
9742
11196
  url: '/api/v1/repositories/{key}/artifacts';
9743
11197
  };
@@ -9783,6 +11237,10 @@ export type DeleteArtifactErrors = {
9783
11237
  * Artifact not found
9784
11238
  */
9785
11239
  404: unknown;
11240
+ /**
11241
+ * Artifact is immutable (released) and cannot be deleted
11242
+ */
11243
+ 409: unknown;
9786
11244
  };
9787
11245
 
9788
11246
  export type DeleteArtifactResponses = {
@@ -9924,6 +11382,55 @@ export type SetCacheTtlResponses = {
9924
11382
 
9925
11383
  export type SetCacheTtlResponse = SetCacheTtlResponses[keyof SetCacheTtlResponses];
9926
11384
 
11385
+ export type InvalidateCacheData = {
11386
+ body?: never;
11387
+ path: {
11388
+ /**
11389
+ * Repository key
11390
+ */
11391
+ key: string;
11392
+ };
11393
+ query: {
11394
+ /**
11395
+ * Artifact path to evict from the proxy cache. Same shape as the path
11396
+ * segment of `GET /api/v1/repositories/{key}/artifacts/{path}`.
11397
+ * Path-traversal segments such as `..` are rejected by
11398
+ * `ProxyService::cache_storage_key` (covered by
11399
+ * `test_invalidate_cache_by_key_rejects_invalid_path`).
11400
+ */
11401
+ path: string;
11402
+ };
11403
+ url: '/api/v1/repositories/{key}/cache/invalidate';
11404
+ };
11405
+
11406
+ export type InvalidateCacheErrors = {
11407
+ /**
11408
+ * Validation error (e.g. non-remote repo or invalid path)
11409
+ */
11410
+ 400: unknown;
11411
+ /**
11412
+ * Authentication required
11413
+ */
11414
+ 401: unknown;
11415
+ /**
11416
+ * Repository not found
11417
+ */
11418
+ 404: unknown;
11419
+ /**
11420
+ * Proxy service not configured on this deployment
11421
+ */
11422
+ 503: unknown;
11423
+ };
11424
+
11425
+ export type InvalidateCacheResponses = {
11426
+ /**
11427
+ * Cache entry invalidated (or was already absent)
11428
+ */
11429
+ 200: InvalidateCacheResponse;
11430
+ };
11431
+
11432
+ export type InvalidateCacheResponse2 = InvalidateCacheResponses[keyof InvalidateCacheResponses];
11433
+
9927
11434
  export type DownloadArtifactData = {
9928
11435
  body?: never;
9929
11436
  path: {
@@ -9956,6 +11463,122 @@ export type DownloadArtifactResponses = {
9956
11463
 
9957
11464
  export type DownloadArtifactResponse = DownloadArtifactResponses[keyof DownloadArtifactResponses];
9958
11465
 
11466
+ export type ListSubscriptionsData = {
11467
+ body?: never;
11468
+ path: {
11469
+ /**
11470
+ * Repository key
11471
+ */
11472
+ key: string;
11473
+ };
11474
+ query?: never;
11475
+ url: '/api/v1/repositories/{key}/email-subscriptions';
11476
+ };
11477
+
11478
+ export type ListSubscriptionsErrors = {
11479
+ /**
11480
+ * Not authenticated
11481
+ */
11482
+ 401: unknown;
11483
+ /**
11484
+ * Insufficient permissions
11485
+ */
11486
+ 403: unknown;
11487
+ /**
11488
+ * Repository not found
11489
+ */
11490
+ 404: unknown;
11491
+ };
11492
+
11493
+ export type ListSubscriptionsResponses = {
11494
+ /**
11495
+ * List of email subscriptions
11496
+ */
11497
+ 200: EmailSubscriptionListResponse;
11498
+ };
11499
+
11500
+ export type ListSubscriptionsResponse = ListSubscriptionsResponses[keyof ListSubscriptionsResponses];
11501
+
11502
+ export type CreateSubscriptionData = {
11503
+ body: CreateEmailSubscriptionRequest;
11504
+ path: {
11505
+ /**
11506
+ * Repository key
11507
+ */
11508
+ key: string;
11509
+ };
11510
+ query?: never;
11511
+ url: '/api/v1/repositories/{key}/email-subscriptions';
11512
+ };
11513
+
11514
+ export type CreateSubscriptionErrors = {
11515
+ /**
11516
+ * Validation error
11517
+ */
11518
+ 400: unknown;
11519
+ /**
11520
+ * Not authenticated
11521
+ */
11522
+ 401: unknown;
11523
+ /**
11524
+ * Insufficient permissions
11525
+ */
11526
+ 403: unknown;
11527
+ /**
11528
+ * Repository not found
11529
+ */
11530
+ 404: unknown;
11531
+ };
11532
+
11533
+ export type CreateSubscriptionResponses = {
11534
+ /**
11535
+ * Subscription created
11536
+ */
11537
+ 201: EmailSubscriptionResponse;
11538
+ };
11539
+
11540
+ export type CreateSubscriptionResponse = CreateSubscriptionResponses[keyof CreateSubscriptionResponses];
11541
+
11542
+ export type DeleteSubscriptionData = {
11543
+ body?: never;
11544
+ path: {
11545
+ /**
11546
+ * Repository key
11547
+ */
11548
+ key: string;
11549
+ /**
11550
+ * Subscription ID
11551
+ */
11552
+ subscription_id: string;
11553
+ };
11554
+ query?: never;
11555
+ url: '/api/v1/repositories/{key}/email-subscriptions/{subscription_id}';
11556
+ };
11557
+
11558
+ export type DeleteSubscriptionErrors = {
11559
+ /**
11560
+ * Not authenticated
11561
+ */
11562
+ 401: unknown;
11563
+ /**
11564
+ * Insufficient permissions
11565
+ */
11566
+ 403: unknown;
11567
+ /**
11568
+ * Subscription or repository not found
11569
+ */
11570
+ 404: unknown;
11571
+ };
11572
+
11573
+ export type DeleteSubscriptionResponses = {
11574
+ /**
11575
+ * Subscription deleted
11576
+ */
11577
+ 204: void;
11578
+ };
11579
+
11580
+ export type DeleteSubscriptionResponse = DeleteSubscriptionResponses[keyof DeleteSubscriptionResponses];
11581
+
9959
11582
  export type ListRepoLabelsData = {
9960
11583
  body?: never;
9961
11584
  path: {
@@ -10094,14 +11717,18 @@ export type ListVirtualMembersErrors = {
10094
11717
  */
10095
11718
  400: unknown;
10096
11719
  /**
10097
- * Repository not found
11720
+ * Authentication required
11721
+ */
11722
+ 401: unknown;
11723
+ /**
11724
+ * Repository not found
10098
11725
  */
10099
11726
  404: unknown;
10100
11727
  };
10101
11728
 
10102
11729
  export type ListVirtualMembersResponses = {
10103
11730
  /**
10104
- * List of virtual repository members
11731
+ * List of virtual repository members (filtered to caller-visible members)
10105
11732
  */
10106
11733
  200: VirtualMembersListResponse;
10107
11734
  };
@@ -10129,6 +11756,10 @@ export type AddVirtualMemberErrors = {
10129
11756
  * Repository or member not found
10130
11757
  */
10131
11758
  404: unknown;
11759
+ /**
11760
+ * Member already exists in virtual repository
11761
+ */
11762
+ 409: unknown;
10132
11763
  };
10133
11764
 
10134
11765
  export type AddVirtualMemberResponses = {
@@ -10214,6 +11845,204 @@ export type RemoveVirtualMemberResponses = {
10214
11845
  200: unknown;
10215
11846
  };
10216
11847
 
11848
+ export type ListPypiTracksData = {
11849
+ body?: never;
11850
+ path: {
11851
+ /**
11852
+ * Repository key
11853
+ */
11854
+ key: string;
11855
+ };
11856
+ query?: never;
11857
+ url: '/api/v1/repositories/{key}/pypi-tracks';
11858
+ };
11859
+
11860
+ export type ListPypiTracksErrors = {
11861
+ /**
11862
+ * Repository not found
11863
+ */
11864
+ 404: unknown;
11865
+ };
11866
+
11867
+ export type ListPypiTracksResponses = {
11868
+ /**
11869
+ * tracks declarations
11870
+ */
11871
+ 200: PypiTracksListResponse;
11872
+ };
11873
+
11874
+ export type ListPypiTracksResponse = ListPypiTracksResponses[keyof ListPypiTracksResponses];
11875
+
11876
+ export type DeletePypiTrackData = {
11877
+ body?: never;
11878
+ path: {
11879
+ /**
11880
+ * Repository key
11881
+ */
11882
+ key: string;
11883
+ /**
11884
+ * Project name (PEP 503 normalized server-side)
11885
+ */
11886
+ project: string;
11887
+ };
11888
+ query?: never;
11889
+ url: '/api/v1/repositories/{key}/pypi-tracks/{project}';
11890
+ };
11891
+
11892
+ export type DeletePypiTrackErrors = {
11893
+ /**
11894
+ * Authentication required
11895
+ */
11896
+ 401: unknown;
11897
+ /**
11898
+ * Repository not found
11899
+ */
11900
+ 404: unknown;
11901
+ };
11902
+
11903
+ export type DeletePypiTrackResponses = {
11904
+ /**
11905
+ * tracks declaration removed (idempotent)
11906
+ */
11907
+ 204: void;
11908
+ };
11909
+
11910
+ export type DeletePypiTrackResponse = DeletePypiTrackResponses[keyof DeletePypiTrackResponses];
11911
+
11912
+ export type PutPypiTrackData = {
11913
+ body: PypiTrackRequest;
11914
+ path: {
11915
+ /**
11916
+ * Repository key
11917
+ */
11918
+ key: string;
11919
+ /**
11920
+ * Project name (PEP 503 normalized server-side)
11921
+ */
11922
+ project: string;
11923
+ };
11924
+ query?: never;
11925
+ url: '/api/v1/repositories/{key}/pypi-tracks/{project}';
11926
+ };
11927
+
11928
+ export type PutPypiTrackErrors = {
11929
+ /**
11930
+ * Invalid request or repository type
11931
+ */
11932
+ 400: unknown;
11933
+ /**
11934
+ * Authentication required
11935
+ */
11936
+ 401: unknown;
11937
+ /**
11938
+ * Repository not found
11939
+ */
11940
+ 404: unknown;
11941
+ };
11942
+
11943
+ export type PutPypiTrackResponses = {
11944
+ /**
11945
+ * tracks declaration stored
11946
+ */
11947
+ 200: PypiTrackResponse;
11948
+ };
11949
+
11950
+ export type PutPypiTrackResponse = PutPypiTrackResponses[keyof PutPypiTrackResponses];
11951
+
11952
+ export type DeleteRoutingRulesData = {
11953
+ body?: never;
11954
+ path: {
11955
+ /**
11956
+ * Repository key
11957
+ */
11958
+ key: string;
11959
+ };
11960
+ query?: never;
11961
+ url: '/api/v1/repositories/{key}/routing-rules';
11962
+ };
11963
+
11964
+ export type DeleteRoutingRulesErrors = {
11965
+ /**
11966
+ * Authentication required
11967
+ */
11968
+ 401: unknown;
11969
+ /**
11970
+ * Repository not found
11971
+ */
11972
+ 404: unknown;
11973
+ };
11974
+
11975
+ export type DeleteRoutingRulesResponses = {
11976
+ /**
11977
+ * Routing rules deleted
11978
+ */
11979
+ 200: unknown;
11980
+ };
11981
+
11982
+ export type GetRoutingRulesData = {
11983
+ body?: never;
11984
+ path: {
11985
+ /**
11986
+ * Repository key
11987
+ */
11988
+ key: string;
11989
+ };
11990
+ query?: never;
11991
+ url: '/api/v1/repositories/{key}/routing-rules';
11992
+ };
11993
+
11994
+ export type GetRoutingRulesErrors = {
11995
+ /**
11996
+ * Repository not found
11997
+ */
11998
+ 404: unknown;
11999
+ };
12000
+
12001
+ export type GetRoutingRulesResponses = {
12002
+ /**
12003
+ * Current routing rules
12004
+ */
12005
+ 200: RoutingRulesResponse;
12006
+ };
12007
+
12008
+ export type GetRoutingRulesResponse = GetRoutingRulesResponses[keyof GetRoutingRulesResponses];
12009
+
12010
+ export type SetRoutingRulesData = {
12011
+ body: SetRoutingRulesRequest;
12012
+ path: {
12013
+ /**
12014
+ * Repository key
12015
+ */
12016
+ key: string;
12017
+ };
12018
+ query?: never;
12019
+ url: '/api/v1/repositories/{key}/routing-rules';
12020
+ };
12021
+
12022
+ export type SetRoutingRulesErrors = {
12023
+ /**
12024
+ * Invalid rule (bad regex or capture reference)
12025
+ */
12026
+ 400: unknown;
12027
+ /**
12028
+ * Authentication required
12029
+ */
12030
+ 401: unknown;
12031
+ /**
12032
+ * Repository not found
12033
+ */
12034
+ 404: unknown;
12035
+ };
12036
+
12037
+ export type SetRoutingRulesResponses = {
12038
+ /**
12039
+ * Routing rules saved
12040
+ */
12041
+ 200: RoutingRulesResponse;
12042
+ };
12043
+
12044
+ export type SetRoutingRulesResponse = SetRoutingRulesResponses[keyof SetRoutingRulesResponses];
12045
+
10217
12046
  export type GetRepoSecurityData = {
10218
12047
  body?: never;
10219
12048
  path: {
@@ -10256,98 +12085,254 @@ export type UpdateRepoSecurityData = {
10256
12085
  url: '/api/v1/repositories/{key}/security';
10257
12086
  };
10258
12087
 
10259
- export type UpdateRepoSecurityErrors = {
12088
+ export type UpdateRepoSecurityErrors = {
12089
+ /**
12090
+ * Repository not found
12091
+ */
12092
+ 404: ErrorResponse;
12093
+ };
12094
+
12095
+ export type UpdateRepoSecurityError = UpdateRepoSecurityErrors[keyof UpdateRepoSecurityErrors];
12096
+
12097
+ export type UpdateRepoSecurityResponses = {
12098
+ /**
12099
+ * Repository security config updated
12100
+ */
12101
+ 200: ScanConfigResponse;
12102
+ };
12103
+
12104
+ export type UpdateRepoSecurityResponse = UpdateRepoSecurityResponses[keyof UpdateRepoSecurityResponses];
12105
+
12106
+ export type ListRepoScansData = {
12107
+ body?: never;
12108
+ path: {
12109
+ /**
12110
+ * Repository key
12111
+ */
12112
+ key: string;
12113
+ };
12114
+ query?: {
12115
+ repository_id?: string | null;
12116
+ artifact_id?: string | null;
12117
+ status?: string | null;
12118
+ page?: number | null;
12119
+ per_page?: number | null;
12120
+ };
12121
+ url: '/api/v1/repositories/{key}/security/scans';
12122
+ };
12123
+
12124
+ export type ListRepoScansErrors = {
12125
+ /**
12126
+ * Repository not found
12127
+ */
12128
+ 404: ErrorResponse;
12129
+ };
12130
+
12131
+ export type ListRepoScansError = ListRepoScansErrors[keyof ListRepoScansErrors];
12132
+
12133
+ export type ListRepoScansResponses = {
12134
+ /**
12135
+ * Paginated list of scans for a repository
12136
+ */
12137
+ 200: ScanListResponse;
12138
+ };
12139
+
12140
+ export type ListRepoScansResponse = ListRepoScansResponses[keyof ListRepoScansResponses];
12141
+
12142
+ export type TestUpstreamData = {
12143
+ body?: never;
12144
+ path: {
12145
+ /**
12146
+ * Repository key
12147
+ */
12148
+ key: string;
12149
+ };
12150
+ query?: never;
12151
+ url: '/api/v1/repositories/{key}/test-upstream';
12152
+ };
12153
+
12154
+ export type TestUpstreamErrors = {
12155
+ /**
12156
+ * Repository is not remote or has no upstream URL
12157
+ */
12158
+ 400: unknown;
12159
+ /**
12160
+ * Authentication required
12161
+ */
12162
+ 401: unknown;
12163
+ /**
12164
+ * Repository not found
12165
+ */
12166
+ 404: unknown;
12167
+ /**
12168
+ * Upstream unreachable
12169
+ */
12170
+ 502: unknown;
12171
+ };
12172
+
12173
+ export type TestUpstreamResponses = {
12174
+ /**
12175
+ * Upstream reachable
12176
+ */
12177
+ 200: unknown;
12178
+ };
12179
+
12180
+ export type ListRepoTokensData = {
12181
+ body?: never;
12182
+ path: {
12183
+ /**
12184
+ * Repository key
12185
+ */
12186
+ key: string;
12187
+ };
12188
+ query?: never;
12189
+ url: '/api/v1/repositories/{key}/tokens';
12190
+ };
12191
+
12192
+ export type ListRepoTokensErrors = {
12193
+ /**
12194
+ * Not authenticated
12195
+ */
12196
+ 401: unknown;
12197
+ /**
12198
+ * Insufficient permissions
12199
+ */
12200
+ 403: unknown;
12201
+ /**
12202
+ * Repository not found
12203
+ */
12204
+ 404: unknown;
12205
+ };
12206
+
12207
+ export type ListRepoTokensResponses = {
12208
+ /**
12209
+ * List of tokens on this repository
12210
+ */
12211
+ 200: RepoTokenListResponse;
12212
+ };
12213
+
12214
+ export type ListRepoTokensResponse = ListRepoTokensResponses[keyof ListRepoTokensResponses];
12215
+
12216
+ export type CreateRepoTokenData = {
12217
+ body: CreateRepoTokenRequest;
12218
+ path: {
12219
+ /**
12220
+ * Repository key
12221
+ */
12222
+ key: string;
12223
+ };
12224
+ query?: never;
12225
+ url: '/api/v1/repositories/{key}/tokens';
12226
+ };
12227
+
12228
+ export type CreateRepoTokenErrors = {
12229
+ /**
12230
+ * Validation error
12231
+ */
12232
+ 400: unknown;
12233
+ /**
12234
+ * Not authenticated
12235
+ */
12236
+ 401: unknown;
12237
+ /**
12238
+ * Insufficient permissions
12239
+ */
12240
+ 403: unknown;
10260
12241
  /**
10261
12242
  * Repository not found
10262
12243
  */
10263
- 404: ErrorResponse;
12244
+ 404: unknown;
10264
12245
  };
10265
12246
 
10266
- export type UpdateRepoSecurityError = UpdateRepoSecurityErrors[keyof UpdateRepoSecurityErrors];
10267
-
10268
- export type UpdateRepoSecurityResponses = {
12247
+ export type CreateRepoTokenResponses = {
10269
12248
  /**
10270
- * Repository security config updated
12249
+ * Token created (value shown once)
10271
12250
  */
10272
- 200: ScanConfigResponse;
12251
+ 200: CreateRepoTokenResponse;
10273
12252
  };
10274
12253
 
10275
- export type UpdateRepoSecurityResponse = UpdateRepoSecurityResponses[keyof UpdateRepoSecurityResponses];
12254
+ export type CreateRepoTokenResponse2 = CreateRepoTokenResponses[keyof CreateRepoTokenResponses];
10276
12255
 
10277
- export type ListRepoScansData = {
12256
+ export type RevokeRepoTokenData = {
10278
12257
  body?: never;
10279
12258
  path: {
10280
12259
  /**
10281
12260
  * Repository key
10282
12261
  */
10283
12262
  key: string;
12263
+ /**
12264
+ * Token ID
12265
+ */
12266
+ token_id: string;
10284
12267
  };
10285
- query?: {
10286
- repository_id?: string | null;
10287
- artifact_id?: string | null;
10288
- status?: string | null;
10289
- page?: number | null;
10290
- per_page?: number | null;
10291
- };
10292
- url: '/api/v1/repositories/{key}/security/scans';
12268
+ query?: never;
12269
+ url: '/api/v1/repositories/{key}/tokens/{token_id}';
10293
12270
  };
10294
12271
 
10295
- export type ListRepoScansErrors = {
12272
+ export type RevokeRepoTokenErrors = {
10296
12273
  /**
10297
- * Repository not found
12274
+ * Not authenticated
10298
12275
  */
10299
- 404: ErrorResponse;
12276
+ 401: unknown;
12277
+ /**
12278
+ * Insufficient permissions
12279
+ */
12280
+ 403: unknown;
12281
+ /**
12282
+ * Repository or token not found
12283
+ */
12284
+ 404: unknown;
10300
12285
  };
10301
12286
 
10302
- export type ListRepoScansError = ListRepoScansErrors[keyof ListRepoScansErrors];
10303
-
10304
- export type ListRepoScansResponses = {
12287
+ export type RevokeRepoTokenResponses = {
10305
12288
  /**
10306
- * Paginated list of scans for a repository
12289
+ * Token revoked
10307
12290
  */
10308
- 200: ScanListResponse;
12291
+ 204: void;
10309
12292
  };
10310
12293
 
10311
- export type ListRepoScansResponse = ListRepoScansResponses[keyof ListRepoScansResponses];
12294
+ export type RevokeRepoTokenResponse = RevokeRepoTokenResponses[keyof RevokeRepoTokenResponses];
10312
12295
 
10313
- export type TestUpstreamData = {
12296
+ export type GetRepoTokenData = {
10314
12297
  body?: never;
10315
12298
  path: {
10316
12299
  /**
10317
12300
  * Repository key
10318
12301
  */
10319
12302
  key: string;
12303
+ /**
12304
+ * Token ID
12305
+ */
12306
+ token_id: string;
10320
12307
  };
10321
12308
  query?: never;
10322
- url: '/api/v1/repositories/{key}/test-upstream';
12309
+ url: '/api/v1/repositories/{key}/tokens/{token_id}';
10323
12310
  };
10324
12311
 
10325
- export type TestUpstreamErrors = {
10326
- /**
10327
- * Repository is not remote or has no upstream URL
10328
- */
10329
- 400: unknown;
12312
+ export type GetRepoTokenErrors = {
10330
12313
  /**
10331
- * Authentication required
12314
+ * Not authenticated
10332
12315
  */
10333
12316
  401: unknown;
10334
12317
  /**
10335
- * Repository not found
12318
+ * Insufficient permissions
10336
12319
  */
10337
- 404: unknown;
12320
+ 403: unknown;
10338
12321
  /**
10339
- * Upstream unreachable
12322
+ * Repository or token not found
10340
12323
  */
10341
- 502: unknown;
12324
+ 404: unknown;
10342
12325
  };
10343
12326
 
10344
- export type TestUpstreamResponses = {
12327
+ export type GetRepoTokenResponses = {
10345
12328
  /**
10346
- * Upstream reachable
12329
+ * Token details
10347
12330
  */
10348
- 200: unknown;
12331
+ 200: RepoTokenResponse;
10349
12332
  };
10350
12333
 
12334
+ export type GetRepoTokenResponse = GetRepoTokenResponses[keyof GetRepoTokenResponses];
12335
+
10351
12336
  export type SetUpstreamAuthData = {
10352
12337
  body: UpstreamAuthRequest;
10353
12338
  path: {
@@ -10486,16 +12471,83 @@ export type CheckLicenseComplianceResponses = {
10486
12471
 
10487
12472
  export type CheckLicenseComplianceResponse = CheckLicenseComplianceResponses[keyof CheckLicenseComplianceResponses];
10488
12473
 
10489
- export type GetCveHistoryData = {
12474
+ export type GetCveHistoryByArtifactData = {
10490
12475
  body?: never;
10491
12476
  path: {
10492
12477
  /**
10493
- * Artifact ID
12478
+ * Artifact UUID
10494
12479
  */
10495
12480
  artifact_id: string;
10496
12481
  };
10497
12482
  query?: never;
10498
- url: '/api/v1/sbom/cve/history/{artifact_id}';
12483
+ url: '/api/v1/sbom/cve/history/by-artifact/{artifact_id}';
12484
+ };
12485
+
12486
+ export type GetCveHistoryByArtifactErrors = {
12487
+ /**
12488
+ * Caller does not have access to this artifact's repository
12489
+ */
12490
+ 403: unknown;
12491
+ /**
12492
+ * Artifact not found
12493
+ */
12494
+ 404: unknown;
12495
+ };
12496
+
12497
+ export type GetCveHistoryByArtifactResponses = {
12498
+ /**
12499
+ * CVE history entries
12500
+ */
12501
+ 200: Array<CveHistoryEntry>;
12502
+ };
12503
+
12504
+ export type GetCveHistoryByArtifactResponse = GetCveHistoryByArtifactResponses[keyof GetCveHistoryByArtifactResponses];
12505
+
12506
+ export type GetCveHistoryByCveData = {
12507
+ body?: never;
12508
+ path: {
12509
+ /**
12510
+ * CVE identifier (e.g. CVE-2019-10744)
12511
+ */
12512
+ cve_id: string;
12513
+ };
12514
+ query?: never;
12515
+ url: '/api/v1/sbom/cve/history/by-cve/{cve_id}';
12516
+ };
12517
+
12518
+ export type GetCveHistoryByCveErrors = {
12519
+ /**
12520
+ * Path id is not a valid CVE identifier
12521
+ */
12522
+ 400: unknown;
12523
+ };
12524
+
12525
+ export type GetCveHistoryByCveResponses = {
12526
+ /**
12527
+ * CVE history entries
12528
+ */
12529
+ 200: Array<CveHistoryEntry>;
12530
+ };
12531
+
12532
+ export type GetCveHistoryByCveResponse = GetCveHistoryByCveResponses[keyof GetCveHistoryByCveResponses];
12533
+
12534
+ export type GetCveHistoryData = {
12535
+ body?: never;
12536
+ path: {
12537
+ /**
12538
+ * Artifact UUID or CVE identifier (e.g. CVE-2019-10744). Prefer the typed routes /cve/history/by-artifact/{uuid} or /cve/history/by-cve/{cve_id}.
12539
+ */
12540
+ id: string;
12541
+ };
12542
+ query?: never;
12543
+ url: '/api/v1/sbom/cve/history/{id}';
12544
+ };
12545
+
12546
+ export type GetCveHistoryErrors = {
12547
+ /**
12548
+ * Path id is neither a valid UUID nor a valid CVE identifier
12549
+ */
12550
+ 400: unknown;
10499
12551
  };
10500
12552
 
10501
12553
  export type GetCveHistoryResponses = {
@@ -10507,6 +12559,48 @@ export type GetCveHistoryResponses = {
10507
12559
 
10508
12560
  export type GetCveHistoryResponse = GetCveHistoryResponses[keyof GetCveHistoryResponses];
10509
12561
 
12562
+ export type UpdateCveStatusByArtifactCveData = {
12563
+ body: UpdateCveStatusRequest;
12564
+ path: {
12565
+ /**
12566
+ * Artifact UUID
12567
+ */
12568
+ artifact_id: string;
12569
+ /**
12570
+ * CVE identifier (e.g. CVE-2019-10744)
12571
+ */
12572
+ cve_id: string;
12573
+ };
12574
+ query?: never;
12575
+ url: '/api/v1/sbom/cve/status/by-artifact/{artifact_id}/by-cve/{cve_id}';
12576
+ };
12577
+
12578
+ export type UpdateCveStatusByArtifactCveErrors = {
12579
+ /**
12580
+ * Validation error (e.g. invalid CVE id or unsupported status)
12581
+ */
12582
+ 400: ErrorResponse;
12583
+ /**
12584
+ * Caller does not have access to this artifact's repository
12585
+ */
12586
+ 403: unknown;
12587
+ /**
12588
+ * No scan_findings rows match (artifact_id, cve_id)
12589
+ */
12590
+ 404: unknown;
12591
+ };
12592
+
12593
+ export type UpdateCveStatusByArtifactCveError = UpdateCveStatusByArtifactCveErrors[keyof UpdateCveStatusByArtifactCveErrors];
12594
+
12595
+ export type UpdateCveStatusByArtifactCveResponses = {
12596
+ /**
12597
+ * Updated synth CVE entry
12598
+ */
12599
+ 200: CveHistoryEntry;
12600
+ };
12601
+
12602
+ export type UpdateCveStatusByArtifactCveResponse = UpdateCveStatusByArtifactCveResponses[keyof UpdateCveStatusByArtifactCveResponses];
12603
+
10510
12604
  export type UpdateCveStatusData = {
10511
12605
  body: UpdateCveStatusRequest;
10512
12606
  path: {
@@ -10778,9 +12872,9 @@ export type ConvertSbomError = ConvertSbomErrors[keyof ConvertSbomErrors];
10778
12872
 
10779
12873
  export type ConvertSbomResponses = {
10780
12874
  /**
10781
- * Converted SBOM
12875
+ * Converted SBOM with content
10782
12876
  */
10783
- 200: SbomResponse;
12877
+ 200: SbomContentResponse;
10784
12878
  };
10785
12879
 
10786
12880
  export type ConvertSbomResponse = ConvertSbomResponses[keyof ConvertSbomResponses];
@@ -10975,6 +13069,15 @@ export type GetDashboardData = {
10975
13069
  url: '/api/v1/security/dashboard';
10976
13070
  };
10977
13071
 
13072
+ export type GetDashboardErrors = {
13073
+ /**
13074
+ * Admin privileges required
13075
+ */
13076
+ 403: ErrorResponse;
13077
+ };
13078
+
13079
+ export type GetDashboardError = GetDashboardErrors[keyof GetDashboardErrors];
13080
+
10978
13081
  export type GetDashboardResponses = {
10979
13082
  /**
10980
13083
  * Security dashboard summary
@@ -10997,6 +13100,10 @@ export type RevokeAcknowledgmentData = {
10997
13100
  };
10998
13101
 
10999
13102
  export type RevokeAcknowledgmentErrors = {
13103
+ /**
13104
+ * Admin privileges required
13105
+ */
13106
+ 403: ErrorResponse;
11000
13107
  /**
11001
13108
  * Finding not found
11002
13109
  */
@@ -11027,6 +13134,10 @@ export type AcknowledgeFindingData = {
11027
13134
  };
11028
13135
 
11029
13136
  export type AcknowledgeFindingErrors = {
13137
+ /**
13138
+ * Admin privileges required
13139
+ */
13140
+ 403: ErrorResponse;
11030
13141
  /**
11031
13142
  * Finding not found
11032
13143
  */
@@ -11189,10 +13300,14 @@ export type TriggerScanErrors = {
11189
13300
  * Validation error
11190
13301
  */
11191
13302
  400: ErrorResponse;
13303
+ /**
13304
+ * bypass_dedup requested by non-admin caller
13305
+ */
13306
+ 403: ErrorResponse;
11192
13307
  /**
11193
13308
  * Scanner service not configured
11194
13309
  */
11195
- 500: ErrorResponse;
13310
+ 503: ErrorResponse;
11196
13311
  };
11197
13312
 
11198
13313
  export type TriggerScanError = TriggerScanErrors[keyof TriggerScanErrors];
@@ -11298,6 +13413,15 @@ export type GetAllScoresData = {
11298
13413
  url: '/api/v1/security/scores';
11299
13414
  };
11300
13415
 
13416
+ export type GetAllScoresErrors = {
13417
+ /**
13418
+ * Admin privileges required
13419
+ */
13420
+ 403: ErrorResponse;
13421
+ };
13422
+
13423
+ export type GetAllScoresError = GetAllScoresErrors[keyof GetAllScoresErrors];
13424
+
11301
13425
  export type GetAllScoresResponses = {
11302
13426
  /**
11303
13427
  * All repository security scores
@@ -12127,6 +14251,22 @@ export type TogglePolicyResponses = {
12127
14251
 
12128
14252
  export type TogglePolicyResponse = TogglePolicyResponses[keyof TogglePolicyResponses];
12129
14253
 
14254
+ export type GetSystemConfigData = {
14255
+ body?: never;
14256
+ path?: never;
14257
+ query?: never;
14258
+ url: '/api/v1/system/config';
14259
+ };
14260
+
14261
+ export type GetSystemConfigResponses = {
14262
+ /**
14263
+ * Public runtime configuration
14264
+ */
14265
+ 200: SystemConfigResponse;
14266
+ };
14267
+
14268
+ export type GetSystemConfigResponse = GetSystemConfigResponses[keyof GetSystemConfigResponses];
14269
+
12130
14270
  export type GetTreeData = {
12131
14271
  body?: never;
12132
14272
  path?: never;
@@ -12227,6 +14367,10 @@ export type CreateSessionErrors = {
12227
14367
  * Unauthorized
12228
14368
  */
12229
14369
  401: unknown;
14370
+ /**
14371
+ * Forbidden
14372
+ */
14373
+ 403: ErrorResponse;
12230
14374
  /**
12231
14375
  * Repository not found
12232
14376
  */
@@ -12527,6 +14671,42 @@ export type UpdateUserResponses = {
12527
14671
 
12528
14672
  export type UpdateUserResponse = UpdateUserResponses[keyof UpdateUserResponses];
12529
14673
 
14674
+ export type ForcePasswordChangeData = {
14675
+ body?: never;
14676
+ path: {
14677
+ /**
14678
+ * User ID
14679
+ */
14680
+ id: string;
14681
+ };
14682
+ query?: never;
14683
+ url: '/api/v1/users/{id}/force-password-change';
14684
+ };
14685
+
14686
+ export type ForcePasswordChangeErrors = {
14687
+ /**
14688
+ * Only administrators can force password changes
14689
+ */
14690
+ 403: unknown;
14691
+ /**
14692
+ * User not found
14693
+ */
14694
+ 404: unknown;
14695
+ /**
14696
+ * Cannot force password change for SSO users
14697
+ */
14698
+ 422: unknown;
14699
+ };
14700
+
14701
+ export type ForcePasswordChangeResponses = {
14702
+ /**
14703
+ * Flag set successfully
14704
+ */
14705
+ 200: ForcePasswordChangeResponse;
14706
+ };
14707
+
14708
+ export type ForcePasswordChangeResponse2 = ForcePasswordChangeResponses[keyof ForcePasswordChangeResponses];
14709
+
12530
14710
  export type ChangePasswordData = {
12531
14711
  body: ChangePasswordRequest;
12532
14712
  path: {
@@ -12801,13 +14981,17 @@ export type CreateWebhookErrors = {
12801
14981
  * Internal server error
12802
14982
  */
12803
14983
  500: unknown;
14984
+ /**
14985
+ * A secret was supplied but AK_WEBHOOK_SECRET_KEY is not configured, so the secret cannot be encrypted at rest
14986
+ */
14987
+ 503: unknown;
12804
14988
  };
12805
14989
 
12806
14990
  export type CreateWebhookResponses = {
12807
14991
  /**
12808
- * Webhook created successfully
14992
+ * Webhook created. Body includes the raw secret exactly once (omitted when created unsigned).
12809
14993
  */
12810
- 200: WebhookResponse;
14994
+ 200: WebhookSecretCreatedResponse;
12811
14995
  };
12812
14996
 
12813
14997
  export type CreateWebhookResponse = CreateWebhookResponses[keyof CreateWebhookResponses];
@@ -12982,6 +15166,42 @@ export type EnableWebhookResponses = {
12982
15166
  200: unknown;
12983
15167
  };
12984
15168
 
15169
+ export type RotateWebhookSecretData = {
15170
+ body?: never;
15171
+ path: {
15172
+ /**
15173
+ * Webhook ID
15174
+ */
15175
+ id: string;
15176
+ };
15177
+ query?: never;
15178
+ url: '/api/v1/webhooks/{id}/rotate-secret';
15179
+ };
15180
+
15181
+ export type RotateWebhookSecretErrors = {
15182
+ /**
15183
+ * Webhook not found
15184
+ */
15185
+ 404: unknown;
15186
+ /**
15187
+ * A previous rotation overlap window is still active
15188
+ */
15189
+ 409: unknown;
15190
+ /**
15191
+ * Encryption key not configured
15192
+ */
15193
+ 500: unknown;
15194
+ };
15195
+
15196
+ export type RotateWebhookSecretResponses = {
15197
+ /**
15198
+ * Secret rotated. Body includes the new raw secret exactly once.
15199
+ */
15200
+ 200: RotateWebhookSecretResponse;
15201
+ };
15202
+
15203
+ export type RotateWebhookSecretResponse2 = RotateWebhookSecretResponses[keyof RotateWebhookSecretResponses];
15204
+
12985
15205
  export type TestWebhookData = {
12986
15206
  body?: never;
12987
15207
  path: {