@artifact-keeper/sdk 1.7.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.gen.ts CHANGED
@@ -80,7 +80,7 @@ export type AddProjectMemberRequest = {
80
80
  actions: Array<string>;
81
81
  principal_id: string;
82
82
  /**
83
- * "user" or "group".
83
+ * "user", "service_account" or "group".
84
84
  */
85
85
  principal_type: string;
86
86
  };
@@ -98,6 +98,13 @@ export type AdminUserResponse = {
98
98
  id: string;
99
99
  is_active: boolean;
100
100
  is_admin: boolean;
101
+ /**
102
+ * Whether this row is a service account rather than a person (#3634).
103
+ *
104
+ * `list_users` already read this column; it was dropped here, leaving
105
+ * clients no way to tell the two kinds of principal apart.
106
+ */
107
+ is_service_account: boolean;
101
108
  last_login_at?: string | null;
102
109
  must_change_password: boolean;
103
110
  username: string;
@@ -126,6 +133,10 @@ export type AffectedRepo = {
126
133
  export type AgeGateConfigResponse = {
127
134
  enabled: boolean;
128
135
  min_age_days: number;
136
+ /**
137
+ * Age-source mode: `upstream_publish_time` or `first_seen` (#2264).
138
+ */
139
+ mode: string;
129
140
  repository_key: string;
130
141
  };
131
142
 
@@ -169,11 +180,50 @@ export type AnnouncePeerRequest = {
169
180
  };
170
181
 
171
182
  export type ApiTokenCreatedResponse = {
183
+ /**
184
+ * When the token expires (`None` = never). Authoritative from the mint,
185
+ * including any expiration the instance policy applied (#3460).
186
+ */
187
+ expires_at?: string | null;
172
188
  id: string;
173
189
  name: string;
190
+ /**
191
+ * True when the instance token expiration policy shaped this mint
192
+ * (applied a default or enforced the permitted range).
193
+ */
194
+ policy_applied: boolean;
174
195
  token: string;
175
196
  };
176
197
 
198
+ /**
199
+ * The API token expiration policy, as stored and as served by the admin API.
200
+ */
201
+ export type ApiTokenExpiryPolicy = {
202
+ /**
203
+ * Whether service-account token mints are subject to the policy.
204
+ * Defaults to false: expiring the credential a pipeline runs on is an
205
+ * outage on a schedule, so it must be an explicit opt-in.
206
+ */
207
+ apply_to_service_accounts?: boolean;
208
+ /**
209
+ * Applied when an enforced request omits `expires_in_days`. `None`
210
+ * means such requests are rejected instead.
211
+ */
212
+ default_days?: number | null;
213
+ /**
214
+ * Maximum acceptable `expires_in_days` while enforcing (inclusive).
215
+ */
216
+ max_days: number;
217
+ /**
218
+ * Minimum acceptable `expires_in_days` while enforcing (inclusive).
219
+ */
220
+ min_days: number;
221
+ /**
222
+ * When false the policy is entirely inert (historical behaviour).
223
+ */
224
+ require_expiration: boolean;
225
+ };
226
+
177
227
  export type ApiTokenListResponse = {
178
228
  items: Array<ApiTokenResponse>;
179
229
  };
@@ -398,6 +448,24 @@ export type ArtifactResponse = {
398
448
  */
399
449
  revision?: number | null;
400
450
  size_bytes: number;
451
+ /**
452
+ * Id of the user that uploaded this artifact (#3271), mirroring
453
+ * [`ArtifactVersionResponse::uploaded_by`] (#2397). Always serialized —
454
+ * `null` for anonymous/unknown uploads and for proxy-cached objects,
455
+ * which have no `artifacts` row — so the UI can rely on the key being
456
+ * present.
457
+ */
458
+ uploaded_by?: string | null;
459
+ /**
460
+ * Display name for [`Self::uploaded_by`], resolved server-side so the UI
461
+ * does not have to follow a bare UUID with an admin-only user lookup
462
+ * (#3271). `null` whenever `uploaded_by` is `null`, and also when the
463
+ * referenced user row no longer exists (a deleted account leaves the id
464
+ * on the artifact). Populated by the listing and per-artifact metadata
465
+ * endpoints; other responses that build an `ArtifactResponse` leave it
466
+ * unresolved.
467
+ */
468
+ uploaded_by_username?: string | null;
401
469
  version?: string | null;
402
470
  /**
403
471
  * Optional human tag recorded for this revision (from the
@@ -529,6 +597,26 @@ export type AuditLogListResponse = {
529
597
  * Authentication provider availability.
530
598
  */
531
599
  export type AuthConfig = {
600
+ /**
601
+ * Whether the verified-admin break-glass local login path is available
602
+ * (issue #2571). Unlike `local_login_enabled` — which only advertises
603
+ * the full local form on explicit `ALLOW_LOCAL_ADMIN_LOGIN=true` opt-in —
604
+ * this reflects the default #443 break-glass: with SSO enabled it is
605
+ * `true` unless the operator opted into strict SSO-only via
606
+ * `SSO_DISABLE_ADMIN_BREAK_GLASS`. Display-only: the login endpoint
607
+ * independently enforces the same policy
608
+ * (`api::handlers::auth::local_login_gate`), so this flag never grants
609
+ * access by itself.
610
+ *
611
+ * **Admin-only (#3489).** It answers "is there a local admin password
612
+ * path into this instance?", which is exactly the recon an anonymous
613
+ * attacker wants before probing `/api/v1/auth/login`, so it is omitted
614
+ * for anonymous and non-admin callers like the other security-posture
615
+ * fields. The login UI does not consume it — it decides whether to show
616
+ * the credentials form from `local_login_enabled`, and `?fallback=local`
617
+ * remains the admin recovery route.
618
+ */
619
+ admin_break_glass_enabled?: boolean | null;
532
620
  /**
533
621
  * Whether an LDAP directory is configured.
534
622
  */
@@ -549,6 +637,16 @@ export type AuthConfig = {
549
637
  * Whether an OIDC provider is configured.
550
638
  */
551
639
  oidc_enabled: boolean;
640
+ /**
641
+ * Whether the web UI should attempt silent SSO auto-login (an invisible
642
+ * OIDC `prompt=none` check-sso probe) when an OIDC provider is enabled.
643
+ * Kill switch: `OIDC_SILENT_SSO=false` (default `true`). Display-only:
644
+ * the flag only tells the frontend whether to *initiate* the silent
645
+ * attempt; the SSO endpoints enforce all authentication policy
646
+ * themselves, and anonymous visitors are never redirected to a visible
647
+ * IdP login page by the silent flow.
648
+ */
649
+ silent_sso_enabled: boolean;
552
650
  /**
553
651
  * Whether SAML SSO is configured (derived from the SSO admin settings in the DB,
554
652
  * but for this endpoint we report whether the OIDC issuer is set as a proxy).
@@ -556,6 +654,35 @@ export type AuthConfig = {
556
654
  sso_enabled: boolean;
557
655
  };
558
656
 
657
+ /**
658
+ * Non-secret provider settings for an `aws_ecr` / `aws_codeartifact` upstream
659
+ * (#1559).
660
+ */
661
+ export type AwsUpstreamAuthRequest = {
662
+ /**
663
+ * CodeArtifact only: domain name. Required for `aws_codeartifact`.
664
+ */
665
+ domain?: string | null;
666
+ /**
667
+ * CodeArtifact only: account id owning the domain. Defaults to the
668
+ * caller's account.
669
+ */
670
+ domain_owner?: string | null;
671
+ /**
672
+ * CodeArtifact only: requested token lifetime in seconds (0, or
673
+ * 900..=43200). Defaults to the AWS default of 12 hours.
674
+ */
675
+ duration_seconds?: number | null;
676
+ /**
677
+ * AWS region of the registry or domain, e.g. `us-east-1`.
678
+ */
679
+ region: string;
680
+ /**
681
+ * ECR only: registry (account) id, used to pin the upstream host.
682
+ */
683
+ registry_id?: string | null;
684
+ };
685
+
559
686
  export type BackupListResponse = {
560
687
  items: Array<BackupResponse>;
561
688
  total: number;
@@ -575,6 +702,41 @@ export type BackupResponse = {
575
702
  type: string;
576
703
  };
577
704
 
705
+ /**
706
+ * What this registry knows about a base image: filled in only when the
707
+ * reference names an image stored here (a local repository, or a remote
708
+ * repository's cache), otherwise `found: false` and the console falls back
709
+ * to guessing from the name.
710
+ */
711
+ export type BaseImageInfo = {
712
+ architecture?: string | null;
713
+ digest?: string | null;
714
+ found: boolean;
715
+ /**
716
+ * Whether the image carries conda.
717
+ */
718
+ has_conda: boolean;
719
+ /**
720
+ * Whether the image carries pip (a `pip install` in its history or a
721
+ * Python image label).
722
+ */
723
+ has_pip: boolean;
724
+ os?: string | null;
725
+ /**
726
+ * `<repo>/<image>:<tag>` inside this registry, when found.
727
+ */
728
+ reference?: string | null;
729
+ /**
730
+ * apt | dnf | microdnf | yum | apk, from the image's build history and
731
+ * labels; absent when the image does not say.
732
+ */
733
+ system_manager?: string | null;
734
+ /**
735
+ * The user the base image runs as; the spec's `user` defaults to it.
736
+ */
737
+ user?: string | null;
738
+ };
739
+
578
740
  /**
579
741
  * One downloader (or the anonymous bucket) of an affected artifact.
580
742
  */
@@ -613,6 +775,14 @@ export type BlastRadiusResponse = {
613
775
  downloaders: Array<BlastDownloader>;
614
776
  page: number;
615
777
  per_page: number;
778
+ /**
779
+ * Exposure through proxy-cached content (#3397).
780
+ */
781
+ proxy_exposure: ProxyBlastRadius;
782
+ /**
783
+ * **Hosted content only.** Every field here is artifact-keyed; see
784
+ * [`ProxyBlastRadius`] for proxy-cached exposure.
785
+ */
616
786
  summary: BlastRadiusSummary;
617
787
  target: BlastRadiusTargetInfo;
618
788
  /**
@@ -925,9 +1095,20 @@ export type CiOidcToggleRequest = {
925
1095
 
926
1096
  export type CiTokenRequest = {
927
1097
  /**
928
- * UUID of the `ci_oidc_providers` row to use for validation.
1098
+ * Optional UUID of the `ci_oidc_providers` row to validate against.
1099
+ *
1100
+ * Leave it out — and omit the body entirely — to have the provider
1101
+ * resolved from the assertion's own `iss` claim (#3548). The UUID is
1102
+ * server-generated and only published by the admin-only
1103
+ * `GET /api/v1/admin/ci-oidc`, so requiring it here meant a keyless CI
1104
+ * job had to authenticate with the admin password first.
1105
+ *
1106
+ * It is still honoured as an explicit override, for callers written
1107
+ * against the pre-#3548 shape and for instances that configure two
1108
+ * enabled providers on the same issuer. It must agree with the
1109
+ * assertion's `iss`; a provider that does not is a 400.
929
1110
  */
930
- provider_id: string;
1111
+ provider_id?: string | null;
931
1112
  };
932
1113
 
933
1114
  export type CiTokenResponse = {
@@ -1066,8 +1247,18 @@ export type CreateApiTokenRequest = {
1066
1247
  * Create API token response
1067
1248
  */
1068
1249
  export type CreateApiTokenResponse = {
1250
+ /**
1251
+ * When the token expires (`None` = never). Authoritative from the mint,
1252
+ * including any expiration the instance policy applied (#3460).
1253
+ */
1254
+ expires_at?: string | null;
1069
1255
  id: string;
1070
1256
  name: string;
1257
+ /**
1258
+ * True when the instance token expiration policy shaped this mint
1259
+ * (applied a default or enforced the permitted range).
1260
+ */
1261
+ policy_applied: boolean;
1071
1262
  token: string;
1072
1263
  };
1073
1264
 
@@ -1185,6 +1376,18 @@ export type CreateGroupRequest = {
1185
1376
  name: string;
1186
1377
  };
1187
1378
 
1379
+ export type CreateImageBuildRequest = {
1380
+ /**
1381
+ * Image path within the repository (`team/app`).
1382
+ */
1383
+ image: string;
1384
+ spec: ImageBuildSpec;
1385
+ /**
1386
+ * Tag to push (`2.56.0-genomics`).
1387
+ */
1388
+ tag: string;
1389
+ };
1390
+
1188
1391
  export type CreateInstanceRequest = {
1189
1392
  api_key: string;
1190
1393
  name: string;
@@ -1256,6 +1459,12 @@ export type CreateMigrationRequest = {
1256
1459
  };
1257
1460
 
1258
1461
  export type CreateOidcConfigRequest = {
1462
+ /**
1463
+ * IdP group whose members are granted the admin role on login.
1464
+ * Persisted as `attribute_mapping.admin_group`, the key the OIDC
1465
+ * callback reads for admin elevation (#3420).
1466
+ */
1467
+ admin_group?: string | null;
1259
1468
  /**
1260
1469
  * Opt-in compatibility flag (migration 144): when `true` the provider
1261
1470
  * accepts ID tokens signed with RSA keys shorter than 2048 bits via a
@@ -1342,8 +1551,18 @@ export type CreateRepoTokenRequest = {
1342
1551
  * contains the plaintext value and is only shown once.
1343
1552
  */
1344
1553
  export type CreateRepoTokenResponse = {
1554
+ /**
1555
+ * When the token expires (`None` = never). Authoritative from the mint,
1556
+ * including any expiration the instance policy applied (#3460).
1557
+ */
1558
+ expires_at?: string | null;
1345
1559
  id: string;
1346
1560
  name: string;
1561
+ /**
1562
+ * True when the instance token expiration policy shaped this mint
1563
+ * (applied a default or enforced the permitted range).
1564
+ */
1565
+ policy_applied: boolean;
1347
1566
  repository_key: string;
1348
1567
  /**
1349
1568
  * The full token value (only returned at creation time).
@@ -1456,7 +1675,7 @@ export type CreateRepositoryRequest = {
1456
1675
  * - Any other non-empty string — custom index prefix.
1457
1676
  *
1458
1677
  * Stored in `repository_config` under `pypi_upstream_index_path`.
1459
- * Only meaningful for PyPI / Poetry / Conda Remote repositories.
1678
+ * Only meaningful for PyPI / Poetry / Jupyter / Conda Remote repositories.
1460
1679
  */
1461
1680
  pypi_upstream_index_path?: string | null;
1462
1681
  quota_bytes?: number | null;
@@ -1531,6 +1750,13 @@ export type CreateSamlConfigRequest = {
1531
1750
  require_signed_assertions?: boolean | null;
1532
1751
  sign_requests?: boolean | null;
1533
1752
  slo_url?: string | null;
1753
+ /**
1754
+ * Optional URL-safe alias for the public SAML routes (#2583). Must
1755
+ * match `^[a-z0-9][a-z0-9_-]*$`, be at most 64 characters, not look
1756
+ * like a UUID, and be unique across SAML configurations. Omit it to
1757
+ * keep the configuration addressable by its `id` only.
1758
+ */
1759
+ slug?: string | null;
1534
1760
  sp_entity_id?: string | null;
1535
1761
  sso_url: string;
1536
1762
  /**
@@ -1671,8 +1897,18 @@ export type CreateTokenRequest = {
1671
1897
  };
1672
1898
 
1673
1899
  export type CreateTokenResponse = {
1900
+ /**
1901
+ * When the token expires (`None` = never). Service-account tokens are
1902
+ * exempt from the instance expiration policy unless the admin opted them
1903
+ * in (`apply_to_service_accounts`) (#3460).
1904
+ */
1905
+ expires_at?: string | null;
1674
1906
  id: string;
1675
1907
  name: string;
1908
+ /**
1909
+ * True when the instance token expiration policy shaped this mint.
1910
+ */
1911
+ policy_applied: boolean;
1676
1912
  token: string;
1677
1913
  };
1678
1914
 
@@ -1735,17 +1971,6 @@ export type CreatedGroupRow = {
1735
1971
  updated_at: string;
1736
1972
  };
1737
1973
 
1738
- export type CreatedPermissionRow = {
1739
- actions: Array<string>;
1740
- created_at: string;
1741
- id: string;
1742
- principal_id: string;
1743
- principal_type: string;
1744
- target_id: string;
1745
- target_type: string;
1746
- updated_at: string;
1747
- };
1748
-
1749
1974
  export type CurationCreateRuleRequest = {
1750
1975
  action: string;
1751
1976
  architecture?: string;
@@ -1782,6 +2007,19 @@ export type CurationCreateRuleRequest = {
1782
2007
 
1783
2008
  export type CurationPackageResponse = {
1784
2009
  architecture?: string | null;
2010
+ attestation_error?: string | null;
2011
+ attestation_identity?: string | null;
2012
+ attestation_issuer?: string | null;
2013
+ attestation_owner?: string | null;
2014
+ /**
2015
+ * Attestation verification record (#2955, surfaced by #3230):
2016
+ * `unverified` | `verified` | `failed`, with the certificate-bound identity
2017
+ * on success and the specific failing check otherwise. Without these an
2018
+ * operator cannot answer "which packages verified, and against which
2019
+ * certificate identity" without querying the database directly.
2020
+ */
2021
+ attestation_state: string;
2022
+ attestation_verified_at?: string | null;
1785
2023
  checksum_sha256?: string | null;
1786
2024
  evaluated_at?: string | null;
1787
2025
  evaluated_by?: string | null;
@@ -2422,6 +2660,60 @@ export type DtVulnerability = {
2422
2660
  vulnId: string;
2423
2661
  };
2424
2662
 
2663
+ /**
2664
+ * Per-repository egress proxy settings (#2469, #2811).
2665
+ *
2666
+ * `proxy_url` is **write-only**: it is encrypted at rest and never returned.
2667
+ * [`EgressProxyResponse`] echoes a redacted form (`http:/***@proxy:3128`)
2668
+ * so an operator can confirm the host and port without recovering the
2669
+ * credentials, exactly as `upstream_auth_configured` does for upstream
2670
+ * credentials.
2671
+ */
2672
+ export type EgressProxyRequest = {
2673
+ /**
2674
+ * `inherit` (follow the process `HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY`
2675
+ * environment — the default), `direct` (never proxy this repository, even
2676
+ * when the environment sets one), or `explicit` (use `proxy_url`, ignoring
2677
+ * the environment entirely).
2678
+ */
2679
+ mode: string;
2680
+ /**
2681
+ * Comma-separated hosts / domain suffixes / CIDRs that bypass the proxy
2682
+ * for this repository. Only meaningful when `mode` is `explicit`.
2683
+ */
2684
+ no_proxy?: string | null;
2685
+ /**
2686
+ * Proxy endpoint, `scheme://host[:port]`, http or https. May embed
2687
+ * `user:pass@` credentials. Required when `mode` is `explicit`.
2688
+ * Write-only, never returned in responses.
2689
+ */
2690
+ proxy_url?: string | null;
2691
+ };
2692
+
2693
+ /**
2694
+ * Read-back of a repository's egress-proxy settings. Carries no secret.
2695
+ */
2696
+ export type EgressProxyResponse = {
2697
+ /**
2698
+ * `inherit`, `direct` or `explicit`.
2699
+ */
2700
+ mode: string;
2701
+ /**
2702
+ * The configured bypass list, if any.
2703
+ */
2704
+ no_proxy?: string | null;
2705
+ /**
2706
+ * Whether the configured proxy URL carries credentials. The credentials
2707
+ * themselves are never returned.
2708
+ */
2709
+ proxy_credentials_configured: boolean;
2710
+ /**
2711
+ * The configured proxy with any credentials replaced by `***`. `None`
2712
+ * unless `mode` is `explicit`.
2713
+ */
2714
+ proxy_url?: string | null;
2715
+ };
2716
+
2425
2717
  export type EmailSubscriptionListResponse = {
2426
2718
  subscriptions: Array<EmailSubscriptionResponse>;
2427
2719
  };
@@ -2472,6 +2764,37 @@ export type ExchangeCodeResponse = {
2472
2764
  token_type: string;
2473
2765
  };
2474
2766
 
2767
+ /**
2768
+ * One finding as an external scanner reports it.
2769
+ *
2770
+ * Deliberately the wire shape of [`FindingResponse`] minus the fields the
2771
+ * server owns (ids, acknowledgment state, timestamps), so a scanner that can
2772
+ * read AK's findings can post findings back in the same vocabulary.
2773
+ */
2774
+ export type ExternalFindingInput = {
2775
+ affected_component?: string | null;
2776
+ affected_version?: string | null;
2777
+ cve_id?: string | null;
2778
+ description?: string | null;
2779
+ fixed_version?: string | null;
2780
+ /**
2781
+ * Scanner severity token. Normalized through the shared classifier, so a
2782
+ * vendor's own spelling (`Moderate`, `NEGLIGIBLE`, ...) is accepted.
2783
+ *
2784
+ * An UNRECOGNIZED token classifies as `high`, not `info` — fail-closed,
2785
+ * per #3306. An unknown verdict from an unknown scanner is the one case
2786
+ * where guessing low would silently disarm every gate that reads severity.
2787
+ */
2788
+ severity: string;
2789
+ /**
2790
+ * Vendor identity for this finding. Defaults to the submission's
2791
+ * `scanner` when omitted, and is what `?source=` filters on (#3410).
2792
+ */
2793
+ source?: string | null;
2794
+ source_url?: string | null;
2795
+ title: string;
2796
+ };
2797
+
2475
2798
  export type FacetValue = {
2476
2799
  count: number;
2477
2800
  value: string;
@@ -2656,6 +2979,18 @@ export type GroupRow = {
2656
2979
 
2657
2980
  /**
2658
2981
  * Growth summary for a time range.
2982
+ *
2983
+ * Computed from `storage_metrics` daily snapshots. **Accounting-basis note
2984
+ * (#3249):** snapshots taken before the #3134/#3249 fix summed
2985
+ * `artifacts.size_bytes` only, missing OCI layer/config blob bytes
2986
+ * (`oci_blobs`) and proxy-cached bytes (`proxy_cache_artifacts`) while
2987
+ * counting legacy backfilled `proxy-cache/%` rows. Those historical rows are
2988
+ * deliberately left as recorded — the source tables hold no history, so past
2989
+ * values cannot be recomputed, only fabricated. A growth series that spans
2990
+ * the fix date therefore shows a one-day upward step in
2991
+ * `storage_bytes_start/end` / `storage_growth_bytes` /
2992
+ * `storage_growth_percent` when the corrected accounting first lands; it is
2993
+ * a measurement correction, not real growth.
2659
2994
  */
2660
2995
  export type GrowthSummary = {
2661
2996
  artifacts_added: number;
@@ -2711,75 +3046,324 @@ export type IdentityResponse = {
2711
3046
  peer_id: string;
2712
3047
  };
2713
3048
 
2714
- export type InitTransferBody = {
2715
- artifact_id: string;
2716
- chunk_size?: number | null;
3049
+ export type ImageBuildListResponse = {
3050
+ items: Array<ImageBuildResponse>;
3051
+ total: number;
2717
3052
  };
2718
3053
 
2719
- /**
2720
- * Request to install a plugin from Git
2721
- */
2722
- export type InstallFromGitRequest = {
3054
+ export type ImageBuildResponse = {
3055
+ containerfile: string;
3056
+ created_at: string;
3057
+ digest?: string | null;
3058
+ error?: string | null;
3059
+ finished_at?: string | null;
3060
+ id: string;
3061
+ image: string;
3062
+ log_bytes: number;
2723
3063
  /**
2724
- * Git ref (tag, branch, or commit)
3064
+ * `<repo key>/<image>:<tag>` the reference within this registry.
2725
3065
  */
2726
- ref?: string | null;
3066
+ reference: string;
3067
+ repository_key: string;
3068
+ requested_by: string;
3069
+ spec: unknown;
3070
+ started_at?: string | null;
2727
3071
  /**
2728
- * Git repository URL
3072
+ * queued | running | succeeded | failed
2729
3073
  */
2730
- url: string;
3074
+ status: string;
3075
+ tag: string;
2731
3076
  };
2732
3077
 
2733
- /**
2734
- * Request for installing from local file path
2735
- */
2736
- export type InstallFromLocalRequest = {
3078
+ export type ImageBuildSettingsResponse = {
2737
3079
  /**
2738
- * Local filesystem path to plugin directory
3080
+ * Building is restricted to administrators on this instance.
2739
3081
  */
2740
- path: string;
2741
- };
2742
-
2743
- export type InvalidateCacheQuery = {
3082
+ admin_only: boolean;
2744
3083
  /**
2745
- * Artifact path to evict from the proxy cache. Same shape as the path
2746
- * segment of `GET /api/v1/repositories/{key}/artifacts/{path}`.
2747
- * Path-traversal segments such as `..` are rejected by
2748
- * `ProxyService::cache_storage_key` (covered by
2749
- * `test_invalidate_cache_by_key_rejects_invalid_path`).
3084
+ * Whole-Dockerfile specs are accepted on this instance.
2750
3085
  */
2751
- path: string;
3086
+ allow_dockerfile: boolean;
3087
+ allow_run: boolean;
3088
+ base_allowlist: Array<string>;
3089
+ /**
3090
+ * Whether the caller may build here: repository write access, plus
3091
+ * admin when `admin_only`.
3092
+ */
3093
+ caller_may_build: boolean;
3094
+ /**
3095
+ * False when `AK_BUILDKIT_ADDR` / `AK_IMAGE_BUILD_PUSH_REGISTRY` are unset.
3096
+ */
3097
+ enabled: boolean;
3098
+ max_concurrent: number;
3099
+ /**
3100
+ * The pip index every generated `pip install` uses, when configured.
3101
+ */
3102
+ pip_index_url?: string | null;
3103
+ /**
3104
+ * The address buildkitd pushes to, for display.
3105
+ */
3106
+ push_registry?: string | null;
3107
+ /**
3108
+ * Whether this repository can receive builds (local container repo).
3109
+ */
3110
+ repository_buildable: boolean;
3111
+ /**
3112
+ * Package managers a spec may install with, for the UI's dropdown.
3113
+ */
3114
+ supported_package_managers: Array<string>;
3115
+ timeout_secs: number;
2752
3116
  };
2753
3117
 
2754
- export type InvalidateCacheResponse = {
2755
- invalidated: boolean;
2756
- path: string;
2757
- repository_key: string;
3118
+ /**
3119
+ * What a user asks for. Either a structured spec (`base_image` plus
3120
+ * package groups, env, labels, user, workdir) or, when the instance allows
3121
+ * it, a whole `dockerfile` the server only checks and stamps.
3122
+ */
3123
+ export type ImageBuildSpec = {
3124
+ apt?: Array<string>;
3125
+ /**
3126
+ * The image to build on (`python:3.12-slim`); must match the
3127
+ * administrator's base allowlist when one is configured. Ignored when
3128
+ * `dockerfile` is set (its FROM lines are checked instead).
3129
+ */
3130
+ base_image?: string;
3131
+ conda?: Array<string>;
3132
+ conda_channels?: Array<string>;
3133
+ /**
3134
+ * A complete Dockerfile replacing the structured fields; accepted only
3135
+ * when `AK_IMAGE_BUILD_ALLOW_DOCKERFILE=true`. Every FROM must match the
3136
+ * base allowlist; the spec label is appended so inspection still knows
3137
+ * what the image came from.
3138
+ */
3139
+ dockerfile?: string | null;
3140
+ /**
3141
+ * Environment variables baked into the image.
3142
+ */
3143
+ env?: {
3144
+ [key: string]: string;
3145
+ };
3146
+ /**
3147
+ * OCI labels baked into the image.
3148
+ */
3149
+ labels?: {
3150
+ [key: string]: string;
3151
+ };
3152
+ /**
3153
+ * Build pip groups in a separate stage and copy only the installed
3154
+ * packages into the final image, so build tooling and caches never ship.
3155
+ */
3156
+ multistage?: boolean;
3157
+ /**
3158
+ * Install steps, rendered in order.
3159
+ */
3160
+ packages?: Array<PackageGroup>;
3161
+ pip?: Array<string>;
3162
+ /**
3163
+ * Raw `RUN` lines. Refused unless `AK_IMAGE_BUILD_ALLOW_RUN=true`.
3164
+ */
3165
+ run?: Array<string>;
3166
+ /**
3167
+ * The user the image runs as (`app`, `1000`, `1000:100`). Required
3168
+ * when any system package group is present (they install as root).
3169
+ */
3170
+ user?: string | null;
3171
+ /**
3172
+ * Working directory the image starts in.
3173
+ */
3174
+ workdir?: string | null;
2758
3175
  };
2759
3176
 
2760
- export type IssueResponse = {
2761
- artifact_id: string;
2762
- category: string;
2763
- check_result_id: string;
2764
- created_at: string;
2765
- description?: string | null;
2766
- id: string;
2767
- is_suppressed: boolean;
2768
- location?: string | null;
2769
- severity: string;
2770
- suppressed_at?: string | null;
2771
- suppressed_by?: string | null;
2772
- suppressed_reason?: string | null;
2773
- title: string;
3177
+ export type ImageConfig = {
3178
+ cmd: Array<string>;
3179
+ entrypoint: Array<string>;
3180
+ env: {
3181
+ [key: string]: string;
3182
+ };
3183
+ exposed_ports: Array<string>;
3184
+ labels: {
3185
+ [key: string]: string;
3186
+ };
3187
+ user: string;
3188
+ working_dir: string;
2774
3189
  };
2775
3190
 
2776
- export type KeyListResponse = {
2777
- keys: Array<SigningKeyPublic>;
2778
- total: number;
3191
+ /**
3192
+ * One `history` row of the image config: the instruction that produced a
3193
+ * layer, joined to that layer when it produced one. This is the closest an
3194
+ * image gets to its Dockerfile when no provenance attestation carries the
3195
+ * real one.
3196
+ */
3197
+ export type ImageHistoryEntry = {
3198
+ comment?: string | null;
3199
+ created?: string | null;
3200
+ created_by: string;
3201
+ empty_layer: boolean;
3202
+ layer_digest?: string | null;
3203
+ size_bytes?: number | null;
2779
3204
  };
2780
3205
 
2781
- export type LabelEntrySchema = {
2782
- key: string;
3206
+ export type ImageInspect = {
3207
+ config: ImageConfig;
3208
+ /**
3209
+ * Digest of the manifest the details describe (the platform manifest
3210
+ * when `reference` resolved to an index).
3211
+ */
3212
+ digest: string;
3213
+ history: Array<ImageHistoryEntry>;
3214
+ /**
3215
+ * Digest of the index the reference points at, when it is one.
3216
+ */
3217
+ index_digest?: string | null;
3218
+ layers: Array<ImageLayer>;
3219
+ platforms: Array<ImagePlatform>;
3220
+ provenance?: null | ImageProvenance;
3221
+ /**
3222
+ * The reference that was inspected (`repo/image:tag`).
3223
+ */
3224
+ reference: string;
3225
+ size_bytes: number;
3226
+ /**
3227
+ * Which producer filled the document: `registry` (read from storage).
3228
+ */
3229
+ source: string;
3230
+ };
3231
+
3232
+ export type ImageLayer = {
3233
+ digest: string;
3234
+ media_type: string;
3235
+ size_bytes: number;
3236
+ };
3237
+
3238
+ export type ImagePlatform = {
3239
+ architecture: string;
3240
+ os: string;
3241
+ variant?: string | null;
3242
+ };
3243
+
3244
+ /**
3245
+ * What a BuildKit SLSA provenance attestation says about how the image
3246
+ * was built. `dockerfile` is present only for `mode=max` attestations,
3247
+ * which embed the source; the image builder always emits those.
3248
+ */
3249
+ export type ImageProvenance = {
3250
+ attestation_digest: string;
3251
+ build_type?: string | null;
3252
+ builder_id?: string | null;
3253
+ dockerfile?: string | null;
3254
+ dockerfile_name?: string | null;
3255
+ predicate_type?: string | null;
3256
+ };
3257
+
3258
+ /**
3259
+ * One external scanner's verdict on one artifact.
3260
+ */
3261
+ export type IngestExternalFindingsRequest = {
3262
+ /**
3263
+ * The artifact these findings are about.
3264
+ */
3265
+ artifact_id: string;
3266
+ /**
3267
+ * The findings. May be empty — a clean verdict is a verdict, and it is
3268
+ * what clears a previously-flagged artifact.
3269
+ */
3270
+ findings: Array<ExternalFindingInput>;
3271
+ /**
3272
+ * Vendor name, recorded as each finding's `source` unless the finding
3273
+ * overrides it. Required: an unattributed verdict cannot be filtered,
3274
+ * audited, or withdrawn.
3275
+ */
3276
+ scanner: string;
3277
+ /**
3278
+ * Vendor build/database version, recorded as `scan_results.scanner_version`.
3279
+ */
3280
+ scanner_version?: string | null;
3281
+ };
3282
+
3283
+ export type IngestExternalFindingsResponse = {
3284
+ artifact_id: string;
3285
+ findings_ingested: number;
3286
+ grade: string;
3287
+ repository_id: string;
3288
+ /**
3289
+ * The `scan_results` row written, already `completed`.
3290
+ */
3291
+ scan_id: string;
3292
+ /**
3293
+ * Repository security score after `recalculate_score`.
3294
+ */
3295
+ score: number;
3296
+ };
3297
+
3298
+ export type InitTransferBody = {
3299
+ artifact_id: string;
3300
+ chunk_size?: number | null;
3301
+ };
3302
+
3303
+ /**
3304
+ * Request to install a plugin from Git
3305
+ */
3306
+ export type InstallFromGitRequest = {
3307
+ /**
3308
+ * Git ref (tag, branch, or commit)
3309
+ */
3310
+ ref?: string | null;
3311
+ /**
3312
+ * Git repository URL
3313
+ */
3314
+ url: string;
3315
+ };
3316
+
3317
+ /**
3318
+ * Request for installing from local file path
3319
+ */
3320
+ export type InstallFromLocalRequest = {
3321
+ /**
3322
+ * Local filesystem path to plugin directory
3323
+ */
3324
+ path: string;
3325
+ };
3326
+
3327
+ export type InvalidateCacheQuery = {
3328
+ /**
3329
+ * Artifact path to evict from the proxy cache. Same shape as the path
3330
+ * segment of `GET /api/v1/repositories/{key}/artifacts/{path}`.
3331
+ * Path-traversal segments such as `..` are rejected by
3332
+ * `ProxyService::cache_storage_key` (covered by
3333
+ * `test_invalidate_cache_by_key_rejects_invalid_path`).
3334
+ */
3335
+ path: string;
3336
+ };
3337
+
3338
+ export type InvalidateCacheResponse = {
3339
+ invalidated: boolean;
3340
+ path: string;
3341
+ repository_key: string;
3342
+ };
3343
+
3344
+ export type IssueResponse = {
3345
+ artifact_id: string;
3346
+ category: string;
3347
+ check_result_id: string;
3348
+ created_at: string;
3349
+ description?: string | null;
3350
+ id: string;
3351
+ is_suppressed: boolean;
3352
+ location?: string | null;
3353
+ severity: string;
3354
+ suppressed_at?: string | null;
3355
+ suppressed_by?: string | null;
3356
+ suppressed_reason?: string | null;
3357
+ title: string;
3358
+ };
3359
+
3360
+ export type KeyListResponse = {
3361
+ keys: Array<SigningKeyPublic>;
3362
+ total: number;
3363
+ };
3364
+
3365
+ export type LabelEntrySchema = {
3366
+ key: string;
2783
3367
  value?: string;
2784
3368
  };
2785
3369
 
@@ -2842,6 +3426,78 @@ export type LdapTestResult = {
2842
3426
  success: boolean;
2843
3427
  };
2844
3428
 
3429
+ /**
3430
+ * One repository's before/after in a ledger backfill (#3650).
3431
+ */
3432
+ export type LedgerBackfillRepository = {
3433
+ /**
3434
+ * `artifacts` bytes, excluding soft-deleted rows and legacy
3435
+ * `proxy-cache/%` keys — migration 182's `hosted_bytes` rule verbatim.
3436
+ */
3437
+ after_hosted_bytes: number;
3438
+ /**
3439
+ * `oci_blobs` bytes (every row counts; a `pending_delete_at` marker is
3440
+ * not a deletion and does not change the figure).
3441
+ */
3442
+ after_oci_bytes: number;
3443
+ /**
3444
+ * `proxy_cache_artifacts` bytes (every row counts). A breakdown of
3445
+ * `after_total_bytes`, not a disjoint bucket.
3446
+ */
3447
+ after_proxy_bytes: number;
3448
+ /**
3449
+ * Ledger total after the backfill: `hosted + proxy + oci`, the same sum
3450
+ * `/admin/stats.total_storage_bytes` aggregates.
3451
+ */
3452
+ after_total_bytes: number;
3453
+ /**
3454
+ * Ledger total before the backfill, or `null` when the repository had no
3455
+ * ledger row at all. A database restored from backup is the `null` case:
3456
+ * the restore inserts `artifacts` / `oci_blobs` / `proxy_cache_artifacts`
3457
+ * rows without firing migration 182's triggers, so no ledger row is ever
3458
+ * written for them.
3459
+ */
3460
+ before_total_bytes?: number | null;
3461
+ /**
3462
+ * `after_total_bytes - before_total_bytes`, counting a missing row as 0.
3463
+ */
3464
+ drift_bytes: number;
3465
+ repository_id: string;
3466
+ repository_key: string;
3467
+ };
3468
+
3469
+ /**
3470
+ * Result of `POST /api/v1/admin/storage/ledger/backfill` (#3650).
3471
+ */
3472
+ export type LedgerBackfillResponse = {
3473
+ /**
3474
+ * `/admin/stats.total_storage_bytes` as it reads after the backfill.
3475
+ */
3476
+ after_total_storage_bytes: number;
3477
+ /**
3478
+ * `/admin/stats.total_storage_bytes` as it read before the backfill.
3479
+ */
3480
+ before_total_storage_bytes: number;
3481
+ /**
3482
+ * Per-repository detail, ordered by repository key.
3483
+ */
3484
+ repositories: Array<LedgerBackfillRepository>;
3485
+ repositories_checked: number;
3486
+ /**
3487
+ * Repositories whose ledger total changed.
3488
+ */
3489
+ repositories_repaired: number;
3490
+ /**
3491
+ * Repositories deleted between the scan and their recompute. Not an
3492
+ * error — the ledger row went with them.
3493
+ */
3494
+ repositories_skipped: number;
3495
+ /**
3496
+ * Sum of the absolute per-repository corrections, in bytes.
3497
+ */
3498
+ total_drift_bytes: number;
3499
+ };
3500
+
2845
3501
  /**
2846
3502
  * Result of license compliance check.
2847
3503
  */
@@ -3002,6 +3658,18 @@ export type ListSbomsQuery = {
3002
3658
  export type ListUsersQuery = {
3003
3659
  is_active?: boolean | null;
3004
3660
  is_admin?: boolean | null;
3661
+ /**
3662
+ * Filter on the service-account discriminator (#3634).
3663
+ *
3664
+ * Service accounts are rows in `users`, so an unfiltered listing mixes
3665
+ * them in with people. A client building a principal picker for
3666
+ * `POST /api/v1/permissions` must be able to exclude them: that endpoint's
3667
+ * `validate_principal` requires `principal_type = "service_account"` for
3668
+ * such a row and rejects it as `"user"`, so offering one under `user` is a
3669
+ * guaranteed 400. `None` keeps the historical unfiltered behavior, which
3670
+ * the audit actor filter and the group member picker both want.
3671
+ */
3672
+ is_service_account?: boolean | null;
3005
3673
  page?: number | null;
3006
3674
  per_page?: number | null;
3007
3675
  search?: string | null;
@@ -3025,6 +3693,18 @@ export type LoginResponse = {
3025
3693
  must_change_password: boolean;
3026
3694
  refresh_token: string;
3027
3695
  token_type: string;
3696
+ /**
3697
+ * Set when the 2FA enforcement policy (#2805) requires this user to enrol
3698
+ * in TOTP before a session can be issued. `totp_token` then carries an
3699
+ * *enrollment ticket* rather than a verification ticket: redeem it at
3700
+ * `POST /auth/totp/enroll/setup` followed by
3701
+ * `POST /auth/totp/enroll/complete`, which returns the real session.
3702
+ *
3703
+ * A client that does not understand this field sees no `access_token` and
3704
+ * must not treat the response as a successful login. It is never set at the
3705
+ * same time as `totp_required`.
3706
+ */
3707
+ totp_enrollment_required?: boolean | null;
3028
3708
  totp_required?: boolean | null;
3029
3709
  totp_token?: string | null;
3030
3710
  };
@@ -3360,6 +4040,19 @@ export type OidcConfigResponse = {
3360
4040
  updated_at: string;
3361
4041
  };
3362
4042
 
4043
+ /**
4044
+ * One install step: which manager, which packages, and for conda which
4045
+ * channels. Groups render in the order given.
4046
+ */
4047
+ export type PackageGroup = {
4048
+ /**
4049
+ * conda channels (`conda-forge`, `bioconda`); conda groups only.
4050
+ */
4051
+ channels?: Array<string>;
4052
+ manager: PackageManager;
4053
+ packages?: Array<string>;
4054
+ };
4055
+
3363
4056
  export type PackageListQuery = {
3364
4057
  limit?: number;
3365
4058
  offset?: number;
@@ -3372,6 +4065,14 @@ export type PackageListResponse = {
3372
4065
  pagination: Pagination;
3373
4066
  };
3374
4067
 
4068
+ /**
4069
+ * A package manager a spec may install with. The system managers run as
4070
+ * root in the final stage and need the spec to name the `user` the image
4071
+ * runs as afterwards; `pip` moves to a builder stage when `multistage` is
4072
+ * set; `conda` always installs in the final stage.
4073
+ */
4074
+ export type PackageManager = 'apt' | 'dnf' | 'microdnf' | 'yum' | 'apk' | 'pip' | 'conda';
4075
+
3375
4076
  export type PackageResponse = {
3376
4077
  created_at: string;
3377
4078
  description?: string | null;
@@ -3441,6 +4142,37 @@ export type PackageVersionsResponse = {
3441
4142
  versions: Array<PackageVersionResponse>;
3442
4143
  };
3443
4144
 
4145
+ /**
4146
+ * Query parameters for `POST /api/v1/admin/packages/backfill`.
4147
+ */
4148
+ export type PackagesBackfillQuery = {
4149
+ /**
4150
+ * Restrict the walk to one repository. Omit to walk every hosted
4151
+ * repository in a catalog-eligible format.
4152
+ */
4153
+ repository_key?: string | null;
4154
+ };
4155
+
4156
+ export type PackagesBackfillResponse = {
4157
+ /**
4158
+ * Rows whose upsert errored; the walk continues past them.
4159
+ */
4160
+ artifacts_failed: number;
4161
+ /**
4162
+ * Live artifact rows considered.
4163
+ */
4164
+ artifacts_scanned: number;
4165
+ /**
4166
+ * Rows with no derivable package coordinates (index/sidecar rows).
4167
+ */
4168
+ artifacts_skipped: number;
4169
+ message: string;
4170
+ /**
4171
+ * Catalog upserts performed.
4172
+ */
4173
+ packages_registered: number;
4174
+ };
4175
+
3444
4176
  /**
3445
4177
  * Pagination metadata for list responses.
3446
4178
  *
@@ -3676,7 +4408,19 @@ export type PluginType = 'format_handler' | 'storage_backend' | 'authentication'
3676
4408
  export type PolicyExecutionResult = {
3677
4409
  artifacts_matched: number;
3678
4410
  artifacts_removed: number;
4411
+ /**
4412
+ * Bytes actually reclaimed by this run. Always zero for a dry run.
4413
+ */
3679
4414
  bytes_freed: number;
4415
+ /**
4416
+ * Bytes held by the `artifacts_matched` rows -- what a run *would*
4417
+ * reclaim. Populated for a dry run as well as a live one, which is the
4418
+ * whole point of a preview: `bytes_freed` is deliberately zero on a dry
4419
+ * run (nothing was freed), so before this field a preview could report
4420
+ * which artifacts it would delete but never how much space that was
4421
+ * worth (#2024).
4422
+ */
4423
+ bytes_matched: number;
3680
4424
  dry_run: boolean;
3681
4425
  errors: Array<string>;
3682
4426
  policy_id: string;
@@ -3861,6 +4605,241 @@ export type PromotionRuleResponse = {
3861
4605
  updated_at: string;
3862
4606
  };
3863
4607
 
4608
+ /**
4609
+ * Exposure through proxy-cached content, reported alongside the hosted
4610
+ * numbers (#3397).
4611
+ *
4612
+ * `summary` above is computed over `scan_findings` joined to `artifacts` and
4613
+ * `download_statistics` — all three artifact-keyed. Proxy-cached bytes have no
4614
+ * `artifacts` row by design, and their downloads land in
4615
+ * `proxy_download_statistics` keyed by `proxy_cache_id`, so the hosted numbers
4616
+ * were not merely incomplete for proxy content: they were structurally
4617
+ * incapable of being non-zero for it. A confident zero to a security question
4618
+ * is worse than an error, so this block exists even when it is all zeros — an
4619
+ * operator can then see that proxy content WAS searched.
4620
+ *
4621
+ * Attribution runs through `proxy_scan_findings` (#3395). Before that table
4622
+ * existed there was no per-CVE detail for proxy content to attribute a
4623
+ * download to, which is why #3397 depended on #3395.
4624
+ */
4625
+ export type ProxyBlastRadius = {
4626
+ /**
4627
+ * Distinct proxy-cached digests carrying this CVE.
4628
+ */
4629
+ affected_digest_count: number;
4630
+ /**
4631
+ * Repositories whose proxy cache holds one of those digests.
4632
+ */
4633
+ affected_repo_count: number;
4634
+ /**
4635
+ * Whether any such pull was anonymous.
4636
+ */
4637
+ anonymous_download_present: boolean;
4638
+ /**
4639
+ * `included` | `not_applicable` — see the constants. Never omit this:
4640
+ * it is what tells a reader whether a zero below means "searched, nothing
4641
+ * found" or "not searched".
4642
+ */
4643
+ coverage: string;
4644
+ /**
4645
+ * Proxy download events of affected digests in the window.
4646
+ */
4647
+ download_count: number;
4648
+ /**
4649
+ * Distinct authenticated users who pulled one.
4650
+ */
4651
+ downloader_user_count: number;
4652
+ };
4653
+
4654
+ /**
4655
+ * A CVE-identified finding retained from an inline proxy scan so it can be
4656
+ * persisted into `proxy_scan_findings` and answered back to an operator
4657
+ * asking "which CVE blocked my build?" (#3395).
4658
+ *
4659
+ * Deliberately narrower than [`RawFinding`]: only the columns the digest-keyed
4660
+ * table stores. `description`, `source` and `source_url` are dropped because
4661
+ * they are scanner prose that would bloat a row written on every proxied
4662
+ * download, and because none of them identify the vulnerability.
4663
+ *
4664
+ * `cve_id` is non-optional here while it is optional on [`RawFinding`]: a
4665
+ * finding a scanner could not attach a CVE id to has nothing to look up, and
4666
+ * the table's identity key is the CVE. Such findings are dropped on the way
4667
+ * in — they still count toward `findings_count` on the verdict, which is
4668
+ * computed from the raw list before this projection runs.
4669
+ */
4670
+ export type ProxyFinding = {
4671
+ /**
4672
+ * Canonical vulnerability id, e.g. `CVE-2021-44228` or `GHSA-...`.
4673
+ */
4674
+ cve_id: string;
4675
+ /**
4676
+ * Version that resolves it, when the scanner reported one — the single
4677
+ * most actionable field for an operator whose build was just blocked.
4678
+ */
4679
+ fixed_version?: string | null;
4680
+ /**
4681
+ * Component the vulnerability was matched against.
4682
+ */
4683
+ package_name?: string | null;
4684
+ package_version?: string | null;
4685
+ /**
4686
+ * Lowercase severity token (`critical`/`high`/`medium`/`low`/`info`),
4687
+ * matching the tokens stored on `proxy_scan_results.max_severity`.
4688
+ */
4689
+ severity: string;
4690
+ title?: string | null;
4691
+ };
4692
+
4693
+ export type ProxyRescanRequest = {
4694
+ /**
4695
+ * Cache path within this repository, e.g.
4696
+ * `simple/click/click-8.0.0-py3-none-any.whl`. Path-keyed for the same
4697
+ * cross-tenant reason the read endpoint is.
4698
+ */
4699
+ path: string;
4700
+ };
4701
+
4702
+ export type ProxyRescanResponse = {
4703
+ critical_count: number;
4704
+ digest: string;
4705
+ /**
4706
+ * Per-CVE detail from this run, bounded to [`MAX_PROXY_FINDINGS`].
4707
+ */
4708
+ findings: Array<ProxyFinding>;
4709
+ findings_count: number;
4710
+ high_count: number;
4711
+ low_count: number;
4712
+ max_severity?: string | null;
4713
+ medium_count: number;
4714
+ /**
4715
+ * Components cataloged and persisted, i.e. how much SBOM this rescan
4716
+ * produced. Zero means the scanner reported no inventory for these bytes.
4717
+ */
4718
+ package_count: number;
4719
+ path: string;
4720
+ repository_key: string;
4721
+ /**
4722
+ * `clean` | `vulnerable` -- the verdict just recorded.
4723
+ */
4724
+ state: string;
4725
+ };
4726
+
4727
+ export type ProxyScanEntry = {
4728
+ cached_at: string;
4729
+ critical_count?: number | null;
4730
+ /**
4731
+ * SHA-256 of the cached bytes; NULL while the row is `pending_ingest`.
4732
+ */
4733
+ digest?: string | null;
4734
+ /**
4735
+ * The CVEs behind the counts (#3395), most severe first and bounded to
4736
+ * [`MAX_PROXY_FINDINGS`].
4737
+ *
4738
+ * Populated ONLY for a single-path (`?path=`) read, and only for a
4739
+ * `vulnerable` entry. Two reasons it is absent from the paged listing:
4740
+ * one query per row would make the list an N+1, and the listing is a
4741
+ * per-repository overview whose job is to point at the entry to open.
4742
+ *
4743
+ * `None` (omitted) means "not requested at this granularity"; an empty
4744
+ * vector means "requested, and this digest has no recorded detail" --
4745
+ * which is the real state for anything cached before #3395 shipped. The
4746
+ * two must stay distinguishable or a pre-#3395 artifact renders as having
4747
+ * no CVEs, which reads as clean.
4748
+ */
4749
+ findings?: Array<ProxyFinding> | null;
4750
+ findings_count?: number | null;
4751
+ high_count?: number | null;
4752
+ low_count?: number | null;
4753
+ max_severity?: string | null;
4754
+ medium_count?: number | null;
4755
+ /**
4756
+ * Set only when `state` is `not_scanned`.
4757
+ */
4758
+ not_scanned_reason?: string | null;
4759
+ path: string;
4760
+ /**
4761
+ * Floored at this repository's own `cached_at` -- see the module note.
4762
+ */
4763
+ scanned_at?: string | null;
4764
+ size_bytes: number;
4765
+ /**
4766
+ * `clean` | `vulnerable` | `not_scanned` | `pending_ingest`.
4767
+ */
4768
+ state: string;
4769
+ };
4770
+
4771
+ /**
4772
+ * Per-state counts over **distinct digests**, not paths: one repository can
4773
+ * cache the same digest at many paths, and the UI label must say so.
4774
+ */
4775
+ export type ProxyScanSummary = {
4776
+ clean: number;
4777
+ not_scanned: number;
4778
+ /**
4779
+ * Catalog rows whose `checksum_sha256` is still NULL. Counted as PATHS
4780
+ * (they have no digest to dedupe on) and excluded from every other count.
4781
+ */
4782
+ pending_ingest: number;
4783
+ /**
4784
+ * Distinct digests cached by this repository. Equals
4785
+ * `clean + vulnerable + not_scanned`.
4786
+ */
4787
+ total_digests: number;
4788
+ vulnerable: number;
4789
+ };
4790
+
4791
+ /**
4792
+ * One stored `proxy_scan_results` row, as returned by the admin
4793
+ * inspect/invalidate endpoints (#3244).
4794
+ */
4795
+ export type ProxyScanVerdictItem = {
4796
+ checksum_sha256: string;
4797
+ critical_count: number;
4798
+ findings_count: number;
4799
+ high_count: number;
4800
+ low_count: number;
4801
+ max_severity?: string | null;
4802
+ medium_count: number;
4803
+ scan_type: string;
4804
+ scanned_at: string;
4805
+ scanner_version?: string | null;
4806
+ verdict: string;
4807
+ };
4808
+
4809
+ /**
4810
+ * Response for the admin proxy-scan-verdict endpoints (#3244).
4811
+ */
4812
+ export type ProxyScanVerdictListResponse = {
4813
+ /**
4814
+ * The normalized (bare-hex) digest the verdicts are keyed on.
4815
+ */
4816
+ digest: string;
4817
+ verdicts: Array<ProxyScanVerdictItem>;
4818
+ };
4819
+
4820
+ export type ProxyScansResponse = {
4821
+ items: Array<ProxyScanEntry>;
4822
+ page: number;
4823
+ per_page: number;
4824
+ /**
4825
+ * `fail_open` | `fail_closed`. Lets `not_scanned` be read as "may have
4826
+ * been served unscanned" versus "was withheld".
4827
+ */
4828
+ proxy_scan_action: string;
4829
+ repository_key: string;
4830
+ /**
4831
+ * Enforcement context. Without it `vulnerable` is ambiguous: with
4832
+ * scanning on it means pulls are blocked; with scanning off it means the
4833
+ * artifact is served anyway and the verdict was recorded elsewhere.
4834
+ */
4835
+ scan_on_proxy: boolean;
4836
+ summary?: null | ProxyScanSummary;
4837
+ /**
4838
+ * Catalog paths matching the query (paths, not digests).
4839
+ */
4840
+ total: number;
4841
+ };
4842
+
3864
4843
  /**
3865
4844
  * Body for declaring that a locally-owned PyPI project tracks an upstream one.
3866
4845
  */
@@ -4020,6 +4999,15 @@ export type RemoveProjectMemberRequest = {
4020
4999
  principal_type: string;
4021
5000
  };
4022
5001
 
5002
+ export type RenderImageBuildRequest = {
5003
+ spec: ImageBuildSpec;
5004
+ };
5005
+
5006
+ export type RenderImageBuildResponse = {
5007
+ containerfile: string;
5008
+ warnings: Array<string>;
5009
+ };
5010
+
4023
5011
  /**
4024
5012
  * Repository exposure descriptor echoed in the response.
4025
5013
  */
@@ -4244,6 +5232,16 @@ export type RepositoryStorageBreakdown = {
4244
5232
  download_count: number;
4245
5233
  format: string;
4246
5234
  last_upload_at?: string | null;
5235
+ /**
5236
+ * The proxy-cache half of `artifact_count` / `storage_bytes`, read from
5237
+ * `proxy_cache_artifacts` (those rows never appear in `artifacts`, #1280).
5238
+ * Disjoint from the hosted figures above, which exclude the legacy
5239
+ * backfilled `proxy-cache/%` `artifacts` rows the same way
5240
+ * `repository_usage_ledger.hosted_bytes` does (migration 182) — unlike
5241
+ * `StorageSnapshot::proxy_storage_bytes`, which is a breakdown of a total
5242
+ * that already contains it. Defaults to 0 on older payloads.
5243
+ */
5244
+ proxy_artifact_count?: number;
4247
5245
  /**
4248
5246
  * Downloads served by this repository's remote pull-through proxy
4249
5247
  * (`proxy_download_statistics`, #2537/#2704). Proxy-cached objects carry
@@ -4253,6 +5251,7 @@ export type RepositoryStorageBreakdown = {
4253
5251
  * unaffected; defaults to 0 when deserializing older payloads.
4254
5252
  */
4255
5253
  proxy_download_count?: number;
5254
+ proxy_storage_bytes?: number;
4256
5255
  repository_id: string;
4257
5256
  repository_key: string;
4258
5257
  repository_name: string;
@@ -4269,6 +5268,12 @@ export type RepositoryStorageBreakdown = {
4269
5268
  *
4270
5269
  * Quota is unaffected: these numbers are accounting/visibility only and do NOT
4271
5270
  * change how the repository's storage quota is enforced (#2056 §7).
5271
+ *
5272
+ * Known bounded exclusion: OCI *manifest* JSON objects are not weighed. Their
5273
+ * `artifacts.size_bytes` holds the aggregate image size, not the stored
5274
+ * object, so counting it would double the layer bytes (#3286); no column holds
5275
+ * the manifest's true size. Manifests are a few KB each, so every figure below
5276
+ * under-reports by roughly that much per tag (#3618).
4272
5277
  */
4273
5278
  export type RepositoryStorageStatsResponse = {
4274
5279
  /**
@@ -4414,6 +5419,18 @@ export type ResetPasswordResponse = {
4414
5419
  };
4415
5420
 
4416
5421
  export type RestoreRequest = {
5422
+ /**
5423
+ * Accept an archive whose integrity cannot be established (#3373).
5424
+ *
5425
+ * A restore refuses an archive it cannot check: since #3373 every backup
5426
+ * records its payload checksum on the `backups` row, outside the archive,
5427
+ * and the archive's contents are verified against it before any row is
5428
+ * ingested. Archives captured before that column existed fall back to the
5429
+ * checksum in their own manifest; one carrying neither cannot be verified
5430
+ * at all, and this flag is the deliberate, audited way to restore it
5431
+ * anyway. It never waives a checksum that is present and does not match.
5432
+ */
5433
+ allow_unverified_archive?: boolean;
4417
5434
  restore_artifacts?: boolean | null;
4418
5435
  restore_database?: boolean | null;
4419
5436
  target_repository_id?: string | null;
@@ -4422,6 +5439,13 @@ export type RestoreRequest = {
4422
5439
  export type RestoreResponse = {
4423
5440
  artifacts_restored: number;
4424
5441
  errors: Array<string>;
5442
+ /**
5443
+ * What the archive's contents were checked against (#3373):
5444
+ * `recorded` (the digest on the `backups` row, the strong case),
5445
+ * `manifest` (the archive's own checksum -- detects corruption, not
5446
+ * tampering), or `waived` (`allow_unverified_archive` was set).
5447
+ */
5448
+ integrity_anchor: string;
4425
5449
  tables_restored: Array<string>;
4426
5450
  };
4427
5451
 
@@ -4563,6 +5587,12 @@ export type SamlConfigResponse = {
4563
5587
  require_signed_assertions: boolean;
4564
5588
  sign_requests: boolean;
4565
5589
  slo_url?: string | null;
5590
+ /**
5591
+ * URL-safe alias the public SAML routes accept in place of `id`
5592
+ * (migration 218, #2583). `None` when the configuration has not been
5593
+ * given one; it is then addressable by `id` only.
5594
+ */
5595
+ slug?: string | null;
4566
5596
  sp_entity_id: string;
4567
5597
  sso_url: string;
4568
5598
  updated_at: string;
@@ -4599,6 +5629,12 @@ export type SbomResponse = {
4599
5629
  };
4600
5630
 
4601
5631
  export type ScanConfigResponse = {
5632
+ /**
5633
+ * Opt-in that makes `severity_threshold` enforced on the proxy/OCI
5634
+ * inline scan gate (#3243/#3246). When false (default), the gate blocks
5635
+ * on any finding above `info`. Hosted-artifact blocking remains
5636
+ * configured via scan policies.
5637
+ */
4602
5638
  block_on_policy_violation: boolean;
4603
5639
  created_at: string;
4604
5640
  id: string;
@@ -4611,6 +5647,11 @@ export type ScanConfigResponse = {
4611
5647
  scan_enabled: boolean;
4612
5648
  scan_on_proxy: boolean;
4613
5649
  scan_on_upload: boolean;
5650
+ /**
5651
+ * Severity floor for the inline proxy scan gate; live only when
5652
+ * `block_on_policy_violation` is set (#3243/#3246). Findings at or above
5653
+ * it block the pull.
5654
+ */
4614
5655
  severity_threshold: string;
4615
5656
  updated_at: string;
4616
5657
  };
@@ -4991,12 +6032,23 @@ export type StatusCount = {
4991
6032
 
4992
6033
  /**
4993
6034
  * Request body for storage GC.
6035
+ *
6036
+ * `dry_run` is **required** and unknown fields are **rejected** (#3501): a
6037
+ * live GC pass is irreversible (no tombstone, no restore path short of a
6038
+ * backup), so an ambiguous request must fail loudly instead of selecting the
6039
+ * destructive branch. Before this, `{}` and any typo'd key
6040
+ * (`{"dryRun": true}`, `{"dry_Run": true}`) silently deserialized to
6041
+ * `dry_run: false` and performed a real deletion. Callers now say which pass
6042
+ * they mean: `{"dry_run": true}` to estimate, `{"dry_run": false}` to
6043
+ * delete; anything else is refused with an error naming the missing or
6044
+ * unknown field (axum's `Json` rejection, HTTP 422), and nothing is deleted.
4994
6045
  */
4995
6046
  export type StorageGcRequest = {
4996
6047
  /**
4997
6048
  * When true, report what would be deleted without actually deleting.
6049
+ * Required: an absent field is a rejected request, never a live delete.
4998
6050
  */
4999
- dry_run?: boolean;
6051
+ dry_run: boolean;
5000
6052
  };
5001
6053
 
5002
6054
  /**
@@ -5007,6 +6059,15 @@ export type StorageGcResult = {
5007
6059
  bytes_freed: number;
5008
6060
  dry_run: boolean;
5009
6061
  errors: Array<string>;
6062
+ /**
6063
+ * Orphaned row-less Maven flat objects this pass identified but left in
6064
+ * place because the sweep is not opted in (`MAVEN_FLAT_GC_ENABLED`
6065
+ * unset, #3431). Report-only: these objects and their attribution rows
6066
+ * were NOT deleted and are not counted in `storage_keys_deleted`. Always
6067
+ * `0` on a dry run (a dry run deletes nothing anyway) and when the sweep
6068
+ * is enabled.
6069
+ */
6070
+ maven_flat_objects_gated?: number;
5010
6071
  storage_keys_deleted: number;
5011
6072
  };
5012
6073
 
@@ -5014,10 +6075,51 @@ export type StorageGcResult = {
5014
6075
  * A single day's storage metrics snapshot.
5015
6076
  */
5016
6077
  export type StorageSnapshot = {
6078
+ /**
6079
+ * Proxy-cached objects at snapshot time (migration 210). They carry no
6080
+ * `artifacts` row (#1280), so this is disjoint from `total_artifacts`.
6081
+ * 0 for snapshots taken before migration 210 and on older payloads.
6082
+ */
6083
+ proxy_artifact_count?: number;
6084
+ /**
6085
+ * Pull-through serves, recorded in `proxy_download_statistics` rather
6086
+ * than `download_statistics`, so this is disjoint from `total_downloads`.
6087
+ */
6088
+ proxy_download_count?: number;
6089
+ /**
6090
+ * Bytes held by those objects — a *breakdown* of `total_storage_bytes`
6091
+ * above, not a disjoint bucket: that total sums
6092
+ * `repository_usage_ledger (hosted_bytes + proxy_bytes + oci_bytes)` and
6093
+ * migration 182 defines `proxy_bytes` as exactly this sum, so the two
6094
+ * must not be added. Same contract as the identically named
6095
+ * `/admin/stats` field (#3134/#3249). (On `RepositoryStorageBreakdown`
6096
+ * the same field name IS disjoint from that struct's `storage_bytes`,
6097
+ * which is hosted-only.)
6098
+ */
6099
+ proxy_storage_bytes?: number;
5017
6100
  snapshot_date: string;
6101
+ /**
6102
+ * Rows in `artifacts` (for OCI repositories that is manifests only —
6103
+ * layer/config blobs are content-addressed objects, not artifacts), the
6104
+ * same deliberate decision as the dashboard's
6105
+ * `SystemStats::total_artifacts` (#3134). Unlike the byte total, this
6106
+ * count still includes legacy backfilled `proxy-cache/%` rows.
6107
+ */
5018
6108
  total_artifacts: number;
5019
6109
  total_downloads: number;
5020
6110
  total_repositories: number;
6111
+ /**
6112
+ * All stored bytes at snapshot time, summed from
6113
+ * `repository_usage_ledger` (`hosted_bytes + proxy_bytes + oci_bytes`) —
6114
+ * the same source as the dashboard `total_storage_bytes` and quota
6115
+ * admission (#3134/#3249), so the analytics series is consistent with
6116
+ * both by construction. Includes OCI layer/config blob bytes
6117
+ * (`oci_blobs`) and proxy-cached bytes (`proxy_cache_artifacts`);
6118
+ * excludes legacy backfilled `proxy-cache/%` `artifacts` rows (their
6119
+ * bytes are represented by the proxy-cache catalog instead). This is the
6120
+ * LOGICAL figure: a blob cross-repo-mounted into N repositories counts
6121
+ * once per repository, matching the per-repo storage column and quota.
6122
+ */
5021
6123
  total_storage_bytes: number;
5022
6124
  total_users: number;
5023
6125
  };
@@ -5200,11 +6302,11 @@ export type SyncTriggerResponse = {
5200
6302
  * affordances a caller needs *before* authenticating (upload limit, demo
5201
6303
  * mode, whether guest access and which login providers are available).
5202
6304
  * * **Security-posture fields** (`scanners`, `search_engine`,
5203
- * `storage_backend`, `permissions`, `plugin_signing`) describe the
5204
- * instance's defensive configuration. They are returned **only to
5205
- * authenticated admins** and are omitted for anonymous / non-admin callers,
5206
- * so the deployment's security posture cannot be fingerprinted by an
5207
- * unauthenticated attacker.
6305
+ * `storage_backend`, `permissions`, `plugin_signing`, and
6306
+ * `auth.admin_break_glass_enabled`) describe the instance's defensive
6307
+ * configuration. They are returned **only to authenticated admins** and are
6308
+ * omitted for anonymous / non-admin callers, so the deployment's security
6309
+ * posture cannot be fingerprinted by an unauthenticated attacker.
5208
6310
  */
5209
6311
  export type SystemConfigResponse = {
5210
6312
  /**
@@ -5268,9 +6370,39 @@ export type SystemSettings = {
5268
6370
  export type SystemStats = {
5269
6371
  active_peers: number;
5270
6372
  pending_sync_tasks: number;
6373
+ /**
6374
+ * Count of proxy-cached (pull-through) objects, tracked in
6375
+ * `proxy_cache_artifacts` rather than `artifacts`. This COUNT is disjoint
6376
+ * from `total_artifacts`, which reads only the hosted tables.
6377
+ */
6378
+ proxy_artifact_count: number;
6379
+ /**
6380
+ * Bytes held by proxy-cached objects. Since #3134 this is a **breakdown
6381
+ * of** `total_storage_bytes`, not a disjoint bucket: the ledger's
6382
+ * `proxy_bytes` component is already inside that total, so a dashboard
6383
+ * that adds the two double-counts the cache (#3650). The count above and
6384
+ * the bytes here therefore do NOT compose the same way — only the count
6385
+ * is disjoint.
6386
+ */
6387
+ proxy_storage_bytes: number;
6388
+ /**
6389
+ * Rows in `artifacts` (for OCI repositories that is manifests only —
6390
+ * layer/config blobs are content-addressed objects, not artifacts).
6391
+ * Unlike the byte total, this count still includes legacy backfilled
6392
+ * `proxy-cache/%` rows.
6393
+ */
5271
6394
  total_artifacts: number;
5272
6395
  total_downloads: number;
5273
6396
  total_repositories: number;
6397
+ /**
6398
+ * All stored bytes, summed from `repository_usage_ledger`
6399
+ * (`hosted_bytes + proxy_bytes + oci_bytes`) — the same source the
6400
+ * per-repository `storage_used_bytes` figures are read from, so the
6401
+ * dashboard total is consistent with the per-repo column by
6402
+ * construction (#3134). Includes OCI layer/config blob bytes
6403
+ * (`oci_blobs`) and proxy-cached bytes; `proxy_storage_bytes` below is
6404
+ * a *breakdown* of this total, not a disjoint bucket.
6405
+ */
5274
6406
  total_storage_bytes: number;
5275
6407
  total_users: number;
5276
6408
  };
@@ -5360,35 +6492,172 @@ export type TokenInfoResponse = {
5360
6492
  last_used_at?: string | null;
5361
6493
  name: string;
5362
6494
  /**
5363
- * Dynamic repository selector, if configured.
6495
+ * Dynamic repository selector, if configured.
6496
+ */
6497
+ repo_selector?: {
6498
+ [key: string]: unknown;
6499
+ } | null;
6500
+ /**
6501
+ * Explicit repository IDs this token is restricted to (from join table).
6502
+ */
6503
+ repository_ids: Array<string>;
6504
+ scopes: Array<string>;
6505
+ token_prefix: string;
6506
+ };
6507
+
6508
+ export type TokenListResponse = {
6509
+ items: Array<TokenInfoResponse>;
6510
+ };
6511
+
6512
+ /**
6513
+ * Current API token expiration policy plus the inventory an operator needs
6514
+ * before (or after) tightening it: how many live tokens already exist with
6515
+ * no expiration. Enabling the policy never touches those rows — they are
6516
+ * surfaced here so an administrator can rotate them deliberately.
6517
+ */
6518
+ export type TokenPolicyResponse = {
6519
+ /**
6520
+ * Whether `PUT` can change the policy at all right now.
6521
+ */
6522
+ editable: boolean;
6523
+ /**
6524
+ * Live never-expiring tokens held by service accounts (CI credentials —
6525
+ * exempt from enforcement unless `apply_to_service_accounts` is set).
6526
+ */
6527
+ non_expiring_service_account_tokens: number;
6528
+ /**
6529
+ * Live (unrevoked, active-owner) never-expiring tokens held by regular
6530
+ * users. These predate or bypass the policy and are unaffected by it;
6531
+ * rotate them via the existing token-revocation endpoints.
6532
+ */
6533
+ non_expiring_user_tokens: number;
6534
+ /**
6535
+ * The policy in force.
6536
+ */
6537
+ policy: ApiTokenExpiryPolicy;
6538
+ /**
6539
+ * Whether it comes from the `API_TOKEN_EXPIRATION_*` environment
6540
+ * variables (in which case `PUT` is refused) or from the database.
6541
+ */
6542
+ source: TokenPolicySource;
6543
+ };
6544
+
6545
+ /**
6546
+ * Where the effective policy came from, surfaced on the admin read endpoint
6547
+ * so an operator can tell why a `PUT` is refused.
6548
+ */
6549
+ export type TokenPolicySource = 'environment' | 'database';
6550
+
6551
+ export type TotpCodeRequest = {
6552
+ code: string;
6553
+ };
6554
+
6555
+ export type TotpDisableRequest = {
6556
+ code: string;
6557
+ password: string;
6558
+ };
6559
+
6560
+ export type TotpEnableResponse = {
6561
+ backup_codes: Array<string>;
6562
+ };
6563
+
6564
+ /**
6565
+ * Request body completing forced enrollment.
6566
+ */
6567
+ export type TotpEnrollCompleteRequest = {
6568
+ /**
6569
+ * The current 6-digit code from the authenticator that scanned the secret.
6570
+ */
6571
+ code: string;
6572
+ /**
6573
+ * The `totp_token` returned alongside `totp_enrollment_required: true`.
6574
+ */
6575
+ totp_token: string;
6576
+ };
6577
+
6578
+ /**
6579
+ * Successful forced enrollment: a real session *plus* the backup codes.
6580
+ *
6581
+ * The session is returned here, in the same response that completes
6582
+ * enrollment, so a user subject to the policy is never left holding a valid
6583
+ * password and no way in.
6584
+ */
6585
+ export type TotpEnrollCompleteResponse = {
6586
+ access_token: string;
6587
+ /**
6588
+ * One-time recovery codes. Shown exactly once — they are stored hashed.
6589
+ */
6590
+ backup_codes: Array<string>;
6591
+ expires_in: number;
6592
+ must_change_password: boolean;
6593
+ refresh_token: string;
6594
+ token_type: string;
6595
+ };
6596
+
6597
+ /**
6598
+ * Request body carrying an enrollment ticket issued by `POST /auth/login`.
6599
+ */
6600
+ export type TotpEnrollSetupRequest = {
6601
+ /**
6602
+ * The `totp_token` returned alongside `totp_enrollment_required: true`.
6603
+ */
6604
+ totp_token: string;
6605
+ };
6606
+
6607
+ /**
6608
+ * System-wide 2FA enforcement policy.
6609
+ */
6610
+ export type TotpPolicy = 'disabled' | 'required_for_admins' | 'required_for_all';
6611
+
6612
+ /**
6613
+ * Current 2FA enforcement policy plus the context an operator needs before
6614
+ * tightening it.
6615
+ */
6616
+ export type TotpPolicyResponse = {
6617
+ /**
6618
+ * Whether the *calling* administrator has TOTP enabled. Tightening the
6619
+ * policy requires this.
6620
+ */
6621
+ caller_totp_enabled: boolean;
6622
+ /**
6623
+ * Whether `PUT` can change the policy at all right now.
6624
+ */
6625
+ editable: boolean;
6626
+ /**
6627
+ * Local (password-authenticating, non-service) administrators.
6628
+ */
6629
+ local_admins: number;
6630
+ /**
6631
+ * How many of those already have TOTP enabled. Under
6632
+ * `required_for_admins`, `local_admins - local_admins_with_totp` is the
6633
+ * number of administrators who will be sent through forced enrollment at
6634
+ * their next sign-in.
6635
+ */
6636
+ local_admins_with_totp: number;
6637
+ /**
6638
+ * Local (password-authenticating, non-service) users, admins included.
5364
6639
  */
5365
- repo_selector?: {
5366
- [key: string]: unknown;
5367
- } | null;
6640
+ local_users: number;
5368
6641
  /**
5369
- * Explicit repository IDs this token is restricted to (from join table).
6642
+ * How many of those already have TOTP enabled.
5370
6643
  */
5371
- repository_ids: Array<string>;
5372
- scopes: Array<string>;
5373
- token_prefix: string;
5374
- };
5375
-
5376
- export type TokenListResponse = {
5377
- items: Array<TokenInfoResponse>;
5378
- };
5379
-
5380
- export type TotpCodeRequest = {
5381
- code: string;
5382
- };
5383
-
5384
- export type TotpDisableRequest = {
5385
- code: string;
5386
- password: string;
6644
+ local_users_with_totp: number;
6645
+ /**
6646
+ * The policy in force.
6647
+ */
6648
+ policy: TotpPolicy;
6649
+ /**
6650
+ * Whether it comes from the `TOTP_POLICY` environment variable (in which
6651
+ * case `PUT` is refused) or from the database.
6652
+ */
6653
+ source: TotpPolicySource;
5387
6654
  };
5388
6655
 
5389
- export type TotpEnableResponse = {
5390
- backup_codes: Array<string>;
5391
- };
6656
+ /**
6657
+ * Where the effective policy came from, surfaced on the admin read endpoint so
6658
+ * an operator can tell why a `PUT` is refused.
6659
+ */
6660
+ export type TotpPolicySource = 'environment' | 'database';
5392
6661
 
5393
6662
  export type TotpSetupResponse = {
5394
6663
  qr_code_url: string;
@@ -5492,6 +6761,11 @@ export type UninstallQuery = {
5492
6761
  export type UpdateAgeGateConfigRequest = {
5493
6762
  enabled: boolean;
5494
6763
  min_age_days: number;
6764
+ /**
6765
+ * Age-source mode. Omitted = keep the repository's current mode, so
6766
+ * pre-mode clients that PUT `{enabled, min_age_days}` stay valid.
6767
+ */
6768
+ mode?: string | null;
5495
6769
  };
5496
6770
 
5497
6771
  export type UpdateAnalysisBody = {
@@ -5596,6 +6870,15 @@ export type UpdateLifecyclePolicyRequest = {
5596
6870
  };
5597
6871
 
5598
6872
  export type UpdateOidcConfigRequest = {
6873
+ /**
6874
+ * IdP group whose members are granted the admin role on login. `Some`
6875
+ * sets `attribute_mapping.admin_group` after the mapping merge/replace
6876
+ * above is applied; `None` leaves the mapping-derived value alone — so
6877
+ * `None` together with `attribute_mapping_replace` clears it, which is
6878
+ * how the env bootstrap revokes group-based admin when
6879
+ * `OIDC_ADMIN_GROUP` is unset (#3420).
6880
+ */
6881
+ admin_group?: string | null;
5599
6882
  allow_legacy_rsa_keys?: boolean | null;
5600
6883
  /**
5601
6884
  * Partial update for `attribute_mapping`. Keys present in this object
@@ -5765,7 +7048,7 @@ export type UpdateRepositoryRequest = {
5765
7048
  * Update the PyPI simple-index prefix (stored in `repository_config` under
5766
7049
  * `pypi_upstream_index_path`). Pass `""` for flat CDN layout, `"simple"` to
5767
7050
  * restore the PEP 503 default, or any other non-empty string for a custom prefix.
5768
- * Only meaningful for PyPI / Poetry / Conda Remote repositories.
7051
+ * Only meaningful for PyPI / Poetry / Jupyter / Conda Remote repositories.
5769
7052
  */
5770
7053
  pypi_upstream_index_path?: string | null;
5771
7054
  /**
@@ -5830,6 +7113,14 @@ export type UpdateSamlConfigRequest = {
5830
7113
  require_signed_assertions?: boolean | null;
5831
7114
  sign_requests?: boolean | null;
5832
7115
  slo_url?: string | null;
7116
+ /**
7117
+ * Set or change the URL-safe alias (#2583). Omitting it preserves the
7118
+ * current value, matching how `slo_url` and `admin_group` behave; a
7119
+ * slug therefore cannot be cleared through this endpoint, only
7120
+ * replaced, so an ACS URL an IdP is already configured with cannot be
7121
+ * removed by an update that simply forgot to mention it.
7122
+ */
7123
+ slug?: string | null;
5833
7124
  sp_entity_id?: string | null;
5834
7125
  sso_url?: string | null;
5835
7126
  use_absolute_acs_url?: boolean | null;
@@ -5865,6 +7156,20 @@ export type UpdateSyncPolicyPayload = {
5865
7156
  };
5866
7157
  };
5867
7158
 
7159
+ /**
7160
+ * Request body for `PUT /admin/settings/token-policy`.
7161
+ */
7162
+ export type UpdateTokenPolicyRequest = {
7163
+ policy: ApiTokenExpiryPolicy;
7164
+ };
7165
+
7166
+ /**
7167
+ * Request body for `PUT /admin/settings/totp-policy`.
7168
+ */
7169
+ export type UpdateTotpPolicyRequest = {
7170
+ policy: TotpPolicy;
7171
+ };
7172
+
5868
7173
  export type UpdateUserRequest = {
5869
7174
  display_name?: string | null;
5870
7175
  email?: string | null;
@@ -5872,7 +7177,22 @@ export type UpdateUserRequest = {
5872
7177
  is_admin?: boolean | null;
5873
7178
  };
5874
7179
 
7180
+ /**
7181
+ * Full-set replace of a virtual repository's members (PR #2795, issue #2785;
7182
+ * ratified in issue #2899).
7183
+ *
7184
+ * This body is the COMPLETE desired member list, not a partial patch. Any
7185
+ * current member whose key is absent from `members` is removed; keys present
7186
+ * are inserted or have their priority updated. An empty `members` array
7187
+ * removes every member.
7188
+ *
7189
+ * WARNING: sending a partial list to reorder priorities deletes the omitted
7190
+ * members. Clients must always send the full member list.
7191
+ */
5875
7192
  export type UpdateVirtualMembersRequest = {
7193
+ /**
7194
+ * The complete desired member set. Members not listed here are removed.
7195
+ */
5876
7196
  members: Array<VirtualMemberPriority>;
5877
7197
  };
5878
7198
 
@@ -5903,6 +7223,10 @@ export type UpsertLicensePolicyRequest = {
5903
7223
  * and an omitted field is never clobbered. See #1374 / B11.
5904
7224
  */
5905
7225
  export type UpsertScanConfigRequest = {
7226
+ /**
7227
+ * Opt-in that makes `severity_threshold` enforced on the proxy/OCI
7228
+ * inline scan gate (#3243/#3246). Default false = block on any finding.
7229
+ */
5906
7230
  block_on_policy_violation?: boolean | null;
5907
7231
  /**
5908
7232
  * #2954: `'fail_open'` (default) | `'fail_closed'` for the inline proxy
@@ -5912,14 +7236,20 @@ export type UpsertScanConfigRequest = {
5912
7236
  scan_enabled?: boolean | null;
5913
7237
  scan_on_proxy?: boolean | null;
5914
7238
  scan_on_upload?: boolean | null;
7239
+ /**
7240
+ * Severity floor for the inline proxy scan gate, live only when
7241
+ * `block_on_policy_violation` is set (#3243/#3246).
7242
+ */
5915
7243
  severity_threshold?: string | null;
5916
7244
  };
5917
7245
 
5918
7246
  export type UpstreamAuthRequest = {
5919
7247
  /**
5920
- * Auth type: "basic", "bearer", or "none" to remove.
7248
+ * Auth type: "basic", "bearer", "aws_ecr", "aws_codeartifact", or "none"
7249
+ * to remove.
5921
7250
  */
5922
7251
  auth_type: string;
7252
+ aws?: null | AwsUpstreamAuthRequest;
5923
7253
  /**
5924
7254
  * Password (basic) or token (bearer). Write-only, never returned.
5925
7255
  */
@@ -5964,7 +7294,13 @@ export type VersionResponse = {
5964
7294
  };
5965
7295
 
5966
7296
  export type VirtualMemberPriority = {
7297
+ /**
7298
+ * Key of the member repository. Inserted if it is not already a member.
7299
+ */
5967
7300
  member_key: string;
7301
+ /**
7302
+ * Resolution priority. Lower values are searched first.
7303
+ */
5968
7304
  priority: number;
5969
7305
  };
5970
7306
 
@@ -6013,7 +7349,7 @@ export type WasmPluginResponse = {
6013
7349
  /**
6014
7350
  * Webhook event types
6015
7351
  */
6016
- export type WebhookEvent = 'artifact_uploaded' | 'artifact_deleted' | 'repository_created' | 'repository_deleted' | 'user_created' | 'user_deleted' | 'build_started' | 'build_completed' | 'build_failed' | 'age_gate_queued' | 'age_gate_approved' | 'age_gate_rejected';
7352
+ export type WebhookEvent = 'artifact_uploaded' | 'artifact_deleted' | 'repository_created' | 'repository_deleted' | 'user_created' | 'user_deleted' | 'build_started' | 'build_completed' | 'build_failed' | 'age_gate_queued' | 'age_gate_approved' | 'age_gate_rejected' | 'age_gate_reopened';
6017
7353
 
6018
7354
  export type WebhookListResponse = {
6019
7355
  items: Array<WebhookResponse>;
@@ -6508,14 +7844,18 @@ export type ExecuteBackupErrors = {
6508
7844
  */
6509
7845
  404: unknown;
6510
7846
  /**
6511
- * Internal server error
7847
+ * Another backup is already in progress
7848
+ */
7849
+ 409: unknown;
7850
+ /**
7851
+ * The run could not be started or its outcome could not be recorded
6512
7852
  */
6513
7853
  500: unknown;
6514
7854
  };
6515
7855
 
6516
7856
  export type ExecuteBackupResponses = {
6517
7857
  /**
6518
- * Backup executed
7858
+ * Backup run finished; `status` is `completed` or `failed` and `error_message` carries the cause of a failure
6519
7859
  */
6520
7860
  200: BackupResponse;
6521
7861
  };
@@ -6535,6 +7875,10 @@ export type RestoreBackupData = {
6535
7875
  };
6536
7876
 
6537
7877
  export type RestoreBackupErrors = {
7878
+ /**
7879
+ * Archive integrity could not be established, or an unsupported option was supplied
7880
+ */
7881
+ 400: unknown;
6538
7882
  /**
6539
7883
  * Backup not found
6540
7884
  */
@@ -7431,6 +8775,115 @@ export type GetHealthLogResponses = {
7431
8775
 
7432
8776
  export type GetHealthLogResponse = GetHealthLogResponses[keyof GetHealthLogResponses];
7433
8777
 
8778
+ export type BackfillPackagesData = {
8779
+ body?: never;
8780
+ path?: never;
8781
+ query?: {
8782
+ /**
8783
+ * Restrict the walk to one repository. Omit to walk every hosted
8784
+ * repository in a catalog-eligible format.
8785
+ */
8786
+ repository_key?: string | null;
8787
+ };
8788
+ url: '/api/v1/admin/packages/backfill';
8789
+ };
8790
+
8791
+ export type BackfillPackagesErrors = {
8792
+ /**
8793
+ * Admin privileges required
8794
+ */
8795
+ 401: unknown;
8796
+ /**
8797
+ * Repository not found
8798
+ */
8799
+ 404: unknown;
8800
+ /**
8801
+ * Internal server error
8802
+ */
8803
+ 500: unknown;
8804
+ };
8805
+
8806
+ export type BackfillPackagesResponses = {
8807
+ /**
8808
+ * Backfill completed
8809
+ */
8810
+ 200: PackagesBackfillResponse;
8811
+ };
8812
+
8813
+ export type BackfillPackagesResponse = BackfillPackagesResponses[keyof BackfillPackagesResponses];
8814
+
8815
+ export type DeleteProxyScanVerdictsData = {
8816
+ body?: never;
8817
+ path: {
8818
+ /**
8819
+ * Content digest: `sha256:<64 hex>` or bare 64-hex
8820
+ */
8821
+ digest: string;
8822
+ };
8823
+ query?: never;
8824
+ url: '/api/v1/admin/proxy-scan-verdicts/{digest}';
8825
+ };
8826
+
8827
+ export type DeleteProxyScanVerdictsErrors = {
8828
+ /**
8829
+ * Malformed digest
8830
+ */
8831
+ 400: unknown;
8832
+ /**
8833
+ * Admin privileges required
8834
+ */
8835
+ 403: unknown;
8836
+ /**
8837
+ * No stored verdict for this digest
8838
+ */
8839
+ 404: unknown;
8840
+ };
8841
+
8842
+ export type DeleteProxyScanVerdictsResponses = {
8843
+ /**
8844
+ * Deleted verdict rows (re-assessment forced on next pull)
8845
+ */
8846
+ 200: ProxyScanVerdictListResponse;
8847
+ };
8848
+
8849
+ export type DeleteProxyScanVerdictsResponse = DeleteProxyScanVerdictsResponses[keyof DeleteProxyScanVerdictsResponses];
8850
+
8851
+ export type GetProxyScanVerdictsData = {
8852
+ body?: never;
8853
+ path: {
8854
+ /**
8855
+ * Content digest: `sha256:<64 hex>` or bare 64-hex
8856
+ */
8857
+ digest: string;
8858
+ };
8859
+ query?: never;
8860
+ url: '/api/v1/admin/proxy-scan-verdicts/{digest}';
8861
+ };
8862
+
8863
+ export type GetProxyScanVerdictsErrors = {
8864
+ /**
8865
+ * Malformed digest
8866
+ */
8867
+ 400: unknown;
8868
+ /**
8869
+ * Admin privileges required
8870
+ */
8871
+ 403: unknown;
8872
+ /**
8873
+ * No stored verdict for this digest
8874
+ */
8875
+ 404: unknown;
8876
+ };
8877
+
8878
+ export type GetProxyScanVerdictsResponses = {
8879
+ /**
8880
+ * Stored verdict rows for the digest
8881
+ */
8882
+ 200: ProxyScanVerdictListResponse;
8883
+ };
8884
+
8885
+ export type GetProxyScanVerdictsResponse = GetProxyScanVerdictsResponses[keyof GetProxyScanVerdictsResponses];
8886
+
7434
8887
  export type AdminListChecksData = {
7435
8888
  body?: never;
7436
8889
  path?: never;
@@ -7797,6 +9250,118 @@ export type UpdateSettingsResponses = {
7797
9250
 
7798
9251
  export type UpdateSettingsResponse = UpdateSettingsResponses[keyof UpdateSettingsResponses];
7799
9252
 
9253
+ export type GetTokenPolicyData = {
9254
+ body?: never;
9255
+ path?: never;
9256
+ query?: never;
9257
+ url: '/api/v1/admin/settings/token-policy';
9258
+ };
9259
+
9260
+ export type GetTokenPolicyErrors = {
9261
+ /**
9262
+ * Admin privileges required
9263
+ */
9264
+ 403: ErrorResponse;
9265
+ };
9266
+
9267
+ export type GetTokenPolicyError = GetTokenPolicyErrors[keyof GetTokenPolicyErrors];
9268
+
9269
+ export type GetTokenPolicyResponses = {
9270
+ /**
9271
+ * Current API token expiration policy
9272
+ */
9273
+ 200: TokenPolicyResponse;
9274
+ };
9275
+
9276
+ export type GetTokenPolicyResponse = GetTokenPolicyResponses[keyof GetTokenPolicyResponses];
9277
+
9278
+ export type UpdateTokenPolicyData = {
9279
+ body: UpdateTokenPolicyRequest;
9280
+ path?: never;
9281
+ query?: never;
9282
+ url: '/api/v1/admin/settings/token-policy';
9283
+ };
9284
+
9285
+ export type UpdateTokenPolicyErrors = {
9286
+ /**
9287
+ * Inconsistent policy (range/default contradiction)
9288
+ */
9289
+ 400: ErrorResponse;
9290
+ /**
9291
+ * Admin privileges required
9292
+ */
9293
+ 403: ErrorResponse;
9294
+ /**
9295
+ * Refused: policy pinned by API_TOKEN_EXPIRATION_* environment variables
9296
+ */
9297
+ 409: ErrorResponse;
9298
+ };
9299
+
9300
+ export type UpdateTokenPolicyError = UpdateTokenPolicyErrors[keyof UpdateTokenPolicyErrors];
9301
+
9302
+ export type UpdateTokenPolicyResponses = {
9303
+ /**
9304
+ * Policy updated
9305
+ */
9306
+ 200: TokenPolicyResponse;
9307
+ };
9308
+
9309
+ export type UpdateTokenPolicyResponse = UpdateTokenPolicyResponses[keyof UpdateTokenPolicyResponses];
9310
+
9311
+ export type GetTotpPolicyData = {
9312
+ body?: never;
9313
+ path?: never;
9314
+ query?: never;
9315
+ url: '/api/v1/admin/settings/totp-policy';
9316
+ };
9317
+
9318
+ export type GetTotpPolicyErrors = {
9319
+ /**
9320
+ * Admin privileges required
9321
+ */
9322
+ 403: ErrorResponse;
9323
+ };
9324
+
9325
+ export type GetTotpPolicyError = GetTotpPolicyErrors[keyof GetTotpPolicyErrors];
9326
+
9327
+ export type GetTotpPolicyResponses = {
9328
+ /**
9329
+ * Current 2FA enforcement policy
9330
+ */
9331
+ 200: TotpPolicyResponse;
9332
+ };
9333
+
9334
+ export type GetTotpPolicyResponse = GetTotpPolicyResponses[keyof GetTotpPolicyResponses];
9335
+
9336
+ export type UpdateTotpPolicyData = {
9337
+ body: UpdateTotpPolicyRequest;
9338
+ path?: never;
9339
+ query?: never;
9340
+ url: '/api/v1/admin/settings/totp-policy';
9341
+ };
9342
+
9343
+ export type UpdateTotpPolicyErrors = {
9344
+ /**
9345
+ * Admin privileges required
9346
+ */
9347
+ 403: ErrorResponse;
9348
+ /**
9349
+ * Refused: policy pinned by TOTP_POLICY, or the calling admin has not enrolled in TOTP
9350
+ */
9351
+ 409: ErrorResponse;
9352
+ };
9353
+
9354
+ export type UpdateTotpPolicyError = UpdateTotpPolicyErrors[keyof UpdateTotpPolicyErrors];
9355
+
9356
+ export type UpdateTotpPolicyResponses = {
9357
+ /**
9358
+ * Policy updated
9359
+ */
9360
+ 200: TotpPolicyResponse;
9361
+ };
9362
+
9363
+ export type UpdateTotpPolicyResponse = UpdateTotpPolicyResponses[keyof UpdateTotpPolicyResponses];
9364
+
7800
9365
  export type SendTestEmailData = {
7801
9366
  body: SmtpTestRequest;
7802
9367
  path?: never;
@@ -8517,6 +10082,33 @@ export type OciBlobReportResponses = {
8517
10082
 
8518
10083
  export type OciBlobReportResponse = OciBlobReportResponses[keyof OciBlobReportResponses];
8519
10084
 
10085
+ export type BackfillStorageLedgerData = {
10086
+ body?: never;
10087
+ path?: never;
10088
+ query?: never;
10089
+ url: '/api/v1/admin/storage/ledger/backfill';
10090
+ };
10091
+
10092
+ export type BackfillStorageLedgerErrors = {
10093
+ /**
10094
+ * Admin privileges required
10095
+ */
10096
+ 401: unknown;
10097
+ /**
10098
+ * Internal server error
10099
+ */
10100
+ 500: unknown;
10101
+ };
10102
+
10103
+ export type BackfillStorageLedgerResponses = {
10104
+ /**
10105
+ * Ledger recomputed
10106
+ */
10107
+ 200: LedgerBackfillResponse;
10108
+ };
10109
+
10110
+ export type BackfillStorageLedgerResponse = BackfillStorageLedgerResponses[keyof BackfillStorageLedgerResponses];
10111
+
8520
10112
  export type ListCrashesData = {
8521
10113
  body?: never;
8522
10114
  path?: never;
@@ -9052,6 +10644,9 @@ export type GetArtifactStatsResponses = {
9052
10644
  export type GetArtifactStatsResponse = GetArtifactStatsResponses[keyof GetArtifactStatsResponses];
9053
10645
 
9054
10646
  export type ExchangeCiTokenData = {
10647
+ /**
10648
+ * Optional. Omit the body entirely to resolve the provider from the assertion's iss claim; send provider_id only to override that.
10649
+ */
9055
10650
  body: CiTokenRequest;
9056
10651
  path?: never;
9057
10652
  query?: never;
@@ -9059,12 +10654,16 @@ export type ExchangeCiTokenData = {
9059
10654
  };
9060
10655
 
9061
10656
  export type ExchangeCiTokenErrors = {
10657
+ /**
10658
+ * Malformed body, provider_id disagrees with the assertion's iss, or the issuer matches several enabled providers
10659
+ */
10660
+ 400: ErrorResponse;
9062
10661
  /**
9063
10662
  * Invalid CI token or provider configuration
9064
10663
  */
9065
10664
  401: ErrorResponse;
9066
10665
  /**
9067
- * CI OIDC provider not found
10666
+ * No enabled CI OIDC provider matches the assertion's issuer
9068
10667
  */
9069
10668
  404: ErrorResponse;
9070
10669
  };
@@ -9269,11 +10868,24 @@ export type OidcLoginData = {
9269
10868
  */
9270
10869
  id: string;
9271
10870
  };
9272
- query?: never;
10871
+ query?: {
10872
+ /**
10873
+ * Optional OIDC `prompt` value forwarded to the IdP's authorization
10874
+ * endpoint. Only `none` is accepted (silent check-sso): the web UI uses
10875
+ * it to probe for an existing IdP session without ever rendering the
10876
+ * IdP's login page. Any other value is rejected so the login redirect
10877
+ * cannot be steered into unexpected IdP behaviours.
10878
+ */
10879
+ prompt?: string | null;
10880
+ };
9273
10881
  url: '/api/v1/auth/sso/oidc/{id}/login';
9274
10882
  };
9275
10883
 
9276
10884
  export type OidcLoginErrors = {
10885
+ /**
10886
+ * Unsupported prompt value
10887
+ */
10888
+ 400: ErrorResponse;
9277
10889
  /**
9278
10890
  * OIDC provider not found
9279
10891
  */
@@ -9302,7 +10914,7 @@ export type SamlAcsData = {
9302
10914
  body: SamlAcsForm;
9303
10915
  path: {
9304
10916
  /**
9305
- * SAML provider configuration ID
10917
+ * SAML provider configuration ID (UUID) or slug
9306
10918
  */
9307
10919
  id: string;
9308
10920
  };
@@ -9323,7 +10935,7 @@ export type SamlLoginData = {
9323
10935
  body?: never;
9324
10936
  path: {
9325
10937
  /**
9326
- * SAML provider configuration ID
10938
+ * SAML provider configuration ID (UUID) or slug
9327
10939
  */
9328
10940
  id: string;
9329
10941
  };
@@ -9438,6 +11050,10 @@ export type DisableTotpErrors = {
9438
11050
  * Invalid password or TOTP code
9439
11051
  */
9440
11052
  401: ErrorResponse;
11053
+ /**
11054
+ * The 2FA enforcement policy requires TOTP for this account
11055
+ */
11056
+ 409: ErrorResponse;
9441
11057
  };
9442
11058
 
9443
11059
  export type DisableTotpError = DisableTotpErrors[keyof DisableTotpErrors];
@@ -9474,6 +11090,64 @@ export type EnableTotpResponses = {
9474
11090
 
9475
11091
  export type EnableTotpResponse = EnableTotpResponses[keyof EnableTotpResponses];
9476
11092
 
11093
+ export type EnrollCompleteData = {
11094
+ body: TotpEnrollCompleteRequest;
11095
+ path?: never;
11096
+ query?: never;
11097
+ url: '/api/v1/auth/totp/enroll/complete';
11098
+ };
11099
+
11100
+ export type EnrollCompleteErrors = {
11101
+ /**
11102
+ * TOTP is already enabled, or /enroll/setup was not called first
11103
+ */
11104
+ 400: ErrorResponse;
11105
+ /**
11106
+ * Invalid code, or invalid/expired/already-used enrollment ticket
11107
+ */
11108
+ 401: ErrorResponse;
11109
+ };
11110
+
11111
+ export type EnrollCompleteError = EnrollCompleteErrors[keyof EnrollCompleteErrors];
11112
+
11113
+ export type EnrollCompleteResponses = {
11114
+ /**
11115
+ * TOTP enrolled; session and backup codes returned
11116
+ */
11117
+ 200: TotpEnrollCompleteResponse;
11118
+ };
11119
+
11120
+ export type EnrollCompleteResponse = EnrollCompleteResponses[keyof EnrollCompleteResponses];
11121
+
11122
+ export type EnrollSetupData = {
11123
+ body: TotpEnrollSetupRequest;
11124
+ path?: never;
11125
+ query?: never;
11126
+ url: '/api/v1/auth/totp/enroll/setup';
11127
+ };
11128
+
11129
+ export type EnrollSetupErrors = {
11130
+ /**
11131
+ * TOTP is already enabled for this account
11132
+ */
11133
+ 400: ErrorResponse;
11134
+ /**
11135
+ * Invalid or expired enrollment ticket
11136
+ */
11137
+ 401: ErrorResponse;
11138
+ };
11139
+
11140
+ export type EnrollSetupError = EnrollSetupErrors[keyof EnrollSetupErrors];
11141
+
11142
+ export type EnrollSetupResponses = {
11143
+ /**
11144
+ * TOTP secret and QR code URL for enrollment
11145
+ */
11146
+ 200: TotpSetupResponse;
11147
+ };
11148
+
11149
+ export type EnrollSetupResponse = EnrollSetupResponses[keyof EnrollSetupResponses];
11150
+
9477
11151
  export type SetupTotpData = {
9478
11152
  body?: never;
9479
11153
  path?: never;
@@ -11416,7 +13090,14 @@ export type GetPackageData = {
11416
13090
  */
11417
13091
  id: string;
11418
13092
  };
11419
- query?: never;
13093
+ query?: {
13094
+ /**
13095
+ * Optional repository key providing virtual-repo context. When it names a
13096
+ * virtual repo that contains this package, the returned `repository_key`
13097
+ * reports the virtual key (matching the aggregated listing).
13098
+ */
13099
+ repository_key?: string | null;
13100
+ };
11420
13101
  url: '/api/v1/packages/{id}';
11421
13102
  };
11422
13103
 
@@ -12057,9 +13738,9 @@ export type GetAssignedReposErrors = {
12057
13738
 
12058
13739
  export type GetAssignedReposResponses = {
12059
13740
  /**
12060
- * List of assigned repository IDs
13741
+ * Sync-enabled subscriptions for this peer (repo id + replication mode)
12061
13742
  */
12062
- 200: Array<string>;
13743
+ 200: Array<SubscriptionResponse>;
12063
13744
  };
12064
13745
 
12065
13746
  export type GetAssignedReposResponse = GetAssignedReposResponses[keyof GetAssignedReposResponses];
@@ -14710,6 +16391,82 @@ export type DownloadArtifactResponses = {
14710
16391
 
14711
16392
  export type DownloadArtifactResponse = DownloadArtifactResponses[keyof DownloadArtifactResponses];
14712
16393
 
16394
+ export type GetEgressProxyData = {
16395
+ body?: never;
16396
+ path: {
16397
+ /**
16398
+ * Repository key
16399
+ */
16400
+ key: string;
16401
+ };
16402
+ query?: never;
16403
+ url: '/api/v1/repositories/{key}/egress-proxy';
16404
+ };
16405
+
16406
+ export type GetEgressProxyErrors = {
16407
+ /**
16408
+ * Authentication required
16409
+ */
16410
+ 401: unknown;
16411
+ /**
16412
+ * Repository admin required
16413
+ */
16414
+ 403: unknown;
16415
+ /**
16416
+ * Repository not found
16417
+ */
16418
+ 404: unknown;
16419
+ };
16420
+
16421
+ export type GetEgressProxyResponses = {
16422
+ /**
16423
+ * Egress proxy configuration
16424
+ */
16425
+ 200: EgressProxyResponse;
16426
+ };
16427
+
16428
+ export type GetEgressProxyResponse = GetEgressProxyResponses[keyof GetEgressProxyResponses];
16429
+
16430
+ export type SetEgressProxyData = {
16431
+ body: EgressProxyRequest;
16432
+ path: {
16433
+ /**
16434
+ * Repository key
16435
+ */
16436
+ key: string;
16437
+ };
16438
+ query?: never;
16439
+ url: '/api/v1/repositories/{key}/egress-proxy';
16440
+ };
16441
+
16442
+ export type SetEgressProxyErrors = {
16443
+ /**
16444
+ * Invalid mode or proxy URL
16445
+ */
16446
+ 400: unknown;
16447
+ /**
16448
+ * Authentication required
16449
+ */
16450
+ 401: unknown;
16451
+ /**
16452
+ * Repository admin required
16453
+ */
16454
+ 403: unknown;
16455
+ /**
16456
+ * Repository not found
16457
+ */
16458
+ 404: unknown;
16459
+ };
16460
+
16461
+ export type SetEgressProxyResponses = {
16462
+ /**
16463
+ * Egress proxy updated
16464
+ */
16465
+ 200: EgressProxyResponse;
16466
+ };
16467
+
16468
+ export type SetEgressProxyResponse = SetEgressProxyResponses[keyof SetEgressProxyResponses];
16469
+
14713
16470
  export type ListSubscriptionsData = {
14714
16471
  body?: never;
14715
16472
  path: {
@@ -14772,21 +16529,218 @@ export type CreateSubscriptionErrors = {
14772
16529
  */
14773
16530
  403: unknown;
14774
16531
  /**
14775
- * Repository not found
16532
+ * Repository not found
16533
+ */
16534
+ 404: unknown;
16535
+ };
16536
+
16537
+ export type CreateSubscriptionResponses = {
16538
+ /**
16539
+ * Subscription created
16540
+ */
16541
+ 201: EmailSubscriptionResponse;
16542
+ };
16543
+
16544
+ export type CreateSubscriptionResponse = CreateSubscriptionResponses[keyof CreateSubscriptionResponses];
16545
+
16546
+ export type DeleteSubscriptionData = {
16547
+ body?: never;
16548
+ path: {
16549
+ /**
16550
+ * Repository key
16551
+ */
16552
+ key: string;
16553
+ /**
16554
+ * Subscription ID
16555
+ */
16556
+ subscription_id: string;
16557
+ };
16558
+ query?: never;
16559
+ url: '/api/v1/repositories/{key}/email-subscriptions/{subscription_id}';
16560
+ };
16561
+
16562
+ export type DeleteSubscriptionErrors = {
16563
+ /**
16564
+ * Not authenticated
16565
+ */
16566
+ 401: unknown;
16567
+ /**
16568
+ * Insufficient permissions
16569
+ */
16570
+ 403: unknown;
16571
+ /**
16572
+ * Subscription or repository not found
16573
+ */
16574
+ 404: unknown;
16575
+ };
16576
+
16577
+ export type DeleteSubscriptionResponses = {
16578
+ /**
16579
+ * Subscription deleted
16580
+ */
16581
+ 204: void;
16582
+ };
16583
+
16584
+ export type DeleteSubscriptionResponse = DeleteSubscriptionResponses[keyof DeleteSubscriptionResponses];
16585
+
16586
+ export type ListImageBuildsData = {
16587
+ body?: never;
16588
+ path: {
16589
+ /**
16590
+ * Repository key
16591
+ */
16592
+ key: string;
16593
+ };
16594
+ query?: never;
16595
+ url: '/api/v1/repositories/{key}/image-builds';
16596
+ };
16597
+
16598
+ export type ListImageBuildsResponses = {
16599
+ /**
16600
+ * Builds, newest first
16601
+ */
16602
+ 200: ImageBuildListResponse;
16603
+ };
16604
+
16605
+ export type ListImageBuildsResponse = ListImageBuildsResponses[keyof ListImageBuildsResponses];
16606
+
16607
+ export type CreateImageBuildData = {
16608
+ body: CreateImageBuildRequest;
16609
+ path: {
16610
+ /**
16611
+ * Repository key
16612
+ */
16613
+ key: string;
16614
+ };
16615
+ query?: never;
16616
+ url: '/api/v1/repositories/{key}/image-builds';
16617
+ };
16618
+
16619
+ export type CreateImageBuildErrors = {
16620
+ /**
16621
+ * Invalid spec, image name or tag; or the repository cannot receive builds
16622
+ */
16623
+ 400: unknown;
16624
+ /**
16625
+ * Image builds are not configured on this instance
16626
+ */
16627
+ 503: unknown;
16628
+ };
16629
+
16630
+ export type CreateImageBuildResponses = {
16631
+ /**
16632
+ * Build queued
16633
+ */
16634
+ 202: ImageBuildResponse;
16635
+ };
16636
+
16637
+ export type CreateImageBuildResponse = CreateImageBuildResponses[keyof CreateImageBuildResponses];
16638
+
16639
+ export type ImageBuildBaseInfoData = {
16640
+ body?: never;
16641
+ path: {
16642
+ /**
16643
+ * Repository key (the one being built into)
16644
+ */
16645
+ key: string;
16646
+ };
16647
+ query: {
16648
+ /**
16649
+ * Base image reference as the spec names it
16650
+ */
16651
+ image: string;
16652
+ };
16653
+ url: '/api/v1/repositories/{key}/image-builds/base-info';
16654
+ };
16655
+
16656
+ export type ImageBuildBaseInfoResponses = {
16657
+ 200: BaseImageInfo;
16658
+ };
16659
+
16660
+ export type ImageBuildBaseInfoResponse = ImageBuildBaseInfoResponses[keyof ImageBuildBaseInfoResponses];
16661
+
16662
+ export type RenderImageBuildData = {
16663
+ body: RenderImageBuildRequest;
16664
+ path: {
16665
+ /**
16666
+ * Repository key
16667
+ */
16668
+ key: string;
16669
+ };
16670
+ query?: never;
16671
+ url: '/api/v1/repositories/{key}/image-builds/render';
16672
+ };
16673
+
16674
+ export type RenderImageBuildErrors = {
16675
+ /**
16676
+ * The spec is invalid or refused by policy
16677
+ */
16678
+ 400: unknown;
16679
+ };
16680
+
16681
+ export type RenderImageBuildResponses = {
16682
+ /**
16683
+ * The Containerfile the server would build
16684
+ */
16685
+ 200: RenderImageBuildResponse;
16686
+ };
16687
+
16688
+ export type RenderImageBuildResponse2 = RenderImageBuildResponses[keyof RenderImageBuildResponses];
16689
+
16690
+ export type ImageBuildSettingsData = {
16691
+ body?: never;
16692
+ path: {
16693
+ /**
16694
+ * Repository key
16695
+ */
16696
+ key: string;
16697
+ };
16698
+ query?: never;
16699
+ url: '/api/v1/repositories/{key}/image-builds/settings';
16700
+ };
16701
+
16702
+ export type ImageBuildSettingsResponses = {
16703
+ /**
16704
+ * Builder availability and policy
16705
+ */
16706
+ 200: ImageBuildSettingsResponse;
16707
+ };
16708
+
16709
+ export type ImageBuildSettingsResponse2 = ImageBuildSettingsResponses[keyof ImageBuildSettingsResponses];
16710
+
16711
+ export type GetImageBuildData = {
16712
+ body?: never;
16713
+ path: {
16714
+ /**
16715
+ * Repository key
16716
+ */
16717
+ key: string;
16718
+ /**
16719
+ * Build id
16720
+ */
16721
+ id: string;
16722
+ };
16723
+ query?: never;
16724
+ url: '/api/v1/repositories/{key}/image-builds/{id}';
16725
+ };
16726
+
16727
+ export type GetImageBuildErrors = {
16728
+ /**
16729
+ * No such build
14776
16730
  */
14777
16731
  404: unknown;
14778
16732
  };
14779
16733
 
14780
- export type CreateSubscriptionResponses = {
16734
+ export type GetImageBuildResponses = {
14781
16735
  /**
14782
- * Subscription created
16736
+ * The build
14783
16737
  */
14784
- 201: EmailSubscriptionResponse;
16738
+ 200: ImageBuildResponse;
14785
16739
  };
14786
16740
 
14787
- export type CreateSubscriptionResponse = CreateSubscriptionResponses[keyof CreateSubscriptionResponses];
16741
+ export type GetImageBuildResponse = GetImageBuildResponses[keyof GetImageBuildResponses];
14788
16742
 
14789
- export type DeleteSubscriptionData = {
16743
+ export type GetImageBuildLogData = {
14790
16744
  body?: never;
14791
16745
  path: {
14792
16746
  /**
@@ -14794,37 +16748,64 @@ export type DeleteSubscriptionData = {
14794
16748
  */
14795
16749
  key: string;
14796
16750
  /**
14797
- * Subscription ID
16751
+ * Build id
14798
16752
  */
14799
- subscription_id: string;
16753
+ id: string;
14800
16754
  };
14801
16755
  query?: never;
14802
- url: '/api/v1/repositories/{key}/email-subscriptions/{subscription_id}';
16756
+ url: '/api/v1/repositories/{key}/image-builds/{id}/log';
14803
16757
  };
14804
16758
 
14805
- export type DeleteSubscriptionErrors = {
16759
+ export type GetImageBuildLogErrors = {
14806
16760
  /**
14807
- * Not authenticated
16761
+ * No such build
14808
16762
  */
14809
- 401: unknown;
16763
+ 404: unknown;
16764
+ };
16765
+
16766
+ export type GetImageBuildLogResponses = {
14810
16767
  /**
14811
- * Insufficient permissions
16768
+ * The buildctl output so far, text/plain
14812
16769
  */
14813
- 403: unknown;
16770
+ 200: unknown;
16771
+ };
16772
+
16773
+ export type InspectImageData = {
16774
+ body?: never;
16775
+ path: {
16776
+ /**
16777
+ * Repository key
16778
+ */
16779
+ key: string;
16780
+ };
16781
+ query: {
16782
+ /**
16783
+ * Image path within the repository
16784
+ */
16785
+ image: string;
16786
+ /**
16787
+ * Tag or sha256: digest
16788
+ */
16789
+ reference: string;
16790
+ };
16791
+ url: '/api/v1/repositories/{key}/image-inspect';
16792
+ };
16793
+
16794
+ export type InspectImageErrors = {
14814
16795
  /**
14815
- * Subscription or repository not found
16796
+ * Repository, image or reference not found
14816
16797
  */
14817
16798
  404: unknown;
14818
16799
  };
14819
16800
 
14820
- export type DeleteSubscriptionResponses = {
16801
+ export type InspectImageResponses = {
14821
16802
  /**
14822
- * Subscription deleted
16803
+ * The image as its manifest, config and provenance describe it
14823
16804
  */
14824
- 204: void;
16805
+ 200: ImageInspect;
14825
16806
  };
14826
16807
 
14827
- export type DeleteSubscriptionResponse = DeleteSubscriptionResponses[keyof DeleteSubscriptionResponses];
16808
+ export type InspectImageResponse = InspectImageResponses[keyof InspectImageResponses];
14828
16809
 
14829
16810
  export type ListRepoLabelsData = {
14830
16811
  body?: never;
@@ -15422,6 +17403,95 @@ export type UpdateRepoSecurityResponses = {
15422
17403
 
15423
17404
  export type UpdateRepoSecurityResponse = UpdateRepoSecurityResponses[keyof UpdateRepoSecurityResponses];
15424
17405
 
17406
+ export type GetRepoProxyScansData = {
17407
+ body?: never;
17408
+ path: {
17409
+ /**
17410
+ * Repository key
17411
+ */
17412
+ key: string;
17413
+ };
17414
+ query?: {
17415
+ /**
17416
+ * Cache path of a single entry, e.g.
17417
+ * `simple/click/click-8.0.0-py3-none-any.whl`. When set, the response
17418
+ * carries just that entry and omits the repository summary.
17419
+ */
17420
+ path?: string | null;
17421
+ page?: number | null;
17422
+ per_page?: number | null;
17423
+ };
17424
+ url: '/api/v1/repositories/{key}/security/proxy-scans';
17425
+ };
17426
+
17427
+ export type GetRepoProxyScansErrors = {
17428
+ /**
17429
+ * Authentication required
17430
+ */
17431
+ 401: ErrorResponse;
17432
+ /**
17433
+ * Repository or path not found
17434
+ */
17435
+ 404: ErrorResponse;
17436
+ };
17437
+
17438
+ export type GetRepoProxyScansError = GetRepoProxyScansErrors[keyof GetRepoProxyScansErrors];
17439
+
17440
+ export type GetRepoProxyScansResponses = {
17441
+ /**
17442
+ * Proxy scan verdicts for a repository
17443
+ */
17444
+ 200: ProxyScansResponse;
17445
+ };
17446
+
17447
+ export type GetRepoProxyScansResponse = GetRepoProxyScansResponses[keyof GetRepoProxyScansResponses];
17448
+
17449
+ export type RescanProxyCachedPathData = {
17450
+ body: ProxyRescanRequest;
17451
+ path: {
17452
+ /**
17453
+ * Repository key
17454
+ */
17455
+ key: string;
17456
+ };
17457
+ query?: never;
17458
+ url: '/api/v1/repositories/{key}/security/proxy-scans/rescan';
17459
+ };
17460
+
17461
+ export type RescanProxyCachedPathErrors = {
17462
+ /**
17463
+ * Authentication required
17464
+ */
17465
+ 401: ErrorResponse;
17466
+ /**
17467
+ * Repository or path not found
17468
+ */
17469
+ 404: ErrorResponse;
17470
+ /**
17471
+ * Cached object is above the inline scan cap
17472
+ */
17473
+ 422: ErrorResponse;
17474
+ /**
17475
+ * Rescan cooldown in effect: `RESCAN_THROTTLED`, with `Retry-After` naming the remaining cooldown in whole seconds.
17476
+ */
17477
+ 429: ErrorResponse;
17478
+ /**
17479
+ * Rescan could not produce a verdict: `NO_SCANNER_CONFIGURED` (no scanner is configured for this instance), `RESCAN_SCAN_FAILED` (the scan ran and errored), or `RESCAN_BUDGET_EXCEEDED` (the scan did not finish inside its budget). `Retry-After` is set only when cooldown time actually remains. The stored verdict is unchanged in every case.
17480
+ */
17481
+ 503: ErrorResponse;
17482
+ };
17483
+
17484
+ export type RescanProxyCachedPathError = RescanProxyCachedPathErrors[keyof RescanProxyCachedPathErrors];
17485
+
17486
+ export type RescanProxyCachedPathResponses = {
17487
+ /**
17488
+ * Rescan completed
17489
+ */
17490
+ 200: ProxyRescanResponse;
17491
+ };
17492
+
17493
+ export type RescanProxyCachedPathResponse = RescanProxyCachedPathResponses[keyof RescanProxyCachedPathResponses];
17494
+
15425
17495
  export type ListRepoScansData = {
15426
17496
  body?: never;
15427
17497
  path: {
@@ -15434,6 +17504,16 @@ export type ListRepoScansData = {
15434
17504
  repository_id?: string | null;
15435
17505
  artifact_id?: string | null;
15436
17506
  status?: string | null;
17507
+ /**
17508
+ * Restrict the listing to one scan engine (#3410), e.g. `grype`.
17509
+ *
17510
+ * `ScanResponse.scan_type` is already on the wire but could not be
17511
+ * filtered on, so a deployment running several engines had to page the
17512
+ * whole list and filter client-side. Validated against
17513
+ * [`KNOWN_SCAN_TYPES`]: an unrecognized value is a `400`, never an
17514
+ * unfiltered listing.
17515
+ */
17516
+ scan_type?: string | null;
15437
17517
  page?: number | null;
15438
17518
  per_page?: number | null;
15439
17519
  };
@@ -15486,6 +17566,38 @@ export type GetRepositoryStorageResponses = {
15486
17566
 
15487
17567
  export type GetRepositoryStorageResponse = GetRepositoryStorageResponses[keyof GetRepositoryStorageResponses];
15488
17568
 
17569
+ export type RunRepositoryStorageGcData = {
17570
+ body: StorageGcRequest;
17571
+ path: {
17572
+ /**
17573
+ * Repository key
17574
+ */
17575
+ key: string;
17576
+ };
17577
+ query?: never;
17578
+ url: '/api/v1/repositories/{key}/storage-gc';
17579
+ };
17580
+
17581
+ export type RunRepositoryStorageGcErrors = {
17582
+ /**
17583
+ * Authentication required, or admin privileges required
17584
+ */
17585
+ 401: unknown;
17586
+ /**
17587
+ * Repository not found
17588
+ */
17589
+ 404: unknown;
17590
+ };
17591
+
17592
+ export type RunRepositoryStorageGcResponses = {
17593
+ /**
17594
+ * GC result
17595
+ */
17596
+ 200: StorageGcResult;
17597
+ };
17598
+
17599
+ export type RunRepositoryStorageGcResponse = RunRepositoryStorageGcResponses[keyof RunRepositoryStorageGcResponses];
17600
+
15489
17601
  export type GetRepositoryStorageTreeData = {
15490
17602
  body?: never;
15491
17603
  path: {
@@ -16514,6 +18626,39 @@ export type GetDashboardResponses = {
16514
18626
 
16515
18627
  export type GetDashboardResponse = GetDashboardResponses[keyof GetDashboardResponses];
16516
18628
 
18629
+ export type IngestExternalFindingsData = {
18630
+ body: IngestExternalFindingsRequest;
18631
+ path?: never;
18632
+ query?: never;
18633
+ url: '/api/v1/security/findings/external';
18634
+ };
18635
+
18636
+ export type IngestExternalFindingsErrors = {
18637
+ /**
18638
+ * Malformed submission
18639
+ */
18640
+ 400: ErrorResponse;
18641
+ /**
18642
+ * Admin privileges or the write:findings scope required
18643
+ */
18644
+ 403: ErrorResponse;
18645
+ /**
18646
+ * Artifact not found
18647
+ */
18648
+ 404: ErrorResponse;
18649
+ };
18650
+
18651
+ export type IngestExternalFindingsError = IngestExternalFindingsErrors[keyof IngestExternalFindingsErrors];
18652
+
18653
+ export type IngestExternalFindingsResponses = {
18654
+ /**
18655
+ * Findings ingested
18656
+ */
18657
+ 200: IngestExternalFindingsResponse;
18658
+ };
18659
+
18660
+ export type IngestExternalFindingsResponse2 = IngestExternalFindingsResponses[keyof IngestExternalFindingsResponses];
18661
+
16517
18662
  export type RevokeAcknowledgmentData = {
16518
18663
  body?: never;
16519
18664
  path: {
@@ -16763,6 +18908,16 @@ export type ListScansData = {
16763
18908
  repository_id?: string | null;
16764
18909
  artifact_id?: string | null;
16765
18910
  status?: string | null;
18911
+ /**
18912
+ * Restrict the listing to one scan engine (#3410), e.g. `grype`.
18913
+ *
18914
+ * `ScanResponse.scan_type` is already on the wire but could not be
18915
+ * filtered on, so a deployment running several engines had to page the
18916
+ * whole list and filter client-side. Validated against
18917
+ * [`KNOWN_SCAN_TYPES`]: an unrecognized value is a `400`, never an
18918
+ * unfiltered listing.
18919
+ */
18920
+ scan_type?: string | null;
16766
18921
  page?: number | null;
16767
18922
  per_page?: number | null;
16768
18923
  };
@@ -16817,6 +18972,27 @@ export type ListFindingsData = {
16817
18972
  id: string;
16818
18973
  };
16819
18974
  query?: {
18975
+ /**
18976
+ * Restrict the listing to one severity (#3410).
18977
+ *
18978
+ * Validated against [`KNOWN_SEVERITIES`]; an unrecognized token is a
18979
+ * `400` rather than an unfiltered page.
18980
+ */
18981
+ severity?: string | null;
18982
+ /**
18983
+ * Restrict the listing to findings written by one scanner (#3410).
18984
+ *
18985
+ * Matched exactly against `scan_findings.source`, which is already
18986
+ * returned as `FindingResponse.source`. Free text (no closed vocabulary):
18987
+ * bounded in length, not enumerated.
18988
+ */
18989
+ source?: string | null;
18990
+ /**
18991
+ * Restrict the listing to one vulnerability identifier (#3410).
18992
+ *
18993
+ * Matched exactly against `scan_findings.cve_id`.
18994
+ */
18995
+ cve_id?: string | null;
16820
18996
  page?: number | null;
16821
18997
  per_page?: number | null;
16822
18998
  };
@@ -18020,6 +20196,18 @@ export type ListUsersData = {
18020
20196
  search?: string | null;
18021
20197
  is_active?: boolean | null;
18022
20198
  is_admin?: boolean | null;
20199
+ /**
20200
+ * Filter on the service-account discriminator (#3634).
20201
+ *
20202
+ * Service accounts are rows in `users`, so an unfiltered listing mixes
20203
+ * them in with people. A client building a principal picker for
20204
+ * `POST /api/v1/permissions` must be able to exclude them: that endpoint's
20205
+ * `validate_principal` requires `principal_type = "service_account"` for
20206
+ * such a row and rejects it as `"user"`, so offering one under `user` is a
20207
+ * guaranteed 400. `None` keeps the historical unfiltered behavior, which
20208
+ * the audit actor filter and the group member picker both want.
20209
+ */
20210
+ is_service_account?: boolean | null;
18023
20211
  page?: number | null;
18024
20212
  per_page?: number | null;
18025
20213
  };
@@ -18382,7 +20570,7 @@ export type GetUserRolesData = {
18382
20570
 
18383
20571
  export type GetUserRolesResponses = {
18384
20572
  /**
18385
- * List of user roles
20573
+ * List of user roles. The `permissions` array describes the ROLE's capabilities, not this user's effective repository access: roles listed here are identity/SSO-mapping metadata and grant no repository access on their own (#3387 / #3522).
18386
20574
  */
18387
20575
  200: RoleListResponse;
18388
20576
  };
@@ -18403,7 +20591,7 @@ export type AssignRoleData = {
18403
20591
 
18404
20592
  export type AssignRoleResponses = {
18405
20593
  /**
18406
- * Role assigned successfully
20594
+ * Role assigned successfully. NOTE: roles assigned here are identity/SSO-mapping metadata and do NOT by themselves grant access to any repository — use POST /api/v1/permissions for that (#3387 / #3522).
18407
20595
  */
18408
20596
  200: unknown;
18409
20597
  };
@@ -18854,6 +21042,121 @@ export type LivenessCheckResponses = {
18854
21042
 
18855
21043
  export type LivenessCheckResponse = LivenessCheckResponses[keyof LivenessCheckResponses];
18856
21044
 
21045
+ export type XmlrpcData = {
21046
+ /**
21047
+ * XML-RPC `methodCall` (opaque). Supported methods: `browse([classifier, ...])` and `list_packages()`.
21048
+ */
21049
+ body: string;
21050
+ path: {
21051
+ /**
21052
+ * Repository key
21053
+ */
21054
+ repo_key: string;
21055
+ };
21056
+ query?: never;
21057
+ url: '/pypi/{repo_key}/pypi';
21058
+ };
21059
+
21060
+ export type XmlrpcErrors = {
21061
+ /**
21062
+ * Repository not found
21063
+ */
21064
+ 404: unknown;
21065
+ /**
21066
+ * Request body larger than 64 KiB
21067
+ */
21068
+ 413: unknown;
21069
+ };
21070
+
21071
+ export type XmlrpcResponses = {
21072
+ /**
21073
+ * XML-RPC `methodResponse` (opaque). `browse` answers `[[name, version], ...]` from stored metadata (hosted repositories, and the hosted members of a virtual); an unknown method, a malformed request, or either method on a remote repository or a virtual without hosted members (fault -32001: the call is never forwarded upstream; JupyterLab surfaces it as a generic error, the reason is in the response) answers an XML-RPC fault, not an HTTP error.
21074
+ */
21075
+ 200: string;
21076
+ };
21077
+
21078
+ export type XmlrpcResponse = XmlrpcResponses[keyof XmlrpcResponses];
21079
+
21080
+ export type LegacyProjectJsonData = {
21081
+ body?: never;
21082
+ path: {
21083
+ /**
21084
+ * Repository key
21085
+ */
21086
+ repo_key: string;
21087
+ /**
21088
+ * Project name; normalized per PEP 503 for the lookup
21089
+ */
21090
+ project: string;
21091
+ };
21092
+ query?: never;
21093
+ url: '/pypi/{repo_key}/pypi/{project}/json';
21094
+ };
21095
+
21096
+ export type LegacyProjectJsonErrors = {
21097
+ /**
21098
+ * Project blocked by a curation rule
21099
+ */
21100
+ 403: unknown;
21101
+ /**
21102
+ * Repository or project not found
21103
+ */
21104
+ 404: unknown;
21105
+ };
21106
+
21107
+ export type LegacyProjectJsonResponses = {
21108
+ /**
21109
+ * Legacy PyPI JSON document: `info` for the latest release, `releases` keyed by version, `urls` for the latest release. Download URLs point at this repository.
21110
+ */
21111
+ 200: {
21112
+ [key: string]: unknown;
21113
+ };
21114
+ };
21115
+
21116
+ export type LegacyProjectJsonResponse = LegacyProjectJsonResponses[keyof LegacyProjectJsonResponses];
21117
+
21118
+ export type LegacyReleaseJsonData = {
21119
+ body?: never;
21120
+ path: {
21121
+ /**
21122
+ * Repository key
21123
+ */
21124
+ repo_key: string;
21125
+ /**
21126
+ * Project name; normalized per PEP 503 for the lookup
21127
+ */
21128
+ project: string;
21129
+ /**
21130
+ * Release version (PEP 440; `1.0` matches a stored `1.0.0`)
21131
+ */
21132
+ version: string;
21133
+ };
21134
+ query?: never;
21135
+ url: '/pypi/{repo_key}/pypi/{project}/{version}/json';
21136
+ };
21137
+
21138
+ export type LegacyReleaseJsonErrors = {
21139
+ /**
21140
+ * Project or version blocked by a curation rule
21141
+ */
21142
+ 403: unknown;
21143
+ /**
21144
+ * Repository, project or release not found
21145
+ */
21146
+ 404: unknown;
21147
+ };
21148
+
21149
+ export type LegacyReleaseJsonResponses = {
21150
+ /**
21151
+ * Legacy PyPI JSON document for one release: `info` and `urls`. Download URLs point at this repository.
21152
+ */
21153
+ 200: {
21154
+ [key: string]: unknown;
21155
+ };
21156
+ };
21157
+
21158
+ export type LegacyReleaseJsonResponse = LegacyReleaseJsonResponses[keyof LegacyReleaseJsonResponses];
21159
+
18857
21160
  export type ReadinessCheckData = {
18858
21161
  body?: never;
18859
21162
  path?: never;