securewithtrace 0.47.0 → 0.48.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.
Files changed (2) hide show
  1. package/dist/index.js +1848 -483
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3700,6 +3700,60 @@ var PENTEST_FINDING_STATUS_VALUES = [
3700
3700
  "DISMISSED"
3701
3701
  ];
3702
3702
 
3703
+ // ../../packages/core/src/agent-session/versions.ts
3704
+ var OOB_PROFILE_SUCCESSIONS = [
3705
+ {
3706
+ successor: { promptVersion: "validation-v11", toolsetVersion: "validation-tools-v7" },
3707
+ predecessor: { promptVersion: "validation-v10", toolsetVersion: "validation-tools-v6" }
3708
+ },
3709
+ {
3710
+ successor: { promptVersion: "operator-v7", toolsetVersion: "operator-tools-v5" },
3711
+ predecessor: { promptVersion: "operator-v6", toolsetVersion: "operator-tools-v4" }
3712
+ },
3713
+ {
3714
+ successor: { promptVersion: "operator-openai-v7", toolsetVersion: "operator-openai-tools-v6" },
3715
+ predecessor: {
3716
+ promptVersion: "operator-openai-v6",
3717
+ toolsetVersion: "operator-openai-tools-v5"
3718
+ }
3719
+ },
3720
+ {
3721
+ successor: { promptVersion: "retest-v7", toolsetVersion: "retest-tools-v5" },
3722
+ predecessor: { promptVersion: "retest-v6", toolsetVersion: "retest-tools-v4" }
3723
+ },
3724
+ {
3725
+ successor: { promptVersion: "assessment-v10", toolsetVersion: "assessment-tools-v7" },
3726
+ predecessor: { promptVersion: "assessment-v9", toolsetVersion: "assessment-tools-v6" }
3727
+ },
3728
+ {
3729
+ successor: { promptVersion: "assessment-v10-desktop", toolsetVersion: "assessment-tools-v7" },
3730
+ predecessor: { promptVersion: "assessment-v9-desktop", toolsetVersion: "assessment-tools-v6" }
3731
+ },
3732
+ {
3733
+ successor: {
3734
+ promptVersion: "assessment-openai-v7",
3735
+ toolsetVersion: "assessment-openai-tools-v6"
3736
+ },
3737
+ predecessor: {
3738
+ promptVersion: "assessment-openai-v6",
3739
+ toolsetVersion: "assessment-openai-tools-v5"
3740
+ }
3741
+ },
3742
+ {
3743
+ successor: {
3744
+ promptVersion: "assessment-openai-v7-desktop",
3745
+ toolsetVersion: "assessment-openai-tools-v6"
3746
+ },
3747
+ predecessor: {
3748
+ promptVersion: "assessment-openai-v6-desktop",
3749
+ toolsetVersion: "assessment-openai-tools-v5"
3750
+ }
3751
+ }
3752
+ ];
3753
+ var OOB_CAPABLE_TOOLSETS = new Set(
3754
+ OOB_PROFILE_SUCCESSIONS.map(({ successor }) => successor.toolsetVersion)
3755
+ );
3756
+
3703
3757
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
3704
3758
  var external_exports = {};
3705
3759
  __export(external_exports, {
@@ -4931,8 +4985,8 @@ function cleanEnum(obj) {
4931
4985
  return Number.isNaN(Number.parseInt(k, 10));
4932
4986
  }).map((el) => el[1]);
4933
4987
  }
4934
- function base64ToUint8Array(base643) {
4935
- const binaryString = atob(base643);
4988
+ function base64ToUint8Array(base644) {
4989
+ const binaryString = atob(base644);
4936
4990
  const bytes = new Uint8Array(binaryString.length);
4937
4991
  for (let i2 = 0; i2 < binaryString.length; i2++) {
4938
4992
  bytes[i2] = binaryString.charCodeAt(i2);
@@ -4947,9 +5001,9 @@ function uint8ArrayToBase64(bytes) {
4947
5001
  return btoa(binaryString);
4948
5002
  }
4949
5003
  function base64urlToUint8Array(base64url3) {
4950
- const base643 = base64url3.replace(/-/g, "+").replace(/_/g, "/");
4951
- const padding = "=".repeat((4 - base643.length % 4) % 4);
4952
- return base64ToUint8Array(base643 + padding);
5004
+ const base644 = base64url3.replace(/-/g, "+").replace(/_/g, "/");
5005
+ const padding = "=".repeat((4 - base644.length % 4) % 4);
5006
+ return base64ToUint8Array(base644 + padding);
4953
5007
  }
4954
5008
  function uint8ArrayToBase64url(bytes) {
4955
5009
  return uint8ArrayToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
@@ -6293,8 +6347,8 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
6293
6347
  function isValidBase64URL(data) {
6294
6348
  if (!base64url.test(data))
6295
6349
  return false;
6296
- const base643 = data.replace(/[-_]/g, (c65) => c65 === "-" ? "+" : "/");
6297
- const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
6350
+ const base644 = data.replace(/[-_]/g, (c69) => c69 === "-" ? "+" : "/");
6351
+ const padded = base644.padEnd(Math.ceil(base644.length / 4) * 4, "=");
6298
6352
  return isValidBase64(padded);
6299
6353
  }
6300
6354
  var $ZodBase64URL = /* @__PURE__ */ $constructor("$ZodBase64URL", (inst, def) => {
@@ -16337,9 +16391,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
16337
16391
  inst._zod.processJSONSchema = (ctx, json2, params) => dateProcessor(inst, ctx, json2, params);
16338
16392
  inst.min = (value, params) => inst.check(_gte(value, params));
16339
16393
  inst.max = (value, params) => inst.check(_lte(value, params));
16340
- const c65 = inst._zod.bag;
16341
- inst.minDate = c65.minimum ? new Date(c65.minimum) : null;
16342
- inst.maxDate = c65.maximum ? new Date(c65.maximum) : null;
16394
+ const c69 = inst._zod.bag;
16395
+ inst.minDate = c69.minimum ? new Date(c69.minimum) : null;
16396
+ inst.maxDate = c69.maximum ? new Date(c69.maximum) : null;
16343
16397
  });
16344
16398
  function date3(params) {
16345
16399
  return _date(ZodDate, params);
@@ -22003,7 +22057,9 @@ var PentestEditEntityValues = [
22003
22057
  // `apps/web` hard-parses audit responses through it, so a new value reaching an old
22004
22058
  // web build fails `ListPentestAuditLogResponseSchema.parse` and takes out the whole
22005
22059
  // staff audit list. The generic `enumLabel` renderer downstream does not save it.
22006
- "PENTEST_ATTACK_CHAIN"
22060
+ "PENTEST_ATTACK_CHAIN",
22061
+ "APPLICATION_SURFACE_FEATURE",
22062
+ "APPLICATION_SURFACE_MAP"
22007
22063
  ];
22008
22064
  var PentestEditEntity = external_exports.enum(PentestEditEntityValues);
22009
22065
  var PentestEditActionValues = [
@@ -22014,7 +22070,9 @@ var PentestEditActionValues = [
22014
22070
  "RESTORE",
22015
22071
  "STAGE_TRANSITION",
22016
22072
  "PENTEST_SCAN_RERUN",
22017
- "DELIVER"
22073
+ "DELIVER",
22074
+ "RETIRE",
22075
+ "MERGE"
22018
22076
  ];
22019
22077
  var PentestEditAction = external_exports.enum(PentestEditActionValues);
22020
22078
  var PentestAuditActorTypeValues = ["USER", "SYSTEM", "AGENT", "API_KEY", "STAFF"];
@@ -22492,7 +22550,18 @@ var OperatorPentestContextSchema = external_exports.object({
22492
22550
  label: external_exports.string(),
22493
22551
  credentialType: external_exports.string()
22494
22552
  })
22495
- )
22553
+ ),
22554
+ /**
22555
+ * The engagement's staff-defined finding tags, name-sorted. The operator
22556
+ * classifies findings with `set_finding_tags` by NAME from this list. Optional
22557
+ * for the same host raw-cast reason as `applications`.
22558
+ */
22559
+ tags: external_exports.array(
22560
+ external_exports.object({
22561
+ name: external_exports.string(),
22562
+ description: external_exports.string().nullable()
22563
+ })
22564
+ ).optional()
22496
22565
  });
22497
22566
 
22498
22567
  // ../../packages/api-contracts/src/contracts/v1/agent-session.ts
@@ -22923,6 +22992,402 @@ var ListAgentTasksQuerySchema = external_exports.object({
22923
22992
  });
22924
22993
  var ListAgentTasksResponseSchema = external_exports.array(AgentTaskResponseSchema);
22925
22994
 
22995
+ // ../../packages/api-contracts/src/schemas/api/v1/repository.api.ts
22996
+ var PlatformValues = ["GITHUB", "GITLAB", "BITBUCKET", "UPLOAD"];
22997
+ var RepositoryStatusValues = ["CONNECTED", "DISCONNECTED"];
22998
+ var RepositoryIdParamsSchema = OrgIdParamsSchema.extend({
22999
+ repositoryId: external_exports.uuid()
23000
+ });
23001
+ var CreateRepositoryRequestSchema = external_exports.object({
23002
+ repositoryUrl: external_exports.url(),
23003
+ platform: external_exports.enum(PlatformValues),
23004
+ githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
23005
+ status: external_exports.enum(RepositoryStatusValues).optional()
23006
+ });
23007
+ var UpdateRepositoryRequestSchema = external_exports.object({
23008
+ repositoryUrl: external_exports.url().optional(),
23009
+ platform: external_exports.enum(PlatformValues).optional(),
23010
+ githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
23011
+ status: external_exports.enum(RepositoryStatusValues).optional()
23012
+ });
23013
+ var RepositoryResponseSchema = external_exports.object({
23014
+ repositoryId: external_exports.uuid(),
23015
+ organizationId: external_exports.uuid(),
23016
+ repositoryUrl: external_exports.url(),
23017
+ platform: external_exports.enum(PlatformValues),
23018
+ status: external_exports.enum(RepositoryStatusValues),
23019
+ githubDefaultBranch: external_exports.string(),
23020
+ scanningBranch: external_exports.string().nullable(),
23021
+ primaryLanguage: external_exports.string().nullable().optional(),
23022
+ /** Staff-set opt-in: automated PR scans run on this repo even without a FULL SAST baseline. */
23023
+ prScansEnabled: external_exports.boolean(),
23024
+ /** Customer-set gate: false = no scans of any kind run for this repo until it is included again. */
23025
+ includedInScanning: external_exports.boolean(),
23026
+ /** Host archive flag mirrored from the provider. */
23027
+ isArchived: external_exports.boolean(),
23028
+ createdAt: external_exports.date(),
23029
+ updatedAt: external_exports.date()
23030
+ });
23031
+ var ListRepositoriesResponseSchema = external_exports.array(RepositoryResponseSchema);
23032
+ var SetScanningInclusionRequestSchema = external_exports.object({
23033
+ repositoryIds: external_exports.array(external_exports.uuid()).min(1).max(500),
23034
+ includedInScanning: external_exports.boolean()
23035
+ });
23036
+ var SetScanningInclusionResponseSchema = external_exports.object({
23037
+ /** Rows whose flag now matches the request (already-matching rows count). */
23038
+ updatedCount: external_exports.number().int().min(0),
23039
+ /** IDs from the request that are not repositories of this organization. */
23040
+ notFoundRepositoryIds: external_exports.array(external_exports.uuid())
23041
+ });
23042
+ var SetPrScansEnabledRequestSchema = external_exports.object({
23043
+ enabled: external_exports.boolean()
23044
+ });
23045
+ var StaffRepositoryPrScanSettingSchema = external_exports.object({
23046
+ repositoryId: external_exports.uuid(),
23047
+ /** GitHub owner/name when synced; null for rows created before the sync backfill. */
23048
+ fullName: external_exports.string().nullable(),
23049
+ repositoryUrl: external_exports.url(),
23050
+ /** The staff-set opt-in arm of the gate. */
23051
+ prScansEnabled: external_exports.boolean(),
23052
+ /**
23053
+ * The implicit arm: a completed FULL SAST scan exists for this repo (any
23054
+ * branch). With the org capability granted, either arm open means PR scans run.
23055
+ */
23056
+ hasSastBaseline: external_exports.boolean()
23057
+ });
23058
+ var StaffPrScanSettingsResponseSchema = external_exports.object({
23059
+ /** Org-level gate: without AUTO_PR_SCANS the per-repo switches are inert. */
23060
+ orgHasAutoPrScans: external_exports.boolean(),
23061
+ repositories: external_exports.array(StaffRepositoryPrScanSettingSchema)
23062
+ });
23063
+ var CloneTokenRequestSchema = external_exports.object({
23064
+ repositoryUrl: external_exports.string().url()
23065
+ });
23066
+ var CloneTokenResponseSchema = external_exports.object({
23067
+ token: external_exports.string(),
23068
+ expiresAt: external_exports.string().datetime(),
23069
+ // Git username scheme to pair with this token. GitHub installation tokens
23070
+ // use `x-access-token`; Bitbucket app tokens use `x-token-auth`. Optional
23071
+ // for back-compat with CLIs that predate Bitbucket support and hardcode
23072
+ // `x-access-token` (the correct value for the GitHub-only flow they gate on).
23073
+ username: external_exports.enum(["x-access-token", "x-token-auth"]).optional()
23074
+ });
23075
+ var ScanningBranchHistoryEntrySchema = external_exports.object({
23076
+ historyId: external_exports.uuid(),
23077
+ branch: external_exports.string(),
23078
+ configuredAt: external_exports.date(),
23079
+ replacedAt: external_exports.date(),
23080
+ configuredByUserId: external_exports.uuid().nullable()
23081
+ });
23082
+ var ScanningBranchStateSchema = external_exports.object({
23083
+ scanningBranch: external_exports.string().nullable(),
23084
+ githubDefaultBranch: external_exports.string(),
23085
+ history: external_exports.array(ScanningBranchHistoryEntrySchema)
23086
+ });
23087
+ var SetScanningBranchRequestSchema = external_exports.object({
23088
+ branch: external_exports.string().min(1).max(255),
23089
+ migrateOpenVulnerabilities: external_exports.boolean(),
23090
+ /**
23091
+ * Optional compare-and-swap guard. When provided, the switch only commits
23092
+ * if the repo's current `scanningBranch` matches. Mismatch → HTTP 409.
23093
+ * `null` means "expect this repo to still be unconfigured."
23094
+ */
23095
+ expectedCurrentBranch: external_exports.string().nullable().optional()
23096
+ });
23097
+ var SetScanningBranchResponseSchema = external_exports.object({
23098
+ previousBranch: external_exports.string().nullable(),
23099
+ newBranch: external_exports.string(),
23100
+ relabeledVulnerabilityCount: external_exports.number().int().min(0),
23101
+ /** Null when previousBranch was null (initial configuration). */
23102
+ historyId: external_exports.uuid().nullable()
23103
+ });
23104
+ var BulkSetScanningBranchBranchSchema = external_exports.discriminatedUnion("kind", [
23105
+ external_exports.object({ kind: external_exports.literal("literal"), value: external_exports.string().min(1).max(255) }),
23106
+ external_exports.object({ kind: external_exports.literal("github-default") })
23107
+ ]);
23108
+ var BulkSetScanningBranchRequestSchema = external_exports.object({
23109
+ branch: BulkSetScanningBranchBranchSchema,
23110
+ repositoryIds: external_exports.array(external_exports.uuid()).min(1).max(100),
23111
+ migrateOpenVulnerabilities: external_exports.boolean()
23112
+ });
23113
+ var BulkSetScanningBranchResultStatusValues = [
23114
+ "switched",
23115
+ "branch-missing-on-github",
23116
+ "forbidden",
23117
+ "already-on-branch",
23118
+ "not-found",
23119
+ "error"
23120
+ ];
23121
+ var BulkSetScanningBranchResultSchema = external_exports.object({
23122
+ repositoryId: external_exports.uuid(),
23123
+ status: external_exports.enum(BulkSetScanningBranchResultStatusValues),
23124
+ relabeledVulnerabilityCount: external_exports.number().int().min(0).optional(),
23125
+ historyId: external_exports.uuid().nullable().optional(),
23126
+ errorMessage: external_exports.string().optional()
23127
+ });
23128
+ var BulkSetScanningBranchResponseSchema = external_exports.object({
23129
+ results: external_exports.array(BulkSetScanningBranchResultSchema)
23130
+ });
23131
+ var ScanningBranchPreferenceSchema = external_exports.object({
23132
+ autoConfigureScanningBranch: external_exports.boolean()
23133
+ });
23134
+ var ConfirmScanningBranchDefaultsResponseSchema = external_exports.object({
23135
+ autoConfigureScanningBranch: external_exports.literal(true),
23136
+ /** Repos the sweep configured to their default-branch mirror. */
23137
+ configuredCount: external_exports.number().int().min(0),
23138
+ /**
23139
+ * Rows skipped by the sweep's domain guards (empty or >255-char mirror).
23140
+ * They stay NULL and keep the "waiting on a scanning branch" banner alive.
23141
+ */
23142
+ skippedCount: external_exports.number().int().min(0)
23143
+ });
23144
+
23145
+ // ../../packages/api-contracts/src/schemas/api/v1/application.api.ts
23146
+ var ApplicationTypeValues = ["WEB", "CLI", "MOBILE", "DESKTOP", "API_SERVICE"];
23147
+ var APPLICATION_NOTES_MAX_CHARS = 2e3;
23148
+ var ApplicationRepositoryRoleValues = [
23149
+ "FRONTEND",
23150
+ "BACKEND_API",
23151
+ "AUTH_SERVICE",
23152
+ "WORKER_JOB_SERVICE",
23153
+ "SHARED_PACKAGE_SDK",
23154
+ "INFRASTRUCTURE_IAC",
23155
+ "MOBILE_CLIENT",
23156
+ "MONOREPO",
23157
+ "OTHER"
23158
+ ];
23159
+ var ApplicationIdParamsSchema = OrgIdParamsSchema.extend({
23160
+ applicationId: external_exports.uuid()
23161
+ });
23162
+ var ApplicationRepositoryIdParamsSchema = ApplicationIdParamsSchema.extend({
23163
+ applicationRepositoryId: external_exports.uuid()
23164
+ });
23165
+ var ApplicationRepositorySummarySchema = external_exports.object({
23166
+ applicationRepositoryId: external_exports.uuid().nullable(),
23167
+ applicationId: external_exports.uuid(),
23168
+ organizationId: external_exports.uuid(),
23169
+ repositoryId: external_exports.uuid(),
23170
+ repositoryName: external_exports.string(),
23171
+ repositoryUrl: external_exports.string(),
23172
+ repositoryStatus: external_exports.enum(RepositoryStatusValues),
23173
+ htmlUrl: external_exports.string().nullable(),
23174
+ createdAt: external_exports.date(),
23175
+ updatedAt: external_exports.date()
23176
+ });
23177
+ var ApplicationRepositoryRolesSchema = external_exports.array(external_exports.enum(ApplicationRepositoryRoleValues)).max(ApplicationRepositoryRoleValues.length);
23178
+ var ApplicationRepositoryLinkResponseSchema = ApplicationRepositorySummarySchema.extend({
23179
+ // First of `roles` (enum order), or null when unspecified. Kept so a new
23180
+ // client reading a pre-this-release API during a rolling deploy still parses.
23181
+ role: external_exports.enum(ApplicationRepositoryRoleValues).nullable(),
23182
+ // Source of truth. Defaulted empty so a new client reading a pre-this-release
23183
+ // API that omitted the field doesn't reject the row; the client then falls
23184
+ // back to wrapping `role`.
23185
+ roles: ApplicationRepositoryRolesSchema.default([]),
23186
+ roleLabel: external_exports.string().max(120).nullable(),
23187
+ repositoryPath: external_exports.string().max(500).nullable(),
23188
+ scanEnabled: external_exports.boolean()
23189
+ });
23190
+ var ListApplicationRepositoryLinksResponseSchema = external_exports.array(
23191
+ ApplicationRepositoryLinkResponseSchema
23192
+ );
23193
+ var ApplicationResponseSchema = external_exports.object({
23194
+ applicationId: external_exports.uuid(),
23195
+ organizationId: external_exports.uuid(),
23196
+ name: external_exports.string(),
23197
+ // `.default('WEB')` keeps responses backward-compatible: a pre-P1.3 API that
23198
+ // never emitted `type` parses cleanly (existing apps are semantically WEB),
23199
+ // so a new frontend reading an old API during a mixed-version rollout doesn't
23200
+ // reject application rows.
23201
+ type: external_exports.enum(ApplicationTypeValues).default("WEB"),
23202
+ applicationUrl: external_exports.string().nullable(),
23203
+ // Customer-authored free-text context, any type ("Advanced → Notes").
23204
+ notes: external_exports.string().nullable(),
23205
+ helpCenterUrl: external_exports.string().nullable(),
23206
+ documentationUrl: external_exports.string().nullable(),
23207
+ repositories: external_exports.array(ApplicationRepositorySummarySchema),
23208
+ // Registrable domains RECON is authorized to discover subdomains under. The
23209
+ // Environments-tab panel hydrates from this payload (no client GET). Defaulted
23210
+ // (like `type`) so a new client reading a pre-this-release API during a rolling
23211
+ // deploy doesn't reject application rows that predate the field.
23212
+ // Signed S3 URL for the Overview screenshot. Defaulted null so a new client
23213
+ // reading a pre-this-release API during a rolling deploy doesn't reject rows
23214
+ // that omit the field. The raw S3 key is never on the wire.
23215
+ screenshotUrl: external_exports.url().nullable().default(null),
23216
+ // Defaulted null so a new client reading a pre-this-release API during a
23217
+ // rolling deploy doesn't reject application rows that omit the field.
23218
+ credentialsNudgeDismissedAt: external_exports.date().nullable().default(null),
23219
+ createdAt: external_exports.date(),
23220
+ updatedAt: external_exports.date()
23221
+ });
23222
+ var ListApplicationsResponseSchema = external_exports.array(ApplicationResponseSchema);
23223
+ var CreateApplicationRequestSchema = external_exports.object({
23224
+ name: external_exports.string().min(1).max(200),
23225
+ type: external_exports.enum(ApplicationTypeValues).default("WEB"),
23226
+ applicationUrl: external_exports.url().max(2048).optional(),
23227
+ notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).optional(),
23228
+ repositoryId: external_exports.uuid().optional(),
23229
+ repositoryPath: external_exports.string().max(500).optional(),
23230
+ helpCenterUrl: external_exports.url().max(2048).optional(),
23231
+ documentationUrl: external_exports.url().max(2048).optional()
23232
+ }).strict().refine((data) => !isUrlBearingApplicationType(data.type) || data.applicationUrl != null, {
23233
+ path: ["applicationUrl"],
23234
+ message: "A web or API application requires an application URL."
23235
+ }).refine((data) => isUrlBearingApplicationType(data.type) || data.applicationUrl == null, {
23236
+ path: ["applicationUrl"],
23237
+ message: "Only web or API applications can have an application URL."
23238
+ });
23239
+ var CreateApplicationRepositoryLinkRequestSchema = external_exports.object({
23240
+ repositoryId: external_exports.uuid(),
23241
+ // Legacy single-role write. Ignored when `roles` is also sent.
23242
+ role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
23243
+ roles: ApplicationRepositoryRolesSchema.optional(),
23244
+ roleLabel: external_exports.string().max(120).nullable().optional(),
23245
+ repositoryPath: external_exports.string().max(500).nullable().optional(),
23246
+ scanEnabled: external_exports.boolean().optional()
23247
+ }).strict();
23248
+ var UpdateApplicationRepositoryLinkRequestSchema = external_exports.object({
23249
+ // Legacy single-role write. Ignored when `roles` is also sent.
23250
+ role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
23251
+ roles: ApplicationRepositoryRolesSchema.optional(),
23252
+ roleLabel: external_exports.string().max(120).nullable().optional(),
23253
+ repositoryPath: external_exports.string().max(500).nullable().optional(),
23254
+ scanEnabled: external_exports.boolean().optional()
23255
+ }).strict();
23256
+ var UpdateApplicationRequestSchema = external_exports.object({
23257
+ name: external_exports.string().min(1).max(200).optional(),
23258
+ applicationUrl: external_exports.url().max(2048).optional(),
23259
+ notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).nullable().optional(),
23260
+ repositoryId: external_exports.uuid().nullable().optional(),
23261
+ repositoryPath: external_exports.string().max(500).nullable().optional(),
23262
+ helpCenterUrl: external_exports.url().max(2048).nullable().optional(),
23263
+ documentationUrl: external_exports.url().max(2048).nullable().optional()
23264
+ }).strict();
23265
+
23266
+ // ../../packages/api-contracts/src/schemas/api/v1/product-evidence.api.ts
23267
+ var ProductEvidenceKindSchema = external_exports.enum(["docs", "source", "live"]);
23268
+ var EvidenceRefSchema = external_exports.object({
23269
+ ref: external_exports.string().min(1).max(512),
23270
+ why: external_exports.string().min(1).max(300)
23271
+ });
23272
+
23273
+ // ../../packages/api-contracts/src/schemas/api/v1/application-surface-map.api.ts
23274
+ var SURFACE_FEATURE_ROLES_MAX = 20;
23275
+ var SURFACE_FEATURE_ENDPOINTS_MAX = 60;
23276
+ var SURFACE_FEATURE_NAME_MAX_CHARS = 120;
23277
+ var SURFACE_FEATURE_SUMMARY_MAX_CHARS = 600;
23278
+ var SURFACE_ROLE_NAME_MAX_CHARS = 60;
23279
+ var SURFACE_ROLE_DESCRIPTION_MAX_CHARS = 200;
23280
+ var SURFACE_ENDPOINT_LABEL_MAX_CHARS = 200;
23281
+ var SURFACE_SOURCE_NOTE_MAX_CHARS = 300;
23282
+ var SurfaceRoleSchema = external_exports.object({
23283
+ name: external_exports.string().min(1).max(SURFACE_ROLE_NAME_MAX_CHARS),
23284
+ description: external_exports.string().min(1).max(SURFACE_ROLE_DESCRIPTION_MAX_CHARS).optional()
23285
+ });
23286
+ var SurfaceEndpointKindSchema = external_exports.enum(["http", "ipc", "deeplink", "other"]);
23287
+ var SurfaceEndpointSchema = external_exports.object({
23288
+ kind: SurfaceEndpointKindSchema,
23289
+ /** A path, a route, a command, a screen. */
23290
+ label: external_exports.string().min(1).max(SURFACE_ENDPOINT_LABEL_MAX_CHARS),
23291
+ method: external_exports.string().min(1).max(10).optional()
23292
+ });
23293
+ var SurfaceSourceEntrySchema = external_exports.object({
23294
+ kind: external_exports.enum(["docs", "source", "live", "staff", "system"]),
23295
+ verdict: external_exports.enum(["observed", "removed"]),
23296
+ agentSessionId: external_exports.uuid().optional(),
23297
+ staffLabel: external_exports.string().min(1).max(320).optional(),
23298
+ /** A staff reason, an agent removal reason, or "not seen in 2 full runs". */
23299
+ note: external_exports.string().min(1).max(SURFACE_SOURCE_NOTE_MAX_CHARS).optional(),
23300
+ refs: external_exports.array(EvidenceRefSchema).max(10),
23301
+ at: external_exports.iso.datetime()
23302
+ });
23303
+ var SurfaceFeatureRetiredReasonSchema = external_exports.enum([
23304
+ "OBSERVED_REMOVED",
23305
+ "UNOBSERVED",
23306
+ "STAFF"
23307
+ ]);
23308
+ var SurfaceMapParamsSchema = OrgIdParamsSchema.extend({
23309
+ pentestId: PentestIdOrDisplayIdSchema
23310
+ });
23311
+ var SurfaceFeatureIdParamsSchema = SurfaceMapParamsSchema.extend({
23312
+ featureId: external_exports.uuid()
23313
+ });
23314
+ var SurfaceFeatureSchema = external_exports.object({
23315
+ featureId: external_exports.uuid(),
23316
+ applicationId: external_exports.uuid(),
23317
+ slug: external_exports.string(),
23318
+ name: external_exports.string(),
23319
+ summary: external_exports.string(),
23320
+ nameEditedByLabel: external_exports.string().nullable(),
23321
+ roles: external_exports.array(SurfaceRoleSchema),
23322
+ endpoints: external_exports.array(SurfaceEndpointSchema),
23323
+ sources: external_exports.array(SurfaceSourceEntrySchema),
23324
+ /** A field whose stored JSON failed its parse is named here; the field renders as unreadable. */
23325
+ unparseableFields: external_exports.array(external_exports.enum(["roles", "endpoints", "sources"])),
23326
+ /** Active, and a `removed` entry younger than 30 days: something said it was gone and it stands. */
23327
+ disputed: external_exports.boolean(),
23328
+ /** Active, and not observed since the latest FULL run on this application started. */
23329
+ unconfirmedByLatestFullRun: external_exports.boolean(),
23330
+ firstRecordedAt: external_exports.coerce.date(),
23331
+ lastRecordedAt: external_exports.coerce.date(),
23332
+ lastObservedAt: external_exports.coerce.date(),
23333
+ retired: external_exports.object({
23334
+ at: external_exports.coerce.date(),
23335
+ reason: SurfaceFeatureRetiredReasonSchema,
23336
+ byLabel: external_exports.string().nullable(),
23337
+ note: external_exports.string().nullable(),
23338
+ mergedInto: external_exports.object({ featureId: external_exports.uuid(), name: external_exports.string() }).nullable()
23339
+ }).nullable()
23340
+ });
23341
+ var SurfaceMapLatestProductReconSchema = external_exports.object({
23342
+ agentSessionId: external_exports.uuid(),
23343
+ status: AgentSessionStatus,
23344
+ promptVersion: external_exports.string(),
23345
+ /** Whether that prompt version writes the feature map at all (v3 onward). */
23346
+ recordsFeatures: external_exports.boolean(),
23347
+ createdAt: external_exports.coerce.date(),
23348
+ completedAt: external_exports.coerce.date().nullable(),
23349
+ /** Whether that session wrote at least one feature (any outcome but rejected). */
23350
+ wroteFeatures: external_exports.boolean()
23351
+ });
23352
+ var SurfaceMapApplicationSchema = external_exports.object({
23353
+ applicationId: external_exports.uuid(),
23354
+ name: external_exports.string(),
23355
+ type: external_exports.enum(ApplicationTypeValues),
23356
+ ordinal: external_exports.number().int(),
23357
+ /** Whether this application type has a FULL run definition, so unconfirmed rows can retire. */
23358
+ fullRunsApply: external_exports.boolean(),
23359
+ /** The latest PRODUCT_RECON session on this lens, any version and any status; the empty states read it. */
23360
+ latestProductRecon: SurfaceMapLatestProductReconSchema.nullable(),
23361
+ /** Latest session on this lens the retirement pass counted as FULL. */
23362
+ lastFullRunAt: external_exports.coerce.date().nullable(),
23363
+ features: external_exports.array(SurfaceFeatureSchema)
23364
+ });
23365
+ var SurfaceMapResponseSchema = external_exports.object({
23366
+ applications: external_exports.array(SurfaceMapApplicationSchema)
23367
+ });
23368
+ var AddSurfaceFeatureRequestSchema = external_exports.object({
23369
+ applicationId: external_exports.uuid(),
23370
+ name: external_exports.string().min(1).max(SURFACE_FEATURE_NAME_MAX_CHARS),
23371
+ summary: external_exports.string().min(1).max(SURFACE_FEATURE_SUMMARY_MAX_CHARS)
23372
+ });
23373
+ var RenameSurfaceFeatureRequestSchema = external_exports.object({
23374
+ name: external_exports.string().min(1).max(SURFACE_FEATURE_NAME_MAX_CHARS).optional(),
23375
+ summary: external_exports.string().min(1).max(SURFACE_FEATURE_SUMMARY_MAX_CHARS).optional(),
23376
+ /** Clear the staff hold so product recon's next write may reword the feature again. */
23377
+ releaseToAgent: external_exports.literal(true).optional()
23378
+ }).refine((v) => v.name !== void 0 || v.summary !== void 0 || v.releaseToAgent === true, {
23379
+ message: "name, summary, or releaseToAgent is required"
23380
+ });
23381
+ var RetireSurfaceFeatureRequestSchema = external_exports.object({
23382
+ reason: external_exports.string().min(1).max(SURFACE_SOURCE_NOTE_MAX_CHARS)
23383
+ });
23384
+ var MergeSurfaceFeatureRequestSchema = external_exports.object({
23385
+ intoFeatureId: external_exports.uuid()
23386
+ });
23387
+ var SurfaceFeatureConflictDetailsSchema = external_exports.object({
23388
+ existing: external_exports.object({ featureId: external_exports.uuid(), name: external_exports.string(), retired: external_exports.boolean() })
23389
+ });
23390
+
22926
23391
  // ../../packages/api-contracts/src/schemas/api/v1/code-upload.api.ts
22927
23392
  var CODE_UPLOAD_MAX_BYTES = 1024 * 1024 * 1024;
22928
23393
  var CODE_UPLOAD_PART_SIZE_BYTES = 10 * 1024 * 1024;
@@ -23439,277 +23904,6 @@ var LinearTicketContextResponseSchema = external_exports.object({
23439
23904
  var AttestationClassificationValues = ["PUBLIC", "CONFIDENTIAL"];
23440
23905
  var AttestationClassification = external_exports.enum(AttestationClassificationValues);
23441
23906
 
23442
- // ../../packages/api-contracts/src/schemas/api/v1/repository.api.ts
23443
- var PlatformValues = ["GITHUB", "GITLAB", "BITBUCKET", "UPLOAD"];
23444
- var RepositoryStatusValues = ["CONNECTED", "DISCONNECTED"];
23445
- var RepositoryIdParamsSchema = OrgIdParamsSchema.extend({
23446
- repositoryId: external_exports.uuid()
23447
- });
23448
- var CreateRepositoryRequestSchema = external_exports.object({
23449
- repositoryUrl: external_exports.url(),
23450
- platform: external_exports.enum(PlatformValues),
23451
- githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
23452
- status: external_exports.enum(RepositoryStatusValues).optional()
23453
- });
23454
- var UpdateRepositoryRequestSchema = external_exports.object({
23455
- repositoryUrl: external_exports.url().optional(),
23456
- platform: external_exports.enum(PlatformValues).optional(),
23457
- githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
23458
- status: external_exports.enum(RepositoryStatusValues).optional()
23459
- });
23460
- var RepositoryResponseSchema = external_exports.object({
23461
- repositoryId: external_exports.uuid(),
23462
- organizationId: external_exports.uuid(),
23463
- repositoryUrl: external_exports.url(),
23464
- platform: external_exports.enum(PlatformValues),
23465
- status: external_exports.enum(RepositoryStatusValues),
23466
- githubDefaultBranch: external_exports.string(),
23467
- scanningBranch: external_exports.string().nullable(),
23468
- primaryLanguage: external_exports.string().nullable().optional(),
23469
- /** Staff-set opt-in: automated PR scans run on this repo even without a FULL SAST baseline. */
23470
- prScansEnabled: external_exports.boolean(),
23471
- /** Customer-set gate: false = no scans of any kind run for this repo until it is included again. */
23472
- includedInScanning: external_exports.boolean(),
23473
- /** Host archive flag mirrored from the provider. */
23474
- isArchived: external_exports.boolean(),
23475
- createdAt: external_exports.date(),
23476
- updatedAt: external_exports.date()
23477
- });
23478
- var ListRepositoriesResponseSchema = external_exports.array(RepositoryResponseSchema);
23479
- var SetScanningInclusionRequestSchema = external_exports.object({
23480
- repositoryIds: external_exports.array(external_exports.uuid()).min(1).max(500),
23481
- includedInScanning: external_exports.boolean()
23482
- });
23483
- var SetScanningInclusionResponseSchema = external_exports.object({
23484
- /** Rows whose flag now matches the request (already-matching rows count). */
23485
- updatedCount: external_exports.number().int().min(0),
23486
- /** IDs from the request that are not repositories of this organization. */
23487
- notFoundRepositoryIds: external_exports.array(external_exports.uuid())
23488
- });
23489
- var SetPrScansEnabledRequestSchema = external_exports.object({
23490
- enabled: external_exports.boolean()
23491
- });
23492
- var StaffRepositoryPrScanSettingSchema = external_exports.object({
23493
- repositoryId: external_exports.uuid(),
23494
- /** GitHub owner/name when synced; null for rows created before the sync backfill. */
23495
- fullName: external_exports.string().nullable(),
23496
- repositoryUrl: external_exports.url(),
23497
- /** The staff-set opt-in arm of the gate. */
23498
- prScansEnabled: external_exports.boolean(),
23499
- /**
23500
- * The implicit arm: a completed FULL SAST scan exists for this repo (any
23501
- * branch). With the org capability granted, either arm open means PR scans run.
23502
- */
23503
- hasSastBaseline: external_exports.boolean()
23504
- });
23505
- var StaffPrScanSettingsResponseSchema = external_exports.object({
23506
- /** Org-level gate: without AUTO_PR_SCANS the per-repo switches are inert. */
23507
- orgHasAutoPrScans: external_exports.boolean(),
23508
- repositories: external_exports.array(StaffRepositoryPrScanSettingSchema)
23509
- });
23510
- var CloneTokenRequestSchema = external_exports.object({
23511
- repositoryUrl: external_exports.string().url()
23512
- });
23513
- var CloneTokenResponseSchema = external_exports.object({
23514
- token: external_exports.string(),
23515
- expiresAt: external_exports.string().datetime(),
23516
- // Git username scheme to pair with this token. GitHub installation tokens
23517
- // use `x-access-token`; Bitbucket app tokens use `x-token-auth`. Optional
23518
- // for back-compat with CLIs that predate Bitbucket support and hardcode
23519
- // `x-access-token` (the correct value for the GitHub-only flow they gate on).
23520
- username: external_exports.enum(["x-access-token", "x-token-auth"]).optional()
23521
- });
23522
- var ScanningBranchHistoryEntrySchema = external_exports.object({
23523
- historyId: external_exports.uuid(),
23524
- branch: external_exports.string(),
23525
- configuredAt: external_exports.date(),
23526
- replacedAt: external_exports.date(),
23527
- configuredByUserId: external_exports.uuid().nullable()
23528
- });
23529
- var ScanningBranchStateSchema = external_exports.object({
23530
- scanningBranch: external_exports.string().nullable(),
23531
- githubDefaultBranch: external_exports.string(),
23532
- history: external_exports.array(ScanningBranchHistoryEntrySchema)
23533
- });
23534
- var SetScanningBranchRequestSchema = external_exports.object({
23535
- branch: external_exports.string().min(1).max(255),
23536
- migrateOpenVulnerabilities: external_exports.boolean(),
23537
- /**
23538
- * Optional compare-and-swap guard. When provided, the switch only commits
23539
- * if the repo's current `scanningBranch` matches. Mismatch → HTTP 409.
23540
- * `null` means "expect this repo to still be unconfigured."
23541
- */
23542
- expectedCurrentBranch: external_exports.string().nullable().optional()
23543
- });
23544
- var SetScanningBranchResponseSchema = external_exports.object({
23545
- previousBranch: external_exports.string().nullable(),
23546
- newBranch: external_exports.string(),
23547
- relabeledVulnerabilityCount: external_exports.number().int().min(0),
23548
- /** Null when previousBranch was null (initial configuration). */
23549
- historyId: external_exports.uuid().nullable()
23550
- });
23551
- var BulkSetScanningBranchBranchSchema = external_exports.discriminatedUnion("kind", [
23552
- external_exports.object({ kind: external_exports.literal("literal"), value: external_exports.string().min(1).max(255) }),
23553
- external_exports.object({ kind: external_exports.literal("github-default") })
23554
- ]);
23555
- var BulkSetScanningBranchRequestSchema = external_exports.object({
23556
- branch: BulkSetScanningBranchBranchSchema,
23557
- repositoryIds: external_exports.array(external_exports.uuid()).min(1).max(100),
23558
- migrateOpenVulnerabilities: external_exports.boolean()
23559
- });
23560
- var BulkSetScanningBranchResultStatusValues = [
23561
- "switched",
23562
- "branch-missing-on-github",
23563
- "forbidden",
23564
- "already-on-branch",
23565
- "not-found",
23566
- "error"
23567
- ];
23568
- var BulkSetScanningBranchResultSchema = external_exports.object({
23569
- repositoryId: external_exports.uuid(),
23570
- status: external_exports.enum(BulkSetScanningBranchResultStatusValues),
23571
- relabeledVulnerabilityCount: external_exports.number().int().min(0).optional(),
23572
- historyId: external_exports.uuid().nullable().optional(),
23573
- errorMessage: external_exports.string().optional()
23574
- });
23575
- var BulkSetScanningBranchResponseSchema = external_exports.object({
23576
- results: external_exports.array(BulkSetScanningBranchResultSchema)
23577
- });
23578
- var ScanningBranchPreferenceSchema = external_exports.object({
23579
- autoConfigureScanningBranch: external_exports.boolean()
23580
- });
23581
- var ConfirmScanningBranchDefaultsResponseSchema = external_exports.object({
23582
- autoConfigureScanningBranch: external_exports.literal(true),
23583
- /** Repos the sweep configured to their default-branch mirror. */
23584
- configuredCount: external_exports.number().int().min(0),
23585
- /**
23586
- * Rows skipped by the sweep's domain guards (empty or >255-char mirror).
23587
- * They stay NULL and keep the "waiting on a scanning branch" banner alive.
23588
- */
23589
- skippedCount: external_exports.number().int().min(0)
23590
- });
23591
-
23592
- // ../../packages/api-contracts/src/schemas/api/v1/application.api.ts
23593
- var ApplicationTypeValues = ["WEB", "CLI", "MOBILE", "DESKTOP", "API_SERVICE"];
23594
- var APPLICATION_NOTES_MAX_CHARS = 2e3;
23595
- var ApplicationRepositoryRoleValues = [
23596
- "FRONTEND",
23597
- "BACKEND_API",
23598
- "AUTH_SERVICE",
23599
- "WORKER_JOB_SERVICE",
23600
- "SHARED_PACKAGE_SDK",
23601
- "INFRASTRUCTURE_IAC",
23602
- "MOBILE_CLIENT",
23603
- "MONOREPO",
23604
- "OTHER"
23605
- ];
23606
- var ApplicationIdParamsSchema = OrgIdParamsSchema.extend({
23607
- applicationId: external_exports.uuid()
23608
- });
23609
- var ApplicationRepositoryIdParamsSchema = ApplicationIdParamsSchema.extend({
23610
- applicationRepositoryId: external_exports.uuid()
23611
- });
23612
- var ApplicationRepositorySummarySchema = external_exports.object({
23613
- applicationRepositoryId: external_exports.uuid().nullable(),
23614
- applicationId: external_exports.uuid(),
23615
- organizationId: external_exports.uuid(),
23616
- repositoryId: external_exports.uuid(),
23617
- repositoryName: external_exports.string(),
23618
- repositoryUrl: external_exports.string(),
23619
- repositoryStatus: external_exports.enum(RepositoryStatusValues),
23620
- htmlUrl: external_exports.string().nullable(),
23621
- createdAt: external_exports.date(),
23622
- updatedAt: external_exports.date()
23623
- });
23624
- var ApplicationRepositoryRolesSchema = external_exports.array(external_exports.enum(ApplicationRepositoryRoleValues)).max(ApplicationRepositoryRoleValues.length);
23625
- var ApplicationRepositoryLinkResponseSchema = ApplicationRepositorySummarySchema.extend({
23626
- // First of `roles` (enum order), or null when unspecified. Kept so a new
23627
- // client reading a pre-this-release API during a rolling deploy still parses.
23628
- role: external_exports.enum(ApplicationRepositoryRoleValues).nullable(),
23629
- // Source of truth. Defaulted empty so a new client reading a pre-this-release
23630
- // API that omitted the field doesn't reject the row; the client then falls
23631
- // back to wrapping `role`.
23632
- roles: ApplicationRepositoryRolesSchema.default([]),
23633
- roleLabel: external_exports.string().max(120).nullable(),
23634
- repositoryPath: external_exports.string().max(500).nullable(),
23635
- scanEnabled: external_exports.boolean()
23636
- });
23637
- var ListApplicationRepositoryLinksResponseSchema = external_exports.array(
23638
- ApplicationRepositoryLinkResponseSchema
23639
- );
23640
- var ApplicationResponseSchema = external_exports.object({
23641
- applicationId: external_exports.uuid(),
23642
- organizationId: external_exports.uuid(),
23643
- name: external_exports.string(),
23644
- // `.default('WEB')` keeps responses backward-compatible: a pre-P1.3 API that
23645
- // never emitted `type` parses cleanly (existing apps are semantically WEB),
23646
- // so a new frontend reading an old API during a mixed-version rollout doesn't
23647
- // reject application rows.
23648
- type: external_exports.enum(ApplicationTypeValues).default("WEB"),
23649
- applicationUrl: external_exports.string().nullable(),
23650
- // Customer-authored free-text context, any type ("Advanced → Notes").
23651
- notes: external_exports.string().nullable(),
23652
- helpCenterUrl: external_exports.string().nullable(),
23653
- documentationUrl: external_exports.string().nullable(),
23654
- repositories: external_exports.array(ApplicationRepositorySummarySchema),
23655
- // Registrable domains RECON is authorized to discover subdomains under. The
23656
- // Environments-tab panel hydrates from this payload (no client GET). Defaulted
23657
- // (like `type`) so a new client reading a pre-this-release API during a rolling
23658
- // deploy doesn't reject application rows that predate the field.
23659
- // Signed S3 URL for the Overview screenshot. Defaulted null so a new client
23660
- // reading a pre-this-release API during a rolling deploy doesn't reject rows
23661
- // that omit the field. The raw S3 key is never on the wire.
23662
- screenshotUrl: external_exports.url().nullable().default(null),
23663
- // Defaulted null so a new client reading a pre-this-release API during a
23664
- // rolling deploy doesn't reject application rows that omit the field.
23665
- credentialsNudgeDismissedAt: external_exports.date().nullable().default(null),
23666
- createdAt: external_exports.date(),
23667
- updatedAt: external_exports.date()
23668
- });
23669
- var ListApplicationsResponseSchema = external_exports.array(ApplicationResponseSchema);
23670
- var CreateApplicationRequestSchema = external_exports.object({
23671
- name: external_exports.string().min(1).max(200),
23672
- type: external_exports.enum(ApplicationTypeValues).default("WEB"),
23673
- applicationUrl: external_exports.url().max(2048).optional(),
23674
- notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).optional(),
23675
- repositoryId: external_exports.uuid().optional(),
23676
- repositoryPath: external_exports.string().max(500).optional(),
23677
- helpCenterUrl: external_exports.url().max(2048).optional(),
23678
- documentationUrl: external_exports.url().max(2048).optional()
23679
- }).strict().refine((data) => !isUrlBearingApplicationType(data.type) || data.applicationUrl != null, {
23680
- path: ["applicationUrl"],
23681
- message: "A web or API application requires an application URL."
23682
- }).refine((data) => isUrlBearingApplicationType(data.type) || data.applicationUrl == null, {
23683
- path: ["applicationUrl"],
23684
- message: "Only web or API applications can have an application URL."
23685
- });
23686
- var CreateApplicationRepositoryLinkRequestSchema = external_exports.object({
23687
- repositoryId: external_exports.uuid(),
23688
- // Legacy single-role write. Ignored when `roles` is also sent.
23689
- role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
23690
- roles: ApplicationRepositoryRolesSchema.optional(),
23691
- roleLabel: external_exports.string().max(120).nullable().optional(),
23692
- repositoryPath: external_exports.string().max(500).nullable().optional(),
23693
- scanEnabled: external_exports.boolean().optional()
23694
- }).strict();
23695
- var UpdateApplicationRepositoryLinkRequestSchema = external_exports.object({
23696
- // Legacy single-role write. Ignored when `roles` is also sent.
23697
- role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
23698
- roles: ApplicationRepositoryRolesSchema.optional(),
23699
- roleLabel: external_exports.string().max(120).nullable().optional(),
23700
- repositoryPath: external_exports.string().max(500).nullable().optional(),
23701
- scanEnabled: external_exports.boolean().optional()
23702
- }).strict();
23703
- var UpdateApplicationRequestSchema = external_exports.object({
23704
- name: external_exports.string().min(1).max(200).optional(),
23705
- applicationUrl: external_exports.url().max(2048).optional(),
23706
- notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).nullable().optional(),
23707
- repositoryId: external_exports.uuid().nullable().optional(),
23708
- repositoryPath: external_exports.string().max(500).nullable().optional(),
23709
- helpCenterUrl: external_exports.url().max(2048).nullable().optional(),
23710
- documentationUrl: external_exports.url().max(2048).nullable().optional()
23711
- }).strict();
23712
-
23713
23907
  // ../../packages/api-contracts/src/schemas/api/v1/pentest-report-pdf.api.ts
23714
23908
  var ReportPdfPentestParamsSchema = OrgIdParamsSchema.extend({
23715
23909
  pentestId: external_exports.uuid()
@@ -24422,6 +24616,250 @@ var ListReportIssuesResponseSchema = external_exports.object({
24422
24616
  issues: external_exports.array(ReportIssueSchema)
24423
24617
  });
24424
24618
 
24619
+ // ../../packages/api-contracts/src/schemas/api/v1/pentest-tag.api.ts
24620
+ var PENTEST_TAG_NAME_MAX_CHARS = 40;
24621
+ var PENTEST_TAG_DESCRIPTION_MAX_CHARS = 500;
24622
+ var PENTEST_TAGS_PER_PENTEST_MAX = 50;
24623
+ var PentestTagsParamsSchema = OrgIdParamsSchema.extend({
24624
+ pentestId: external_exports.string().min(1)
24625
+ });
24626
+ var PentestTagIdParamsSchema = PentestTagsParamsSchema.extend({
24627
+ pentestTagId: external_exports.uuid()
24628
+ });
24629
+ var tagName = external_exports.string().trim().min(1).max(PENTEST_TAG_NAME_MAX_CHARS);
24630
+ var tagDescription = external_exports.string().trim().max(PENTEST_TAG_DESCRIPTION_MAX_CHARS);
24631
+ var PentestTagResponseSchema = external_exports.object({
24632
+ pentestTagId: external_exports.uuid(),
24633
+ pentestId: external_exports.uuid(),
24634
+ organizationId: external_exports.uuid(),
24635
+ name: external_exports.string(),
24636
+ description: external_exports.string().nullable(),
24637
+ /** How many findings on the engagement currently wear the tag (drafts included on staff reads). */
24638
+ findingCount: external_exports.number().int().nonnegative(),
24639
+ createdById: external_exports.uuid(),
24640
+ createdAt: external_exports.coerce.date(),
24641
+ updatedAt: external_exports.coerce.date()
24642
+ });
24643
+ var ListPentestTagsResponseSchema = external_exports.array(PentestTagResponseSchema);
24644
+ var CreatePentestTagRequestSchema = external_exports.object({
24645
+ name: tagName,
24646
+ description: tagDescription.optional()
24647
+ }).strict();
24648
+ var UpdatePentestTagRequestSchema = external_exports.object({
24649
+ name: tagName.optional(),
24650
+ /** Null clears the description. */
24651
+ description: tagDescription.nullable().optional()
24652
+ }).strict();
24653
+ var PentestFindingTagSchema = external_exports.object({
24654
+ pentestTagId: external_exports.uuid(),
24655
+ name: external_exports.string()
24656
+ });
24657
+ var SetPentestFindingTagsRequestSchema = external_exports.object({
24658
+ pentestTagIds: external_exports.array(external_exports.uuid()).max(PENTEST_TAGS_PER_PENTEST_MAX)
24659
+ }).strict();
24660
+
24661
+ // ../../packages/api-contracts/src/schemas/domain/oob.schema.ts
24662
+ var OOB_MAX_BODY_BYTES = 1048576;
24663
+ var OOB_MAX_RESPONSE_BYTES = 65536;
24664
+ var OOB_MAX_ENVELOPE_BYTES = 2097152;
24665
+ var OobListenerStatusValues = ["ACTIVE", "CLOSED"];
24666
+ var OobCaptureStatusValues = ["PENDING", "COMPLETE", "FAILED"];
24667
+ var OobListenerHealthValues = ["PROBING", "READY", "FAILED"];
24668
+ var OobProtocolValues = ["HTTP", "HTTPS"];
24669
+ var OobProbeResultValues = ["PENDING", "VERIFIED", "FAILED"];
24670
+ var OobListenerStatusSchema = external_exports.enum(OobListenerStatusValues);
24671
+ var OobCaptureStatusSchema = external_exports.enum(OobCaptureStatusValues);
24672
+ var OobListenerHealthSchema = external_exports.enum(OobListenerHealthValues);
24673
+ var OobProtocolSchema = external_exports.enum(OobProtocolValues);
24674
+ var OobProbeResultSchema = external_exports.enum(OobProbeResultValues);
24675
+ var OobSha256Schema = external_exports.string().regex(/^[0-9a-f]{64}$/);
24676
+ var OobSequenceSchema = external_exports.string().regex(/^(0|[1-9][0-9]*)$/);
24677
+ var base643 = external_exports.string().regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/);
24678
+ var OobHeaderSchema = external_exports.strictObject({ name: external_exports.string(), value: external_exports.string() });
24679
+ var OobMultimapSchema = external_exports.unknown().transform((input, context) => {
24680
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
24681
+ context.addIssue({ code: "custom", message: "Expected a map of string arrays." });
24682
+ return external_exports.NEVER;
24683
+ }
24684
+ const entries = Object.entries(input);
24685
+ const parsedEntries = [];
24686
+ for (const [key, value] of entries) {
24687
+ const parsed = external_exports.array(external_exports.string()).safeParse(value);
24688
+ if (!parsed.success) {
24689
+ context.addIssue({ code: "custom", path: [key], message: "Expected an array of strings." });
24690
+ return external_exports.NEVER;
24691
+ }
24692
+ parsedEntries.push([key, parsed.data]);
24693
+ }
24694
+ return Object.fromEntries(parsedEntries);
24695
+ });
24696
+ var forbiddenResponseHeaders = /* @__PURE__ */ new Set([
24697
+ "connection",
24698
+ "content-length",
24699
+ "transfer-encoding",
24700
+ "keep-alive",
24701
+ "te",
24702
+ "trailer",
24703
+ "upgrade",
24704
+ "proxy-authenticate",
24705
+ "proxy-authorization"
24706
+ ]);
24707
+ var OobResponseSchema = external_exports.strictObject({
24708
+ status: external_exports.number().int().min(200).max(599),
24709
+ headers: external_exports.array(OobHeaderSchema).max(32),
24710
+ bodyBase64: base643.max(Math.ceil(OOB_MAX_RESPONSE_BYTES / 3) * 4)
24711
+ }).superRefine((response, context) => {
24712
+ const bytes = response.bodyBase64.length * 3 / 4 - (response.bodyBase64.endsWith("==") ? 2 : response.bodyBase64.endsWith("=") ? 1 : 0);
24713
+ if (bytes > OOB_MAX_RESPONSE_BYTES)
24714
+ context.addIssue({
24715
+ code: "custom",
24716
+ path: ["bodyBase64"],
24717
+ message: "Response body exceeds 65536 bytes."
24718
+ });
24719
+ if ([204, 205, 304].includes(response.status) && bytes !== 0)
24720
+ context.addIssue({
24721
+ code: "custom",
24722
+ path: ["bodyBase64"],
24723
+ message: "This response status requires an empty body."
24724
+ });
24725
+ let headerBytes = 0;
24726
+ response.headers.forEach((header, index) => {
24727
+ headerBytes += new TextEncoder().encode(`${header.name}: ${header.value}\r
24728
+ `).length;
24729
+ if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(header.name) || forbiddenResponseHeaders.has(header.name.toLowerCase()) || /[^\t\x20-\x7e\x80-\xff]/.test(header.value))
24730
+ context.addIssue({
24731
+ code: "custom",
24732
+ path: ["headers", index],
24733
+ message: "Response header name or value is unsupported."
24734
+ });
24735
+ if (header.name.toLowerCase() === "location") {
24736
+ try {
24737
+ const url2 = new URL(header.value);
24738
+ if (!["http:", "https:"].includes(url2.protocol)) throw new Error("scheme");
24739
+ } catch {
24740
+ context.addIssue({
24741
+ code: "custom",
24742
+ path: ["headers", index],
24743
+ message: "Location must be an HTTP or HTTPS URL."
24744
+ });
24745
+ }
24746
+ }
24747
+ });
24748
+ if (headerBytes > 8192)
24749
+ context.addIssue({
24750
+ code: "custom",
24751
+ path: ["headers"],
24752
+ message: "Response headers exceed 8192 bytes."
24753
+ });
24754
+ });
24755
+ var OobPersistenceRequestSchema = external_exports.discriminatedUnion("action", [
24756
+ external_exports.strictObject({
24757
+ action: external_exports.literal("admit"),
24758
+ publicToken: external_exports.string().regex(/^[a-z0-9]{32,64}$/),
24759
+ protocol: OobProtocolSchema,
24760
+ method: external_exports.string().regex(/^[A-Z]{1,20}$/),
24761
+ sourceIp: external_exports.union([external_exports.ipv4(), external_exports.ipv6()]),
24762
+ bodyBytes: external_exports.number().int().min(0).max(OOB_MAX_BODY_BYTES),
24763
+ bodySha256: OobSha256Schema,
24764
+ probeNonceHash: OobSha256Schema.nullable()
24765
+ }),
24766
+ external_exports.strictObject({
24767
+ action: external_exports.literal("complete"),
24768
+ captureId: external_exports.uuid(),
24769
+ admissionCapability: external_exports.uuid(),
24770
+ envelopeSha256: OobSha256Schema,
24771
+ envelopeBytes: external_exports.number().int().min(1).max(OOB_MAX_ENVELOPE_BYTES)
24772
+ }),
24773
+ external_exports.strictObject({
24774
+ action: external_exports.literal("fail"),
24775
+ captureId: external_exports.uuid(),
24776
+ admissionCapability: external_exports.uuid(),
24777
+ failureCode: external_exports.enum(["PUT_REJECTED", "PUT_AMBIGUOUS", "COMMIT_FAILED"])
24778
+ })
24779
+ ]);
24780
+ var OobAdmissionSchema = external_exports.strictObject({
24781
+ captureId: external_exports.uuid(),
24782
+ listenerId: external_exports.uuid(),
24783
+ pentestId: external_exports.uuid(),
24784
+ organizationId: external_exports.uuid(),
24785
+ admissionCapability: external_exports.uuid(),
24786
+ admittedAt: external_exports.iso.datetime({ offset: true }),
24787
+ objectKey: external_exports.string().regex(/^oob\/[0-9a-f-]+\/[0-9a-f-]+\/[0-9a-f-]+\/[0-9a-f-]+\.json$/),
24788
+ probeAttemptId: external_exports.uuid().nullable(),
24789
+ isSystemProbe: external_exports.boolean(),
24790
+ responseVersion: external_exports.number().int().positive(),
24791
+ response: OobResponseSchema
24792
+ });
24793
+ var OobAdmissionResultSchema = external_exports.union([
24794
+ OobAdmissionSchema,
24795
+ external_exports.strictObject({ error: external_exports.enum(["UNKNOWN", "CLOSED", "QUOTA", "UNKNOWN_PROBE"]) })
24796
+ ]);
24797
+ var OobAdmissionInspectionSchema = external_exports.strictObject({
24798
+ captureId: external_exports.uuid(),
24799
+ listenerId: external_exports.uuid(),
24800
+ pentestId: external_exports.uuid(),
24801
+ organizationId: external_exports.uuid(),
24802
+ objectKey: external_exports.string(),
24803
+ bodyBytes: external_exports.number().int().min(0).max(OOB_MAX_BODY_BYTES),
24804
+ bodySha256: OobSha256Schema,
24805
+ status: OobCaptureStatusSchema,
24806
+ admittedAt: external_exports.iso.datetime({ offset: true }),
24807
+ protocol: OobProtocolSchema,
24808
+ probeAttemptId: external_exports.uuid().nullable(),
24809
+ isSystemProbe: external_exports.boolean(),
24810
+ responseVersion: external_exports.number().int().positive()
24811
+ });
24812
+ var OobPersistenceResultSchema = external_exports.union([
24813
+ OobAdmissionResultSchema,
24814
+ external_exports.strictObject({ captureSeq: OobSequenceSchema }),
24815
+ external_exports.strictObject({ status: OobCaptureStatusSchema })
24816
+ ]);
24817
+ var OobEnvelopeSchema = external_exports.strictObject({
24818
+ version: external_exports.literal(1),
24819
+ captureId: external_exports.uuid(),
24820
+ listenerId: external_exports.uuid(),
24821
+ organizationId: external_exports.uuid(),
24822
+ pentestId: external_exports.uuid(),
24823
+ admittedAt: external_exports.iso.datetime({ offset: true }),
24824
+ protocol: OobProtocolSchema,
24825
+ sourceIp: external_exports.union([external_exports.ipv4(), external_exports.ipv6()]),
24826
+ probeAttemptId: external_exports.uuid().nullable(),
24827
+ isSystemProbe: external_exports.boolean(),
24828
+ method: external_exports.string().regex(/^[A-Z]{1,20}$/),
24829
+ rawTarget: external_exports.string().max(65536),
24830
+ rawHeaders: external_exports.array(OobHeaderSchema).max(512),
24831
+ headers: OobMultimapSchema,
24832
+ query: OobMultimapSchema,
24833
+ bodyBase64: base643.max(Math.ceil(OOB_MAX_BODY_BYTES / 3) * 4),
24834
+ bodyBytes: external_exports.number().int().min(0).max(OOB_MAX_BODY_BYTES),
24835
+ bodySha256: OobSha256Schema,
24836
+ responseVersion: external_exports.number().int().positive(),
24837
+ plannedResponse: OobResponseSchema,
24838
+ fidelity: external_exports.literal("collector-observed")
24839
+ }).superRefine((envelope, context) => {
24840
+ const bytes = envelope.bodyBase64.length * 3 / 4 - (envelope.bodyBase64.endsWith("==") ? 2 : envelope.bodyBase64.endsWith("=") ? 1 : 0);
24841
+ if (bytes !== envelope.bodyBytes)
24842
+ context.addIssue({
24843
+ code: "custom",
24844
+ path: ["bodyBytes"],
24845
+ message: "Captured body length differs from its encoded bytes."
24846
+ });
24847
+ if (envelope.isSystemProbe !== (envelope.probeAttemptId !== null))
24848
+ context.addIssue({
24849
+ code: "custom",
24850
+ path: ["isSystemProbe"],
24851
+ message: "Probe classification differs from the registered attempt identity."
24852
+ });
24853
+ });
24854
+ var OobSourceEvidenceSchema = external_exports.strictObject({
24855
+ captureId: external_exports.uuid(),
24856
+ listenerId: external_exports.uuid(),
24857
+ admittedAt: external_exports.iso.datetime({ offset: true }),
24858
+ envelopeSha256: OobSha256Schema,
24859
+ protocol: OobProtocolSchema,
24860
+ fidelity: external_exports.literal("collector-observed")
24861
+ });
24862
+
24425
24863
  // ../../packages/api-contracts/src/schemas/api/v1/pentest-validation.api.ts
24426
24864
  var PentestValidationParamsSchema = OrgIdParamsSchema.extend({
24427
24865
  pentestId: PentestIdOrDisplayIdSchema
@@ -24539,6 +24977,8 @@ var PentestToolRunResponseSchema = external_exports.object({
24539
24977
  });
24540
24978
  var PentestExploitArtifactMetadataResponseSchema = external_exports.object({
24541
24979
  artifactId: external_exports.uuid(),
24980
+ sourceOobCaptureId: external_exports.uuid().nullable().optional(),
24981
+ sourceOobCapture: OobSourceEvidenceSchema.nullable().optional(),
24542
24982
  organizationId: external_exports.uuid(),
24543
24983
  pentestId: external_exports.uuid(),
24544
24984
  attemptId: external_exports.uuid().nullable(),
@@ -24748,7 +25188,11 @@ var PentestFindingResponseSchema = external_exports.object({
24748
25188
  // operator schemas omit it (agents don't act on tickets). `.default(null)` keeps
24749
25189
  // the field input-optional (legacy fixtures / producers that predate it parse
24750
25190
  // clean) while the OUTPUT type stays `ExternalTicketSummary | null`.
24751
- externalTicket: ExternalTicketSummarySchema.nullable().default(null)
25191
+ externalTicket: ExternalTicketSummarySchema.nullable().default(null),
25192
+ // Staff-defined engagement tags on the finding, name-sorted. On every read
25193
+ // (list, detail, customer, operator) so the table filter and the chips render
25194
+ // from the row. `.default([])` for the same rolling-deploy reason as above.
25195
+ tags: external_exports.array(PentestFindingTagSchema).default([])
24752
25196
  });
24753
25197
  var PentestFindingListItemSchema = PentestFindingResponseSchema.omit({
24754
25198
  summary: true,
@@ -26033,13 +26477,13 @@ var StorageStateSchema = external_exports.object({
26033
26477
  } catch {
26034
26478
  return;
26035
26479
  }
26036
- s.cookies.forEach((c65, i2) => {
26037
- const d = c65.domain.replace(/^\./, "").toLowerCase();
26480
+ s.cookies.forEach((c69, i2) => {
26481
+ const d = c69.domain.replace(/^\./, "").toLowerCase();
26038
26482
  if (d !== host && !host.endsWith(`.${d}`)) {
26039
26483
  ctx.addIssue({
26040
26484
  code: "custom",
26041
26485
  path: ["cookies", i2, "domain"],
26042
- message: `cookie domain "${c65.domain}" is not the capture origin host "${host}" or a parent domain of it`
26486
+ message: `cookie domain "${c69.domain}" is not the capture origin host "${host}" or a parent domain of it`
26043
26487
  });
26044
26488
  }
26045
26489
  });
@@ -26242,20 +26686,72 @@ var c3 = initContract();
26242
26686
  var DesktopTargetInternalParamsSchema = external_exports.object({
26243
26687
  desktopTargetId: external_exports.uuid()
26244
26688
  });
26689
+ var DesktopTargetTransportSchema = external_exports.object({
26690
+ /** The session sshd's ed25519 host public key, OpenSSH one-line form. */
26691
+ sshHostPublicKey: external_exports.string().max(400).regex(/^ssh-ed25519 AAAA[0-9A-Za-z+/]+=*$/),
26692
+ /** The public address the host observed for itself; also the device's egress. */
26693
+ host: external_exports.union([external_exports.ipv4(), external_exports.ipv6()]),
26694
+ port: external_exports.number().int().min(1).max(65535)
26695
+ });
26245
26696
  var DesktopTargetRegisterRequestSchema = external_exports.object({
26246
26697
  runVersion: external_exports.number().int().min(0),
26247
26698
  agentVersion: external_exports.string().min(1).max(64),
26248
- osVersion: external_exports.string().min(1).max(200)
26699
+ osVersion: external_exports.string().min(1).max(200),
26700
+ transport: DesktopTargetTransportSchema.optional()
26249
26701
  });
26250
26702
  var DesktopTargetRegisterResponseSchema = external_exports.object({
26251
26703
  ok: external_exports.literal(true)
26252
26704
  });
26705
+ var DesktopEmulatorProfileValues = ["INSPECTION", "BASELINE"];
26706
+ var DesktopTargetHostHealthSchema = external_exports.object({
26707
+ emulators: external_exports.array(
26708
+ external_exports.object({
26709
+ serial: external_exports.string().min(1).max(32),
26710
+ profile: external_exports.enum(DesktopEmulatorProfileValues),
26711
+ booted: external_exports.boolean(),
26712
+ adbResponsive: external_exports.boolean()
26713
+ })
26714
+ ).max(4),
26715
+ captureCanaryOk: external_exports.boolean(),
26716
+ metadataDenied: external_exports.boolean()
26717
+ });
26253
26718
  var DesktopTargetHeartbeatRequestSchema = external_exports.object({
26254
- runVersion: external_exports.number().int().min(0)
26719
+ runVersion: external_exports.number().int().min(0),
26720
+ health: DesktopTargetHostHealthSchema.optional()
26721
+ });
26722
+ var DesktopTargetLeaseSchema = external_exports.object({
26723
+ desktopTargetId: external_exports.uuid(),
26724
+ runVersion: external_exports.number().int().min(0),
26725
+ /** The owning session, or null for a staff-provisioned target. */
26726
+ agentSessionId: external_exports.uuid().nullable(),
26727
+ agentSessionRunVersion: external_exports.number().int().min(0).nullable(),
26728
+ expiresAtMs: external_exports.number().int().positive()
26255
26729
  });
26256
26730
  var DesktopTargetHeartbeatResponseSchema = external_exports.object({
26257
- revoked: external_exports.boolean()
26731
+ revoked: external_exports.boolean(),
26732
+ /**
26733
+ * Null or absent means "admit nothing": the host closes session connections
26734
+ * and refuses new ones. A Windows rig ignores this field.
26735
+ */
26736
+ lease: DesktopTargetLeaseSchema.nullable().optional()
26737
+ });
26738
+ var DesktopBootFailureStageValues = [
26739
+ "SDK",
26740
+ "EMULATOR_BOOT",
26741
+ "ROOT_POLICY",
26742
+ "ABI",
26743
+ "METADATA_DENIAL",
26744
+ "CAPTURE_CANARY",
26745
+ "TRANSPORT",
26746
+ "DEADLINE"
26747
+ ];
26748
+ var DesktopTargetBootFailureRequestSchema = external_exports.object({
26749
+ runVersion: external_exports.number().int().min(0),
26750
+ stage: external_exports.enum(DesktopBootFailureStageValues),
26751
+ /** Shape only: exit code, expected-vs-observed class. Never guest output. */
26752
+ details: external_exports.string().max(500)
26258
26753
  });
26754
+ var DesktopTargetBootFailureResponseSchema = external_exports.object({ ok: external_exports.literal(true) });
26259
26755
  var DESKTOP_CLAIM_MAX_WAIT_MS = 25e3;
26260
26756
  var DesktopTargetClaimRequestSchema = external_exports.object({
26261
26757
  runVersion: external_exports.number().int().min(0),
@@ -26269,7 +26765,8 @@ var DesktopTargetStatusValues = [
26269
26765
  "TERMINATED",
26270
26766
  "FAILED"
26271
26767
  ];
26272
- var DesktopTargetPlatformValues = ["WINDOWS", "MACOS"];
26768
+ var DesktopTargetPlatformValues = ["WINDOWS", "MACOS", "ANDROID"];
26769
+ var SessionRequestableDesktopPlatformValues = ["WINDOWS", "MACOS"];
26273
26770
  var DesktopActionStatusValues = [
26274
26771
  "PENDING",
26275
26772
  "CLAIMED",
@@ -26362,6 +26859,21 @@ var desktopTargetInternalContract = c3.router({
26362
26859
  500: ErrorResponseSchema
26363
26860
  }
26364
26861
  },
26862
+ reportBootFailure: {
26863
+ method: "POST",
26864
+ path: "/internal/v1/desktop-targets/:desktopTargetId/boot-failure",
26865
+ pathParams: DesktopTargetInternalParamsSchema,
26866
+ body: DesktopTargetBootFailureRequestSchema,
26867
+ responses: {
26868
+ 200: DesktopTargetBootFailureResponseSchema,
26869
+ 400: ErrorResponseSchema,
26870
+ 401: ErrorResponseSchema,
26871
+ // Not PROVISIONING, or runVersion mismatch: a stale boot cannot fail a
26872
+ // later run's row.
26873
+ 409: ErrorResponseSchema,
26874
+ 500: ErrorResponseSchema
26875
+ }
26876
+ },
26365
26877
  claimAction: {
26366
26878
  method: "POST",
26367
26879
  path: "/internal/v1/desktop-targets/:desktopTargetId/actions/claim",
@@ -26564,11 +27076,6 @@ var RecordCandidateVulnResponseSchema = external_exports.object({
26564
27076
  inserted: external_exports.boolean()
26565
27077
  });
26566
27078
  var ProductContextStatement = external_exports.string().min(1).max(8e3);
26567
- var ProductEvidenceKindSchema = external_exports.enum(["docs", "source", "live"]);
26568
- var EvidenceRefSchema = external_exports.object({
26569
- ref: external_exports.string().min(1).max(512),
26570
- why: external_exports.string().min(1).max(300)
26571
- });
26572
27079
  var ProductFamilyEvidence = {
26573
27080
  evidence: ProductEvidenceKindSchema.optional(),
26574
27081
  refs: external_exports.array(EvidenceRefSchema).max(10).optional()
@@ -26606,6 +27113,95 @@ var RecordProductContextResponseSchema = external_exports.object({
26606
27113
  disputed: external_exports.number().int().nonnegative(),
26607
27114
  rejected: external_exports.number().int().nonnegative()
26608
27115
  });
27116
+ var SURFACE_FEATURE_SLUG_MAX_CHARS_WIRE = 64;
27117
+ var SURFACE_FEATURES_PER_CALL_MAX = 40;
27118
+ var SURFACE_RETIREMENTS_PER_CALL_MAX = 20;
27119
+ var SurfaceFeatureSlug = external_exports.string().min(1).max(SURFACE_FEATURE_SLUG_MAX_CHARS_WIRE);
27120
+ var RecordSurfaceFeaturesRequestSchema = external_exports.object({
27121
+ runVersion: external_exports.number().int().nonnegative(),
27122
+ features: external_exports.array(
27123
+ external_exports.object({
27124
+ slug: SurfaceFeatureSlug,
27125
+ name: external_exports.string().min(1).max(120),
27126
+ summary: external_exports.string().min(1).max(600),
27127
+ roles: external_exports.array(SurfaceRoleSchema).max(SURFACE_FEATURE_ROLES_MAX).optional(),
27128
+ endpoints: external_exports.array(SurfaceEndpointSchema).max(SURFACE_FEATURE_ENDPOINTS_MAX).optional(),
27129
+ evidence: ProductEvidenceKindSchema,
27130
+ refs: external_exports.array(EvidenceRefSchema).min(1).max(10)
27131
+ })
27132
+ ).max(SURFACE_FEATURES_PER_CALL_MAX),
27133
+ retired: external_exports.array(
27134
+ external_exports.object({
27135
+ slug: SurfaceFeatureSlug,
27136
+ reason: external_exports.string().min(1).max(SURFACE_SOURCE_NOTE_MAX_CHARS),
27137
+ /** The corpus of the refs, exactly as a feature. */
27138
+ evidence: ProductEvidenceKindSchema,
27139
+ refs: external_exports.array(EvidenceRefSchema).min(1).max(10)
27140
+ })
27141
+ ).max(SURFACE_RETIREMENTS_PER_CALL_MAX)
27142
+ });
27143
+ var SurfaceFeatureWriteOutcomeSchema = external_exports.enum([
27144
+ "created",
27145
+ "updated",
27146
+ "restored",
27147
+ "retired",
27148
+ "rejected"
27149
+ ]);
27150
+ var SurfaceFeatureRejectReasonSchema = external_exports.enum([
27151
+ "NO_VALID_REF",
27152
+ "SOURCE_EVIDENCE_WITHOUT_REPOSITORY",
27153
+ "LIVE_EVIDENCE_WITHOUT_TARGET",
27154
+ "UNKNOWN_SLUG",
27155
+ "INVALID_SLUG",
27156
+ "NOT_RETIRABLE"
27157
+ ]);
27158
+ var RecordSurfaceFeaturesResponseSchema = external_exports.object({
27159
+ results: external_exports.array(
27160
+ external_exports.object({
27161
+ /** As the api stored it: normalized, or the survivor's slug when a merged row redirected. */
27162
+ slug: external_exports.string(),
27163
+ outcome: SurfaceFeatureWriteOutcomeSchema,
27164
+ reason: SurfaceFeatureRejectReasonSchema.optional()
27165
+ })
27166
+ ),
27167
+ created: external_exports.number().int().nonnegative(),
27168
+ updated: external_exports.number().int().nonnegative(),
27169
+ restored: external_exports.number().int().nonnegative(),
27170
+ retired: external_exports.number().int().nonnegative(),
27171
+ rejected: external_exports.number().int().nonnegative()
27172
+ });
27173
+ var COVERAGE_CLASSES_PER_CALL_MAX = 40;
27174
+ var COVERAGE_CLASS_ID_MAX_CHARS = 64;
27175
+ var COVERAGE_CLASS_NAME_MAX_CHARS = 200;
27176
+ var COVERAGE_NOTE_MAX_CHARS = 2e3;
27177
+ var COVERAGE_MAPPINGS_MAX = 10;
27178
+ var COVERAGE_MAPPING_MAX_CHARS = 40;
27179
+ var COVERAGE_WIRE_STATUSES = [
27180
+ "covered",
27181
+ "partial",
27182
+ "not_covered",
27183
+ "not_applicable"
27184
+ ];
27185
+ var COVERAGE_WIRE_RELEVANCES = ["critical", "high", "medium", "not_applicable"];
27186
+ var CoverageClassEntrySchema = external_exports.object({
27187
+ id: external_exports.string().min(1).max(COVERAGE_CLASS_ID_MAX_CHARS),
27188
+ name: external_exports.string().min(1).max(COVERAGE_CLASS_NAME_MAX_CHARS),
27189
+ relevance: external_exports.enum(COVERAGE_WIRE_RELEVANCES),
27190
+ status: external_exports.enum(COVERAGE_WIRE_STATUSES),
27191
+ notes: external_exports.string().max(COVERAGE_NOTE_MAX_CHARS),
27192
+ mappings: external_exports.array(external_exports.string().min(1).max(COVERAGE_MAPPING_MAX_CHARS)).max(COVERAGE_MAPPINGS_MAX).optional()
27193
+ });
27194
+ var RecordCoverageRequestSchema = external_exports.object({
27195
+ runVersion: external_exports.number().int().nonnegative(),
27196
+ /** Per-run counter the host assigns in call order, starting at 1. */
27197
+ callSeq: external_exports.number().int().positive(),
27198
+ classes: external_exports.array(CoverageClassEntrySchema).min(1).max(COVERAGE_CLASSES_PER_CALL_MAX)
27199
+ });
27200
+ var RecordCoverageResponseSchema = external_exports.object({
27201
+ /** `stale`: a later call from this session already landed, so nothing changed. */
27202
+ outcome: external_exports.enum(["replaced", "stale"]),
27203
+ written: external_exports.number().int().nonnegative()
27204
+ });
26609
27205
  var ThreatModelStatement = external_exports.string().min(1).max(2e3);
26610
27206
  var RepoScopedThreatItem = external_exports.object({
26611
27207
  repoAlias: external_exports.string().min(1).max(200),
@@ -26655,6 +27251,7 @@ var ValidationResultProseSchema = external_exports.object({
26655
27251
  });
26656
27252
  var RecordValidationEvidenceItemSchema = external_exports.object({
26657
27253
  key: external_exports.string().min(1).max(1024),
27254
+ sourceOobCaptureId: external_exports.uuid().optional(),
26658
27255
  kind: PentestExploitArtifactKind.optional(),
26659
27256
  caption: external_exports.string().min(1).max(500).optional(),
26660
27257
  section: ValidationEvidenceSection.optional(),
@@ -27477,6 +28074,12 @@ var OperatorPublishFindingRequestSchema = external_exports.object({
27477
28074
  pentestFindingId: external_exports.uuid(),
27478
28075
  expectedUpdatedAt: external_exports.coerce.date()
27479
28076
  });
28077
+ var OperatorSetFindingTagsRequestSchema = external_exports.object({
28078
+ runVersion: operatorRunVersion,
28079
+ reason: operatorReason,
28080
+ pentestFindingId: external_exports.uuid(),
28081
+ tags: external_exports.array(external_exports.string().trim().min(1).max(PENTEST_TAG_NAME_MAX_CHARS)).max(PENTEST_TAGS_PER_PENTEST_MAX)
28082
+ });
27480
28083
  var OperatorApplyFindingCvssRequestSchema = ApplyFindingCvssRequestSchema.omit({
27481
28084
  rationale: true
27482
28085
  // the operator `reason` IS the cvss audit rationale
@@ -27508,6 +28111,7 @@ var OperatorAttachFindingEvidenceRequestSchema = external_exports.object({
27508
28111
  reason: operatorReason,
27509
28112
  pentestFindingId: external_exports.uuid(),
27510
28113
  key: external_exports.string().min(1).max(1024),
28114
+ sourceOobCaptureId: external_exports.uuid().optional(),
27511
28115
  kind: PentestExploitArtifactKind.optional(),
27512
28116
  caption: external_exports.string().min(1).max(500).optional(),
27513
28117
  section: ValidationEvidenceSection.optional(),
@@ -27747,8 +28351,9 @@ var ReportUpdateScopeRequestSchema = external_exports.object({
27747
28351
  var RequestDesktopTargetRequestSchema = external_exports.object({
27748
28352
  runVersion: external_exports.number().int().min(0),
27749
28353
  /** A MACOS request is also gated on the session's pinned toolset (the api's
27750
- * `DESKTOP_MACOS_CAPABLE_TOOLSETS`); the schema alone does not authorize it. */
27751
- platform: external_exports.enum(DesktopTargetPlatformValues)
28354
+ * `DESKTOP_MACOS_CAPABLE_TOOLSETS`); the schema alone does not authorize it.
28355
+ * ANDROID is not offered here until the session-side transport lands. */
28356
+ platform: external_exports.enum(SessionRequestableDesktopPlatformValues)
27752
28357
  });
27753
28358
  var DesktopCredentialRefSchema = external_exports.object({
27754
28359
  credentialId: external_exports.uuid(),
@@ -27953,6 +28558,38 @@ var agentSessionInternalContract = c4.router({
27953
28558
  500: ErrorResponseSchema
27954
28559
  }
27955
28560
  },
28561
+ recordSurfaceFeatures: {
28562
+ method: "POST",
28563
+ path: "/internal/v1/agent-sessions/:agentSessionId/surface-features",
28564
+ pathParams: AgentSessionInternalParamsSchema,
28565
+ body: RecordSurfaceFeaturesRequestSchema,
28566
+ responses: {
28567
+ 201: RecordSurfaceFeaturesResponseSchema,
28568
+ 400: ErrorResponseSchema,
28569
+ 401: ErrorResponseSchema,
28570
+ // 403 = the run token's session is not a PRODUCT_RECON session (type backstop).
28571
+ 403: ErrorResponseSchema,
28572
+ // 409 = run stale/revoked, or pentest deleted (app unresolvable).
28573
+ 409: ErrorResponseSchema,
28574
+ 500: ErrorResponseSchema
28575
+ }
28576
+ },
28577
+ recordCoverage: {
28578
+ method: "POST",
28579
+ path: "/internal/v1/agent-sessions/:agentSessionId/coverage",
28580
+ pathParams: AgentSessionInternalParamsSchema,
28581
+ body: RecordCoverageRequestSchema,
28582
+ responses: {
28583
+ 201: RecordCoverageResponseSchema,
28584
+ 400: ErrorResponseSchema,
28585
+ 401: ErrorResponseSchema,
28586
+ // 403 = the run token's session is not a hunting session (CODE_REVIEW, RECON, ASSESSMENT).
28587
+ 403: ErrorResponseSchema,
28588
+ // 409 = run stale/revoked (RUN_REVOKED), or the pentest was deleted (COVERAGE_PENTEST_GONE).
28589
+ 409: ErrorResponseSchema,
28590
+ 500: ErrorResponseSchema
28591
+ }
28592
+ },
27956
28593
  recordThreatModel: {
27957
28594
  method: "POST",
27958
28595
  path: "/internal/v1/agent-sessions/:agentSessionId/threat-model",
@@ -28572,6 +29209,21 @@ var agentSessionInternalContract = c4.router({
28572
29209
  500: ErrorResponseSchema
28573
29210
  }
28574
29211
  },
29212
+ setFindingTags: {
29213
+ method: "POST",
29214
+ path: "/internal/v1/agent-sessions/:agentSessionId/operator/findings/tags",
29215
+ pathParams: AgentSessionInternalParamsSchema,
29216
+ body: OperatorSetFindingTagsRequestSchema,
29217
+ responses: {
29218
+ 200: OperatorFindingReadSchema,
29219
+ // PENTEST_TAG_UNKNOWN_NAME: a name is not one of the engagement's tags (details.knownTags).
29220
+ 400: ErrorResponseSchema,
29221
+ 401: ErrorResponseSchema,
29222
+ 403: ErrorResponseSchema,
29223
+ 404: ErrorResponseSchema,
29224
+ 500: ErrorResponseSchema
29225
+ }
29226
+ },
28575
29227
  applyFindingCvss: {
28576
29228
  method: "POST",
28577
29229
  path: "/internal/v1/agent-sessions/:agentSessionId/operator/findings/cvss",
@@ -29352,8 +30004,100 @@ var applicationContract = c7.router({
29352
30004
  }
29353
30005
  });
29354
30006
 
29355
- // ../../packages/api-contracts/src/contracts/v1/bitbucket.ts
30007
+ // ../../packages/api-contracts/src/contracts/v1/application-surface-map.ts
29356
30008
  var c8 = initContract();
30009
+ var applicationSurfaceMapContract = c8.router({
30010
+ listSurfaceMap: {
30011
+ method: "GET",
30012
+ path: "/organizations/:organizationId/pentests/:pentestId/surface-map",
30013
+ pathParams: SurfaceMapParamsSchema,
30014
+ responses: {
30015
+ 200: SurfaceMapResponseSchema,
30016
+ 401: ErrorResponseSchema,
30017
+ 403: ErrorResponseSchema,
30018
+ 404: ErrorResponseSchema,
30019
+ 500: ErrorResponseSchema
30020
+ }
30021
+ },
30022
+ addSurfaceFeature: {
30023
+ method: "POST",
30024
+ path: "/organizations/:organizationId/pentests/:pentestId/surface-map/features",
30025
+ pathParams: SurfaceMapParamsSchema,
30026
+ body: AddSurfaceFeatureRequestSchema,
30027
+ responses: {
30028
+ 201: SurfaceFeatureSchema,
30029
+ 400: ErrorResponseSchema,
30030
+ 401: ErrorResponseSchema,
30031
+ 403: ErrorResponseSchema,
30032
+ 404: ErrorResponseSchema,
30033
+ // errorCode SURFACE_FEATURE_SLUG_EXISTS with `details` per SurfaceFeatureConflictDetailsSchema.
30034
+ 409: ErrorResponseSchema,
30035
+ 500: ErrorResponseSchema
30036
+ }
30037
+ },
30038
+ renameSurfaceFeature: {
30039
+ method: "PATCH",
30040
+ path: "/organizations/:organizationId/pentests/:pentestId/surface-map/features/:featureId",
30041
+ pathParams: SurfaceFeatureIdParamsSchema,
30042
+ body: RenameSurfaceFeatureRequestSchema,
30043
+ responses: {
30044
+ 200: SurfaceFeatureSchema,
30045
+ 400: ErrorResponseSchema,
30046
+ 401: ErrorResponseSchema,
30047
+ 403: ErrorResponseSchema,
30048
+ 404: ErrorResponseSchema,
30049
+ 500: ErrorResponseSchema
30050
+ }
30051
+ },
30052
+ retireSurfaceFeature: {
30053
+ method: "POST",
30054
+ path: "/organizations/:organizationId/pentests/:pentestId/surface-map/features/:featureId/retire",
30055
+ pathParams: SurfaceFeatureIdParamsSchema,
30056
+ body: RetireSurfaceFeatureRequestSchema,
30057
+ responses: {
30058
+ 200: SurfaceFeatureSchema,
30059
+ 400: ErrorResponseSchema,
30060
+ 401: ErrorResponseSchema,
30061
+ 403: ErrorResponseSchema,
30062
+ 404: ErrorResponseSchema,
30063
+ 409: ErrorResponseSchema,
30064
+ 500: ErrorResponseSchema
30065
+ }
30066
+ },
30067
+ restoreSurfaceFeature: {
30068
+ method: "POST",
30069
+ path: "/organizations/:organizationId/pentests/:pentestId/surface-map/features/:featureId/restore",
30070
+ pathParams: SurfaceFeatureIdParamsSchema,
30071
+ body: c8.noBody(),
30072
+ responses: {
30073
+ 200: SurfaceFeatureSchema,
30074
+ 401: ErrorResponseSchema,
30075
+ 403: ErrorResponseSchema,
30076
+ 404: ErrorResponseSchema,
30077
+ 409: ErrorResponseSchema,
30078
+ 500: ErrorResponseSchema
30079
+ }
30080
+ },
30081
+ mergeSurfaceFeature: {
30082
+ method: "POST",
30083
+ path: "/organizations/:organizationId/pentests/:pentestId/surface-map/features/:featureId/merge",
30084
+ pathParams: SurfaceFeatureIdParamsSchema,
30085
+ body: MergeSurfaceFeatureRequestSchema,
30086
+ responses: {
30087
+ // The survivor.
30088
+ 200: SurfaceFeatureSchema,
30089
+ 400: ErrorResponseSchema,
30090
+ 401: ErrorResponseSchema,
30091
+ 403: ErrorResponseSchema,
30092
+ 404: ErrorResponseSchema,
30093
+ 409: ErrorResponseSchema,
30094
+ 500: ErrorResponseSchema
30095
+ }
30096
+ }
30097
+ });
30098
+
30099
+ // ../../packages/api-contracts/src/contracts/v1/bitbucket.ts
30100
+ var c9 = initContract();
29357
30101
  var BitbucketInstallationParamsSchema = external_exports.object({
29358
30102
  organizationId: external_exports.uuid()
29359
30103
  });
@@ -29388,7 +30132,7 @@ var SyncBitbucketInstallationResponseSchema = external_exports.object({
29388
30132
  /** Previously-connected repos absent from the workspace listing, now disconnected. */
29389
30133
  disconnectedRepoCount: external_exports.number().int()
29390
30134
  });
29391
- var bitbucketContract = c8.router({
30135
+ var bitbucketContract = c9.router({
29392
30136
  claimInstallation: {
29393
30137
  method: "POST",
29394
30138
  path: "/organizations/:organizationId/bitbucket/installations/claim",
@@ -29493,8 +30237,8 @@ var ListChatSessionsResponseSchema = external_exports.object({
29493
30237
  });
29494
30238
 
29495
30239
  // ../../packages/api-contracts/src/contracts/v1/chat-session.ts
29496
- var c9 = initContract();
29497
- var chatSessionContract = c9.router({
30240
+ var c10 = initContract();
30241
+ var chatSessionContract = c10.router({
29498
30242
  createSession: {
29499
30243
  method: "POST",
29500
30244
  path: "/organizations/:organizationId/chat/sessions",
@@ -30197,8 +30941,8 @@ var ReverifyConvexDeploymentResponseSchema = external_exports.object({
30197
30941
  }).strict();
30198
30942
 
30199
30943
  // ../../packages/api-contracts/src/contracts/v1/cloud-integration.ts
30200
- var c10 = initContract();
30201
- var cloudIntegrationContract = c10.router({
30944
+ var c11 = initContract();
30945
+ var cloudIntegrationContract = c11.router({
30202
30946
  createAwsIntegration: {
30203
30947
  method: "POST",
30204
30948
  path: "/organizations/:organizationId/cloud-integrations/aws",
@@ -30484,7 +31228,7 @@ var cloudIntegrationContract = c10.router({
30484
31228
  method: "POST",
30485
31229
  path: "/organizations/:organizationId/cloud-integrations/:cloudIntegrationId/vercel/installations/:vercelInstallationId/reverify",
30486
31230
  pathParams: VercelInstallationIdParamsSchema,
30487
- body: c10.noBody(),
31231
+ body: c11.noBody(),
30488
31232
  responses: {
30489
31233
  200: ReverifyVercelInstallationResponseSchema,
30490
31234
  400: ErrorResponseSchema,
@@ -30581,7 +31325,7 @@ var cloudIntegrationContract = c10.router({
30581
31325
  method: "POST",
30582
31326
  path: "/organizations/:organizationId/cloud-integrations/:cloudIntegrationId/convex/deployments/:convexLinkedDeploymentId/reverify",
30583
31327
  pathParams: ConvexDeploymentIdParamsSchema,
30584
- body: c10.noBody(),
31328
+ body: c11.noBody(),
30585
31329
  responses: {
30586
31330
  200: ReverifyConvexDeploymentResponseSchema,
30587
31331
  400: ErrorResponseSchema,
@@ -30705,8 +31449,8 @@ var StaffCodeSizeRemeasureResponseSchema = external_exports.object({
30705
31449
  });
30706
31450
 
30707
31451
  // ../../packages/api-contracts/src/contracts/v1/code-size.ts
30708
- var c11 = initContract();
30709
- var codeSizeContract = c11.router({
31452
+ var c12 = initContract();
31453
+ var codeSizeContract = c12.router({
30710
31454
  getOrganizationCodeSize: {
30711
31455
  method: "GET",
30712
31456
  path: "/organizations/:organizationId/code-size",
@@ -30724,7 +31468,7 @@ var codeSizeContract = c11.router({
30724
31468
  method: "POST",
30725
31469
  path: "/organizations/:organizationId/code-size/recalculate",
30726
31470
  pathParams: OrgIdParamsSchema,
30727
- body: c11.noBody(),
31471
+ body: c12.noBody(),
30728
31472
  responses: {
30729
31473
  200: CodeSizeRecalculateResponseSchema,
30730
31474
  401: ErrorResponseSchema,
@@ -30772,7 +31516,7 @@ var codeSizeContract = c11.router({
30772
31516
  });
30773
31517
 
30774
31518
  // ../../packages/api-contracts/src/contracts/v1/code-upload.ts
30775
- var c12 = initContract();
31519
+ var c13 = initContract();
30776
31520
  var commonErrors = {
30777
31521
  400: ErrorResponseSchema,
30778
31522
  401: ErrorResponseSchema,
@@ -30782,7 +31526,7 @@ var commonErrors = {
30782
31526
  500: ErrorResponseSchema,
30783
31527
  503: ErrorResponseSchema
30784
31528
  };
30785
- var codeUploadContract = c12.router({
31529
+ var codeUploadContract = c13.router({
30786
31530
  initializeCodeUpload: {
30787
31531
  method: "POST",
30788
31532
  path: "/organizations/:organizationId/code-uploads",
@@ -31072,8 +31816,8 @@ var RevealCredentialSecretResponseSchema = external_exports.discriminatedUnion("
31072
31816
  ]);
31073
31817
 
31074
31818
  // ../../packages/api-contracts/src/contracts/v1/credential.ts
31075
- var c13 = initContract();
31076
- var credentialContract = c13.router({
31819
+ var c14 = initContract();
31820
+ var credentialContract = c14.router({
31077
31821
  listCredentials: {
31078
31822
  method: "GET",
31079
31823
  path: "/organizations/:organizationId/environments/:environmentId/credentials",
@@ -31165,7 +31909,7 @@ var credentialContract = c13.router({
31165
31909
  method: "POST",
31166
31910
  path: "/organizations/:organizationId/environments/:environmentId/credentials/:credentialId/reveal",
31167
31911
  pathParams: CredentialIdParamsSchema,
31168
- body: c13.noBody(),
31912
+ body: c14.noBody(),
31169
31913
  responses: {
31170
31914
  200: RevealCredentialSecretResponseSchema,
31171
31915
  401: ErrorResponseSchema,
@@ -31218,7 +31962,7 @@ var credentialContract = c13.router({
31218
31962
  method: "POST",
31219
31963
  path: "/organizations/:organizationId/environments/:environmentId/credentials/:credentialId/mfa/code",
31220
31964
  pathParams: CredentialIdParamsSchema,
31221
- body: c13.noBody(),
31965
+ body: c14.noBody(),
31222
31966
  responses: {
31223
31967
  200: CredentialMfaCodeResponseSchema,
31224
31968
  401: ErrorResponseSchema,
@@ -31480,8 +32224,8 @@ var DependencySummaryResponseSchema = external_exports.object({
31480
32224
  });
31481
32225
 
31482
32226
  // ../../packages/api-contracts/src/contracts/v1/dependency.ts
31483
- var c14 = initContract();
31484
- var dependencyContract = c14.router({
32227
+ var c15 = initContract();
32228
+ var dependencyContract = c15.router({
31485
32229
  /** Cross-repo dependency search. Two-phase: pg_trgm on Package, then join repos. */
31486
32230
  searchDependencies: {
31487
32231
  method: "POST",
@@ -31626,8 +32370,8 @@ var DockerScoutIntegrationResponseSchema = external_exports.object({
31626
32370
  });
31627
32371
 
31628
32372
  // ../../packages/api-contracts/src/contracts/v1/docker-scout-integration.ts
31629
- var c15 = initContract();
31630
- var dockerScoutIntegrationContract = c15.router({
32373
+ var c16 = initContract();
32374
+ var dockerScoutIntegrationContract = c16.router({
31631
32375
  createDockerScoutIntegration: {
31632
32376
  method: "POST",
31633
32377
  path: "/organizations/:organizationId/docker-scout-integration",
@@ -31827,12 +32571,12 @@ var EngagementResponseSchema = external_exports.object({
31827
32571
  });
31828
32572
 
31829
32573
  // ../../packages/api-contracts/src/contracts/v1/engagement.ts
31830
- var c16 = initContract();
32574
+ var c17 = initContract();
31831
32575
  var RecordDashboardSessionRequest = external_exports.object({
31832
32576
  sessionId: external_exports.string().min(1).max(100)
31833
32577
  });
31834
32578
  var RecordDashboardSessionResponse = external_exports.object({});
31835
- var engagementContract = c16.router({
32579
+ var engagementContract = c17.router({
31836
32580
  recordDashboardSession: {
31837
32581
  method: "POST",
31838
32582
  // `pathPrefix: '/v1'` is applied at the router level (see
@@ -31906,8 +32650,8 @@ var UpdateEnvironmentRequestSchema = external_exports.object({
31906
32650
  }).strict();
31907
32651
 
31908
32652
  // ../../packages/api-contracts/src/contracts/v1/environment.ts
31909
- var c17 = initContract();
31910
- var environmentContract = c17.router({
32653
+ var c18 = initContract();
32654
+ var environmentContract = c18.router({
31911
32655
  listEnvironments: {
31912
32656
  method: "GET",
31913
32657
  path: "/organizations/:organizationId/applications/:applicationId/environments",
@@ -32161,8 +32905,8 @@ var GitHubRepoSchema = external_exports.object({
32161
32905
  var ListGitHubInstallationReposResponseSchema = external_exports.array(GitHubRepoSchema);
32162
32906
 
32163
32907
  // ../../packages/api-contracts/src/contracts/v1/github.ts
32164
- var c18 = initContract();
32165
- var githubContract = c18.router({
32908
+ var c19 = initContract();
32909
+ var githubContract = c19.router({
32166
32910
  // Tier chooser data: which app tiers this env can connect + the org's
32167
32911
  // entitlement default. Pure read (auth context + server config).
32168
32912
  getConnectOptions: {
@@ -32261,7 +33005,7 @@ var githubContract = c18.router({
32261
33005
  method: "POST",
32262
33006
  path: "/organizations/:organizationId/github/install-requests/:requestId/cancel",
32263
33007
  pathParams: GitHubInstallRequestParamsSchema,
32264
- body: c18.type(),
33008
+ body: c19.type(),
32265
33009
  responses: {
32266
33010
  200: GitHubInstallRequestSchema,
32267
33011
  401: ErrorResponseSchema,
@@ -32272,7 +33016,7 @@ var githubContract = c18.router({
32272
33016
  }
32273
33017
  }
32274
33018
  });
32275
- var staffGithubContract = c18.router({
33019
+ var staffGithubContract = c19.router({
32276
33020
  listStaffInstallations: {
32277
33021
  method: "GET",
32278
33022
  path: "/staff/github/installations",
@@ -32287,8 +33031,8 @@ var staffGithubContract = c18.router({
32287
33031
  });
32288
33032
 
32289
33033
  // ../../packages/api-contracts/src/contracts/v1/inbox.ts
32290
- var c19 = initContract();
32291
- var inboxContract = c19.router({
33034
+ var c20 = initContract();
33035
+ var inboxContract = c20.router({
32292
33036
  listInboxes: {
32293
33037
  method: "GET",
32294
33038
  path: "/organizations/:organizationId/inboxes",
@@ -32441,8 +33185,8 @@ var AcceptInviteLinkRejectedResponseSchema = ErrorResponseSchema.extend({
32441
33185
  });
32442
33186
 
32443
33187
  // ../../packages/api-contracts/src/contracts/v1/invite-link.ts
32444
- var c20 = initContract();
32445
- var inviteLinkContract = c20.router({
33188
+ var c21 = initContract();
33189
+ var inviteLinkContract = c21.router({
32446
33190
  createInviteLink: {
32447
33191
  method: "POST",
32448
33192
  path: "/organizations/:organizationId/invite-links",
@@ -32482,7 +33226,7 @@ var inviteLinkContract = c20.router({
32482
33226
  }
32483
33227
  }
32484
33228
  });
32485
- var inviteLinkPublicContract = c20.router(
33229
+ var inviteLinkPublicContract = c21.router(
32486
33230
  {
32487
33231
  previewInviteLink: {
32488
33232
  method: "GET",
@@ -32499,7 +33243,7 @@ var inviteLinkPublicContract = c20.router(
32499
33243
  method: "POST",
32500
33244
  path: "/invite-links/:token/accept",
32501
33245
  pathParams: InviteLinkTokenParamsSchema,
32502
- body: c20.noBody(),
33246
+ body: c21.noBody(),
32503
33247
  responses: {
32504
33248
  200: AcceptInviteLinkResponseSchema,
32505
33249
  400: ErrorResponseSchema,
@@ -32547,8 +33291,8 @@ var UpdateKnowledgeBaseResponseSchema = external_exports.object({
32547
33291
  });
32548
33292
 
32549
33293
  // ../../packages/api-contracts/src/contracts/v1/knowledge-base.ts
32550
- var c21 = initContract();
32551
- var knowledgeBaseContract = c21.router({
33294
+ var c22 = initContract();
33295
+ var knowledgeBaseContract = c22.router({
32552
33296
  getKnowledgeBase: {
32553
33297
  method: "GET",
32554
33298
  path: "/organizations/:organizationId/knowledge-base",
@@ -32769,8 +33513,8 @@ var UpdateRepoDocumentContentResponseSchema = external_exports.object({
32769
33513
  });
32770
33514
 
32771
33515
  // ../../packages/api-contracts/src/contracts/v1/knowledge-document.ts
32772
- var c22 = initContract();
32773
- var knowledgeDocumentContract = c22.router({
33516
+ var c23 = initContract();
33517
+ var knowledgeDocumentContract = c23.router({
32774
33518
  createDocument: {
32775
33519
  method: "POST",
32776
33520
  path: "/organizations/:organizationId/knowledge-documents",
@@ -33096,8 +33840,8 @@ var LinearMetadataResponseSchema = external_exports.object({
33096
33840
  });
33097
33841
 
33098
33842
  // ../../packages/api-contracts/src/contracts/v1/linear-integration.ts
33099
- var c23 = initContract();
33100
- var linearIntegrationContract = c23.router({
33843
+ var c24 = initContract();
33844
+ var linearIntegrationContract = c24.router({
33101
33845
  getLinearIntegration: {
33102
33846
  method: "GET",
33103
33847
  path: "/organizations/:organizationId/integrations/linear",
@@ -33115,7 +33859,7 @@ var linearIntegrationContract = c23.router({
33115
33859
  method: "POST",
33116
33860
  path: "/organizations/:organizationId/integrations/linear/connect",
33117
33861
  pathParams: OrgIdParamsSchema,
33118
- body: c23.noBody(),
33862
+ body: c24.noBody(),
33119
33863
  responses: {
33120
33864
  200: LinearConnectResponseSchema,
33121
33865
  401: ErrorResponseSchema,
@@ -33130,7 +33874,7 @@ var linearIntegrationContract = c23.router({
33130
33874
  method: "POST",
33131
33875
  path: "/organizations/:organizationId/integrations/linear/disconnect",
33132
33876
  pathParams: OrgIdParamsSchema,
33133
- body: c23.noBody(),
33877
+ body: c24.noBody(),
33134
33878
  responses: {
33135
33879
  200: LinearIntegrationResponseSchema,
33136
33880
  401: ErrorResponseSchema,
@@ -33192,8 +33936,8 @@ var linearIntegrationContract = c23.router({
33192
33936
  });
33193
33937
 
33194
33938
  // ../../packages/api-contracts/src/contracts/v1/linear-tickets.ts
33195
- var c24 = initContract();
33196
- var linearTicketContract = c24.router({
33939
+ var c25 = initContract();
33940
+ var linearTicketContract = c25.router({
33197
33941
  /**
33198
33942
  * Push one or more pentest findings to Linear as tickets. Customer-side
33199
33943
  * (VIEW_RESULTS + PENTEST capability); non-admins create into the org's
@@ -33297,8 +34041,8 @@ var LlmProviderKeyResponseSchema = external_exports.object({
33297
34041
  var ListLlmProviderKeysResponseSchema = external_exports.array(LlmProviderKeyResponseSchema);
33298
34042
 
33299
34043
  // ../../packages/api-contracts/src/contracts/v1/llm-provider-key.ts
33300
- var c25 = initContract();
33301
- var llmProviderKeyContract = c25.router({
34044
+ var c26 = initContract();
34045
+ var llmProviderKeyContract = c26.router({
33302
34046
  createLlmProviderKey: {
33303
34047
  method: "POST",
33304
34048
  path: "/organizations/:organizationId/llm-provider-keys",
@@ -33366,8 +34110,8 @@ var llmProviderKeyContract = c25.router({
33366
34110
  });
33367
34111
 
33368
34112
  // ../../packages/api-contracts/src/contracts/v1/member.ts
33369
- var c26 = initContract();
33370
- var memberContract = c26.router({
34113
+ var c27 = initContract();
34114
+ var memberContract = c27.router({
33371
34115
  createInvitation: {
33372
34116
  method: "POST",
33373
34117
  path: "/organizations/:organizationId/members/invitations",
@@ -33386,6 +34130,299 @@ var memberContract = c26.router({
33386
34130
  }
33387
34131
  });
33388
34132
 
34133
+ // ../../packages/api-contracts/src/schemas/api/v1/oob-listener.api.ts
34134
+ var isoDate = external_exports.iso.datetime({ offset: true });
34135
+ var OobListenerParamsSchema = external_exports.object({ organizationId: external_exports.uuid(), pentestId: external_exports.uuid() });
34136
+ var OobListenerIdParamsSchema = OobListenerParamsSchema.extend({ listenerId: external_exports.uuid() });
34137
+ var OobCaptureIdParamsSchema = OobListenerIdParamsSchema.extend({ captureId: external_exports.uuid() });
34138
+ var OobCountsSchema = external_exports.strictObject({
34139
+ normal: external_exports.number().int().nonnegative(),
34140
+ probes: external_exports.number().int().nonnegative(),
34141
+ pending: external_exports.number().int().nonnegative(),
34142
+ failed: external_exports.number().int().nonnegative()
34143
+ });
34144
+ var OobProbeAttemptSchema = external_exports.strictObject({
34145
+ probeAttemptId: external_exports.uuid(),
34146
+ protocol: OobProtocolSchema,
34147
+ responseVersion: external_exports.number().int().positive(),
34148
+ issuedAt: isoDate,
34149
+ expiresAt: isoDate,
34150
+ result: OobProbeResultSchema,
34151
+ verifiedCaptureId: external_exports.uuid().nullable(),
34152
+ verifiedAt: isoDate.nullable(),
34153
+ failureStage: external_exports.string().nullable()
34154
+ });
34155
+ var OobListenerSchema = external_exports.strictObject({
34156
+ listenerId: external_exports.uuid(),
34157
+ organizationId: external_exports.uuid(),
34158
+ pentestId: external_exports.uuid(),
34159
+ label: external_exports.string(),
34160
+ purpose: external_exports.string(),
34161
+ httpUrl: external_exports.url(),
34162
+ httpsUrl: external_exports.url(),
34163
+ status: OobListenerStatusSchema,
34164
+ health: OobListenerHealthSchema,
34165
+ responseVersion: external_exports.number().int().positive(),
34166
+ response: OobResponseSchema,
34167
+ creatorAgentSessionId: external_exports.uuid().nullable(),
34168
+ createdByStaffLabel: external_exports.string().nullable(),
34169
+ creatorSessionStatus: AgentSessionStatus.nullable(),
34170
+ canConfigure: external_exports.boolean(),
34171
+ canProbe: external_exports.boolean(),
34172
+ canClose: external_exports.boolean(),
34173
+ maxCaptureCount: external_exports.number().int().positive(),
34174
+ maxCaptureBytes: OobSequenceSchema,
34175
+ admittedCaptureCount: external_exports.number().int().nonnegative(),
34176
+ admittedBytes: OobSequenceSchema,
34177
+ lastCaptureSeq: OobSequenceSchema,
34178
+ counts: OobCountsSchema,
34179
+ probes: external_exports.array(OobProbeAttemptSchema),
34180
+ lastProbeAt: isoDate.nullable(),
34181
+ lastProbeResponseVersion: external_exports.number().int().positive().nullable(),
34182
+ createdAt: isoDate,
34183
+ closedAt: isoDate.nullable(),
34184
+ closedByActor: external_exports.string().nullable(),
34185
+ closeReason: external_exports.string().nullable()
34186
+ });
34187
+ var CreateOobListenerRequestSchema = external_exports.strictObject({
34188
+ requestKey: external_exports.string().min(1).max(128),
34189
+ label: external_exports.string().trim().min(1).max(120),
34190
+ purpose: external_exports.string().trim().min(1).max(1e3),
34191
+ response: OobResponseSchema.optional()
34192
+ });
34193
+ var GetOobListenerRequestSchema = external_exports.strictObject({
34194
+ listenerId: external_exports.uuid().optional(),
34195
+ pageToken: external_exports.string().max(2048).optional(),
34196
+ limit: external_exports.number().int().min(1).max(50).optional()
34197
+ });
34198
+ var ConfigureOobListenerRequestSchema = external_exports.strictObject({
34199
+ listenerId: external_exports.uuid(),
34200
+ expectedResponseVersion: external_exports.number().int().positive(),
34201
+ response: OobResponseSchema
34202
+ });
34203
+ var StaffOobListenerQuotasSchema = external_exports.strictObject({
34204
+ maxCaptureCount: external_exports.number().int().min(1).max(1e4),
34205
+ maxCaptureBytes: external_exports.number().int().min(1).max(1073741824)
34206
+ });
34207
+ var StaffConfigureOobListenerRequestSchema = ConfigureOobListenerRequestSchema.omit({
34208
+ listenerId: true
34209
+ }).extend({
34210
+ reason: external_exports.string().trim().min(1).max(1e3),
34211
+ quotas: StaffOobListenerQuotasSchema.optional()
34212
+ });
34213
+ var PollOobCallbacksRequestSchema = external_exports.strictObject({
34214
+ listenerId: external_exports.uuid(),
34215
+ afterSequence: external_exports.string().max(2048).optional(),
34216
+ limit: external_exports.number().int().min(1).max(50).optional(),
34217
+ includeSystemProbes: external_exports.boolean().optional()
34218
+ });
34219
+ var GetOobCallbackRequestSchema = external_exports.strictObject({
34220
+ listenerId: external_exports.uuid(),
34221
+ captureId: external_exports.uuid()
34222
+ });
34223
+ var ProbeOobListenerRequestSchema = external_exports.strictObject({ listenerId: external_exports.uuid() });
34224
+ var CloseOobListenerRequestSchema = external_exports.strictObject({
34225
+ listenerId: external_exports.uuid(),
34226
+ reason: external_exports.string().trim().min(1).max(1e3)
34227
+ });
34228
+ var RepairOobListenerRequestSchema = external_exports.strictObject({
34229
+ pageToken: external_exports.string().max(2048).optional()
34230
+ });
34231
+ var CreateOobListenerResponseSchema = external_exports.strictObject({ listener: OobListenerSchema });
34232
+ var GetOobListenerResponseSchema = external_exports.strictObject({
34233
+ listeners: external_exports.array(OobListenerSchema),
34234
+ nextPageToken: external_exports.string().nullable()
34235
+ });
34236
+ var ConfigureOobListenerResponseSchema = CreateOobListenerResponseSchema;
34237
+ var ProbeOobListenerResponseSchema = CreateOobListenerResponseSchema;
34238
+ var CloseOobListenerResponseSchema = CreateOobListenerResponseSchema;
34239
+ var OobCallbackSchema = external_exports.strictObject({
34240
+ captureId: external_exports.uuid(),
34241
+ listenerId: external_exports.uuid(),
34242
+ captureSeq: OobSequenceSchema,
34243
+ status: external_exports.literal("COMPLETE"),
34244
+ admittedAt: isoDate,
34245
+ completedAt: isoDate,
34246
+ protocol: OobProtocolSchema,
34247
+ method: external_exports.string(),
34248
+ sourceIp: external_exports.string(),
34249
+ isSystemProbe: external_exports.boolean(),
34250
+ probeAttemptId: external_exports.uuid().nullable(),
34251
+ responseVersion: external_exports.number().int().positive(),
34252
+ bodyBytes: external_exports.number().int().nonnegative(),
34253
+ bodySha256: OobSha256Schema,
34254
+ envelopeBytes: external_exports.number().int().positive(),
34255
+ envelopeSha256: OobSha256Schema,
34256
+ fidelity: external_exports.literal("collector-observed")
34257
+ });
34258
+ var PollOobCallbacksResponseSchema = external_exports.strictObject({
34259
+ callbacks: external_exports.array(OobCallbackSchema),
34260
+ nextCursor: external_exports.string(),
34261
+ observedHighWater: OobSequenceSchema,
34262
+ hasMore: external_exports.boolean(),
34263
+ counts: OobCountsSchema,
34264
+ health: OobListenerHealthSchema
34265
+ });
34266
+ var OobCallbackGrantSchema = OobCallbackSchema.extend({
34267
+ organizationId: external_exports.uuid(),
34268
+ pentestId: external_exports.uuid(),
34269
+ url: external_exports.url(),
34270
+ expiresAt: isoDate
34271
+ });
34272
+ var GetOobCallbackResponseSchema = OobCallbackGrantSchema;
34273
+ var RepairOobListenerResponseSchema = external_exports.strictObject({
34274
+ nextPageToken: external_exports.string().nullable(),
34275
+ repaired: external_exports.number().int().nonnegative(),
34276
+ failed: external_exports.number().int().nonnegative(),
34277
+ pending: external_exports.number().int().nonnegative(),
34278
+ listener: OobListenerSchema
34279
+ });
34280
+
34281
+ // ../../packages/api-contracts/src/contracts/v1/oob-listener.ts
34282
+ var c28 = initContract();
34283
+ var errors = {
34284
+ 400: ErrorResponseSchema,
34285
+ 401: ErrorResponseSchema,
34286
+ 402: ErrorResponseSchema,
34287
+ 403: ErrorResponseSchema,
34288
+ 404: ErrorResponseSchema,
34289
+ 409: ErrorResponseSchema,
34290
+ 500: ErrorResponseSchema,
34291
+ 503: ErrorResponseSchema
34292
+ };
34293
+ var staffPath = "/staff/orgs/:organizationId/pentests/:pentestId/oob-listeners";
34294
+ var oobListenerContract = c28.router({
34295
+ list: {
34296
+ method: "GET",
34297
+ path: staffPath,
34298
+ pathParams: OobListenerParamsSchema,
34299
+ query: GetOobListenerRequestSchema.omit({ listenerId: true }).extend({
34300
+ limit: external_exports.coerce.number().int().min(1).max(50).optional()
34301
+ }),
34302
+ responses: { 200: GetOobListenerResponseSchema, ...errors },
34303
+ summary: "List callback listeners and retained history for a pentest"
34304
+ },
34305
+ create: {
34306
+ method: "POST",
34307
+ path: staffPath,
34308
+ pathParams: OobListenerParamsSchema,
34309
+ body: CreateOobListenerRequestSchema,
34310
+ responses: { 201: CreateOobListenerResponseSchema, ...errors },
34311
+ summary: "Create and probe a callback listener"
34312
+ },
34313
+ get: {
34314
+ method: "GET",
34315
+ path: `${staffPath}/:listenerId`,
34316
+ pathParams: OobListenerIdParamsSchema,
34317
+ responses: { 200: CreateOobListenerResponseSchema, ...errors },
34318
+ summary: "Read callback listener state"
34319
+ },
34320
+ configure: {
34321
+ method: "PATCH",
34322
+ path: `${staffPath}/:listenerId`,
34323
+ pathParams: OobListenerIdParamsSchema,
34324
+ body: StaffConfigureOobListenerRequestSchema,
34325
+ responses: { 200: ConfigureOobListenerResponseSchema, ...errors },
34326
+ summary: "Change a callback listener static response"
34327
+ },
34328
+ poll: {
34329
+ method: "GET",
34330
+ path: `${staffPath}/:listenerId/callbacks`,
34331
+ pathParams: OobListenerIdParamsSchema,
34332
+ query: PollOobCallbacksRequestSchema.omit({ listenerId: true }).extend({
34333
+ limit: external_exports.coerce.number().int().min(1).max(50).optional(),
34334
+ includeSystemProbes: external_exports.union([external_exports.boolean(), external_exports.enum(["true", "false"]).transform((value) => value === "true")]).optional()
34335
+ }),
34336
+ responses: { 200: PollOobCallbacksResponseSchema, ...errors },
34337
+ summary: "Read committed callback metadata"
34338
+ },
34339
+ callback: {
34340
+ method: "GET",
34341
+ path: `${staffPath}/:listenerId/callbacks/:captureId`,
34342
+ pathParams: OobCaptureIdParamsSchema,
34343
+ responses: { 200: GetOobCallbackResponseSchema, ...errors },
34344
+ summary: "Download the original callback evidence"
34345
+ },
34346
+ probe: {
34347
+ method: "POST",
34348
+ path: `${staffPath}/:listenerId/probe`,
34349
+ pathParams: OobListenerIdParamsSchema,
34350
+ body: external_exports.strictObject({}),
34351
+ responses: { 200: ProbeOobListenerResponseSchema, ...errors },
34352
+ summary: "Verify HTTP and HTTPS callback collection"
34353
+ },
34354
+ close: {
34355
+ method: "POST",
34356
+ path: `${staffPath}/:listenerId/close`,
34357
+ pathParams: OobListenerIdParamsSchema,
34358
+ body: CloseOobListenerRequestSchema.omit({ listenerId: true }),
34359
+ responses: { 200: CloseOobListenerResponseSchema, ...errors },
34360
+ summary: "Close a listener while retaining its captured history"
34361
+ },
34362
+ repair: {
34363
+ method: "POST",
34364
+ path: `${staffPath}/:listenerId/repair`,
34365
+ pathParams: OobListenerIdParamsSchema,
34366
+ body: RepairOobListenerRequestSchema,
34367
+ responses: { 200: RepairOobListenerResponseSchema, ...errors },
34368
+ summary: "Repair captures whose object persisted before indexing failed"
34369
+ }
34370
+ });
34371
+ var runScope = { runVersion: external_exports.number().int().nonnegative() };
34372
+ var runParams = external_exports.strictObject({ agentSessionId: external_exports.uuid() });
34373
+ var internalPath = "/internal/v1/agent-sessions/:agentSessionId/oob";
34374
+ var agentSessionOobInternalContract = c28.router({
34375
+ create: {
34376
+ method: "POST",
34377
+ path: `${internalPath}/create`,
34378
+ pathParams: runParams,
34379
+ body: CreateOobListenerRequestSchema.extend(runScope),
34380
+ responses: { 201: CreateOobListenerResponseSchema, ...errors }
34381
+ },
34382
+ get: {
34383
+ method: "POST",
34384
+ path: `${internalPath}/get`,
34385
+ pathParams: runParams,
34386
+ body: GetOobListenerRequestSchema.extend(runScope),
34387
+ responses: { 200: GetOobListenerResponseSchema, ...errors }
34388
+ },
34389
+ configure: {
34390
+ method: "POST",
34391
+ path: `${internalPath}/configure`,
34392
+ pathParams: runParams,
34393
+ body: ConfigureOobListenerRequestSchema.extend(runScope),
34394
+ responses: { 200: ConfigureOobListenerResponseSchema, ...errors }
34395
+ },
34396
+ poll: {
34397
+ method: "POST",
34398
+ path: `${internalPath}/poll`,
34399
+ pathParams: runParams,
34400
+ body: PollOobCallbacksRequestSchema.extend(runScope),
34401
+ responses: { 200: PollOobCallbacksResponseSchema, ...errors }
34402
+ },
34403
+ callback: {
34404
+ method: "POST",
34405
+ path: `${internalPath}/callback`,
34406
+ pathParams: runParams,
34407
+ body: GetOobCallbackRequestSchema.extend(runScope),
34408
+ responses: { 200: GetOobCallbackResponseSchema, ...errors }
34409
+ },
34410
+ probe: {
34411
+ method: "POST",
34412
+ path: `${internalPath}/probe`,
34413
+ pathParams: runParams,
34414
+ body: ProbeOobListenerRequestSchema.extend(runScope),
34415
+ responses: { 200: ProbeOobListenerResponseSchema, ...errors }
34416
+ },
34417
+ close: {
34418
+ method: "POST",
34419
+ path: `${internalPath}/close`,
34420
+ pathParams: runParams,
34421
+ body: CloseOobListenerRequestSchema.extend(runScope),
34422
+ responses: { 200: CloseOobListenerResponseSchema, ...errors }
34423
+ }
34424
+ });
34425
+
33389
34426
  // ../../packages/api-contracts/src/schemas/api/v1/organization.api.ts
33390
34427
  var OrgCapabilityValues = [
33391
34428
  "PENTEST",
@@ -33831,8 +34868,8 @@ var LogoDeleteRequestSchema = external_exports.object({
33831
34868
  });
33832
34869
 
33833
34870
  // ../../packages/api-contracts/src/contracts/v1/organization.ts
33834
- var c27 = initContract();
33835
- var organizationContract = c27.router({
34871
+ var c29 = initContract();
34872
+ var organizationContract = c29.router({
33836
34873
  listOrganizations: {
33837
34874
  method: "GET",
33838
34875
  path: "/organizations",
@@ -34301,7 +35338,7 @@ var organizationContract = c27.router({
34301
35338
  method: "POST",
34302
35339
  path: "/organizations/:organizationId/logos-from-homepage",
34303
35340
  pathParams: OrgIdParamsSchema,
34304
- body: c27.type(),
35341
+ body: c29.type(),
34305
35342
  responses: {
34306
35343
  200: OrganizationResponseSchema,
34307
35344
  // 400 — no homepage set on the organization.
@@ -34317,8 +35354,8 @@ var organizationContract = c27.router({
34317
35354
  });
34318
35355
 
34319
35356
  // ../../packages/api-contracts/src/contracts/v1/payment-card.ts
34320
- var c28 = initContract();
34321
- var paymentCardContract = c28.router({
35357
+ var c30 = initContract();
35358
+ var paymentCardContract = c30.router({
34322
35359
  listPaymentCards: {
34323
35360
  method: "GET",
34324
35361
  path: "/staff/payment-cards",
@@ -34667,8 +35704,8 @@ var ScanReuseSuggestionsResponseSchema = external_exports.object({
34667
35704
  });
34668
35705
 
34669
35706
  // ../../packages/api-contracts/src/contracts/v1/pentest.ts
34670
- var c29 = initContract();
34671
- var pentestContract = c29.router({
35707
+ var c31 = initContract();
35708
+ var pentestContract = c31.router({
34672
35709
  listPentests: {
34673
35710
  method: "GET",
34674
35711
  path: "/organizations/:organizationId/pentests",
@@ -34978,8 +36015,8 @@ var pentestContract = c29.router({
34978
36015
  });
34979
36016
 
34980
36017
  // ../../packages/api-contracts/src/contracts/v1/pentest-attack-chain.ts
34981
- var c30 = initContract();
34982
- var pentestAttackChainContract = c30.router({
36018
+ var c32 = initContract();
36019
+ var pentestAttackChainContract = c32.router({
34983
36020
  listAttackChains: {
34984
36021
  method: "GET",
34985
36022
  path: "/organizations/:organizationId/pentests/:pentestId/attack-chains",
@@ -35098,7 +36135,7 @@ var pentestAttackChainContract = c30.router({
35098
36135
  method: "DELETE",
35099
36136
  path: "/organizations/:organizationId/pentests/:pentestId/attack-chains/:attackChainId",
35100
36137
  pathParams: PentestAttackChainIdParamsSchema,
35101
- body: c30.noBody(),
36138
+ body: c32.noBody(),
35102
36139
  responses: {
35103
36140
  200: DeleteResponseSchema,
35104
36141
  401: ErrorResponseSchema,
@@ -35259,8 +36296,8 @@ var ReadAttestationDownloadResponseSchema = external_exports.union([
35259
36296
  ]);
35260
36297
 
35261
36298
  // ../../packages/api-contracts/src/contracts/v1/pentest-attestation.ts
35262
- var c31 = initContract();
35263
- var pentestAttestationContract = c31.router({
36299
+ var c33 = initContract();
36300
+ var pentestAttestationContract = c33.router({
35264
36301
  getDefaults: {
35265
36302
  method: "GET",
35266
36303
  path: "/organizations/:organizationId/pentests/:pentestId/attestations/defaults",
@@ -35403,8 +36440,8 @@ var ListPentestAuditLogResponseSchema = external_exports.object({
35403
36440
  });
35404
36441
 
35405
36442
  // ../../packages/api-contracts/src/contracts/v1/pentest-audit-log.ts
35406
- var c32 = initContract();
35407
- var pentestAuditLogContract = c32.router({
36443
+ var c34 = initContract();
36444
+ var pentestAuditLogContract = c34.router({
35408
36445
  listAuditLog: {
35409
36446
  method: "GET",
35410
36447
  path: "/organizations/:organizationId/pentests/:pentestId/audit-log",
@@ -35451,8 +36488,8 @@ var CreatePentestAuthorizedDomainRequestSchema = external_exports.object({
35451
36488
  }).strict();
35452
36489
 
35453
36490
  // ../../packages/api-contracts/src/contracts/v1/pentest-authorized-domain.ts
35454
- var c33 = initContract();
35455
- var pentestAuthorizedDomainContract = c33.router({
36491
+ var c35 = initContract();
36492
+ var pentestAuthorizedDomainContract = c35.router({
35456
36493
  getPentestAuthorizedScope: {
35457
36494
  method: "GET",
35458
36495
  path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope",
@@ -35500,14 +36537,118 @@ var pentestAuthorizedDomainContract = c33.router({
35500
36537
  }
35501
36538
  });
35502
36539
 
36540
+ // ../../packages/api-contracts/src/schemas/api/v1/pentest-coverage.api.ts
36541
+ var CoverageTaxonomyValues = ["GENERAL", "LLM", "DESKTOP", "RECON", "OTHER"];
36542
+ var CoverageTaxonomySchema = external_exports.enum(CoverageTaxonomyValues);
36543
+ var CoverageStatusValues = [
36544
+ "COVERED",
36545
+ "PARTIAL",
36546
+ "NOT_COVERED",
36547
+ "NOT_APPLICABLE"
36548
+ ];
36549
+ var CoverageStatusSchema = external_exports.enum(CoverageStatusValues);
36550
+ var CoverageRelevanceValues = ["CRITICAL", "HIGH", "MEDIUM", "NOT_APPLICABLE"];
36551
+ var CoverageRelevanceSchema = external_exports.enum(CoverageRelevanceValues);
36552
+ var CoverageFamilyValues = ["CODE_REVIEW", "RECON", "ASSESSMENT"];
36553
+ var CoverageFamilySchema = external_exports.enum(CoverageFamilyValues);
36554
+ var CoverageGridParamsSchema = OrgIdParamsSchema.extend({
36555
+ pentestId: PentestIdOrDisplayIdSchema
36556
+ });
36557
+ var CoverageContributorSchema = external_exports.object({
36558
+ agentSessionId: external_exports.uuid(),
36559
+ sessionType: CoverageFamilySchema,
36560
+ /** As this session named the class; differs from the row's name when sessions disagree. */
36561
+ className: external_exports.string(),
36562
+ status: CoverageStatusSchema,
36563
+ relevance: CoverageRelevanceSchema,
36564
+ notes: external_exports.string(),
36565
+ mappings: external_exports.array(external_exports.string()),
36566
+ recordedAt: external_exports.coerce.date(),
36567
+ /** The session is still running, so its next write replaces this entry. */
36568
+ inProgress: external_exports.boolean()
36569
+ });
36570
+ var CoverageClassRowSchema = external_exports.object({
36571
+ /** Stable within a response and across refetches: family, taxonomy, class id, and the split name. */
36572
+ rowKey: external_exports.string(),
36573
+ taxonomy: CoverageTaxonomySchema,
36574
+ classId: external_exports.string(),
36575
+ /** The newest contributor's name. */
36576
+ className: external_exports.string(),
36577
+ /** Best status any contributor reached; NOT_APPLICABLE only when every contributor says so. */
36578
+ rolledUpStatus: CoverageStatusSchema,
36579
+ maxRelevance: CoverageRelevanceSchema,
36580
+ /** Contributors recorded more than one status. */
36581
+ disagreement: external_exports.boolean(),
36582
+ /**
36583
+ * One session sent this class id for more than one class, so the id was split by class name.
36584
+ * Free-text ids only; canonical ids end it.
36585
+ */
36586
+ sharedId: external_exports.boolean(),
36587
+ /** Newest first. */
36588
+ contributors: external_exports.array(CoverageContributorSchema)
36589
+ });
36590
+ var CoverageFamilyBandSchema = external_exports.object({
36591
+ family: CoverageFamilySchema,
36592
+ rows: external_exports.array(CoverageClassRowSchema)
36593
+ });
36594
+ var CoverageGridResponseSchema = external_exports.object({
36595
+ /** Families with at least one row, in CoverageFamilyValues order. */
36596
+ bands: external_exports.array(CoverageFamilyBandSchema),
36597
+ /** Rows per rolled-up status, across every band. */
36598
+ summary: external_exports.object({
36599
+ COVERED: external_exports.number().int().nonnegative(),
36600
+ PARTIAL: external_exports.number().int().nonnegative(),
36601
+ NOT_COVERED: external_exports.number().int().nonnegative(),
36602
+ NOT_APPLICABLE: external_exports.number().int().nonnegative()
36603
+ }),
36604
+ /** Sessions with rows, newest recording first. */
36605
+ sessions: external_exports.array(
36606
+ external_exports.object({
36607
+ agentSessionId: external_exports.uuid(),
36608
+ sessionType: CoverageFamilySchema,
36609
+ status: AgentSessionStatus,
36610
+ entryCount: external_exports.number().int().nonnegative(),
36611
+ lastRecordedAt: external_exports.coerce.date()
36612
+ })
36613
+ ),
36614
+ /**
36615
+ * Sessions that recorded coverage into their transcript before coverage moved to the
36616
+ * database. A session resumed across that change appears here and in `sessions`.
36617
+ */
36618
+ legacyCoverageSessions: external_exports.array(
36619
+ external_exports.object({
36620
+ agentSessionId: external_exports.uuid(),
36621
+ sessionType: CoverageFamilySchema,
36622
+ lastRecordedAt: external_exports.coerce.date()
36623
+ })
36624
+ )
36625
+ });
36626
+
36627
+ // ../../packages/api-contracts/src/contracts/v1/pentest-coverage.ts
36628
+ var c36 = initContract();
36629
+ var pentestCoverageContract = c36.router({
36630
+ getCoverageGrid: {
36631
+ method: "GET",
36632
+ path: "/organizations/:organizationId/pentests/:pentestId/coverage",
36633
+ pathParams: CoverageGridParamsSchema,
36634
+ responses: {
36635
+ 200: CoverageGridResponseSchema,
36636
+ 401: ErrorResponseSchema,
36637
+ 403: ErrorResponseSchema,
36638
+ 404: ErrorResponseSchema,
36639
+ 500: ErrorResponseSchema
36640
+ }
36641
+ }
36642
+ });
36643
+
35503
36644
  // ../../packages/api-contracts/src/schemas/api/v1/pentest-egress.api.ts
35504
36645
  var PentestEgressResponseSchema = external_exports.object({
35505
36646
  publicIp: external_exports.string().nullable()
35506
36647
  }).strict();
35507
36648
 
35508
36649
  // ../../packages/api-contracts/src/contracts/v1/pentest-egress.ts
35509
- var c34 = initContract();
35510
- var pentestEgressContract = c34.router({
36650
+ var c37 = initContract();
36651
+ var pentestEgressContract = c37.router({
35511
36652
  getPentestEgress: {
35512
36653
  method: "GET",
35513
36654
  path: "/staff/pentest-egress",
@@ -35546,8 +36687,8 @@ var CreatePentestEngagementExclusionRequestSchema = external_exports.object({
35546
36687
  }).strict();
35547
36688
 
35548
36689
  // ../../packages/api-contracts/src/contracts/v1/pentest-engagement-exclusion.ts
35549
- var c35 = initContract();
35550
- var pentestEngagementExclusionContract = c35.router({
36690
+ var c38 = initContract();
36691
+ var pentestEngagementExclusionContract = c38.router({
35551
36692
  listPentestEngagementExclusions: {
35552
36693
  method: "GET",
35553
36694
  path: "/organizations/:organizationId/pentests/:pentestId/engagement-exclusions",
@@ -35611,8 +36752,8 @@ var CreatePentestEnvironmentRequestSchema = external_exports.object({
35611
36752
  }).strict();
35612
36753
 
35613
36754
  // ../../packages/api-contracts/src/contracts/v1/pentest-environment.ts
35614
- var c36 = initContract();
35615
- var pentestEnvironmentContract = c36.router({
36755
+ var c39 = initContract();
36756
+ var pentestEnvironmentContract = c39.router({
35616
36757
  listPentestEnvironments: {
35617
36758
  method: "GET",
35618
36759
  path: "/organizations/:organizationId/pentests/:pentestId/environments",
@@ -35661,8 +36802,8 @@ var pentestEnvironmentContract = c36.router({
35661
36802
  });
35662
36803
 
35663
36804
  // ../../packages/api-contracts/src/contracts/v1/pentest-finding.ts
35664
- var c37 = initContract();
35665
- var pentestFindingContract = c37.router({
36805
+ var c40 = initContract();
36806
+ var pentestFindingContract = c40.router({
35666
36807
  // ─── Findings ───
35667
36808
  listFindings: {
35668
36809
  method: "GET",
@@ -36331,8 +37472,8 @@ var pentestFindingContract = c37.router({
36331
37472
  });
36332
37473
 
36333
37474
  // ../../packages/api-contracts/src/contracts/v1/pentest-hypothesis.ts
36334
- var c38 = initContract();
36335
- var pentestHypothesisContract = c38.router({
37475
+ var c41 = initContract();
37476
+ var pentestHypothesisContract = c41.router({
36336
37477
  listHypotheses: {
36337
37478
  method: "GET",
36338
37479
  path: "/organizations/:organizationId/pentests/:pentestId/hypotheses",
@@ -36487,8 +37628,8 @@ var DownloadPentestIntakeDocumentResponseSchema = external_exports.object({
36487
37628
  });
36488
37629
 
36489
37630
  // ../../packages/api-contracts/src/contracts/v1/pentest-intake-document.ts
36490
- var c39 = initContract();
36491
- var pentestIntakeDocumentContract = c39.router({
37631
+ var c42 = initContract();
37632
+ var pentestIntakeDocumentContract = c42.router({
36492
37633
  listDocuments: {
36493
37634
  method: "GET",
36494
37635
  path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents",
@@ -36574,8 +37715,8 @@ var pentestIntakeDocumentContract = c39.router({
36574
37715
  });
36575
37716
 
36576
37717
  // ../../packages/api-contracts/src/contracts/v1/pentest-manual-finding.ts
36577
- var c40 = initContract();
36578
- var pentestManualFindingContract = c40.router({
37718
+ var c43 = initContract();
37719
+ var pentestManualFindingContract = c43.router({
36579
37720
  listManualFindings: {
36580
37721
  method: "GET",
36581
37722
  path: "/organizations/:organizationId/pentests/:pentestId/manual-findings",
@@ -36662,8 +37803,8 @@ var pentestManualFindingContract = c40.router({
36662
37803
  });
36663
37804
 
36664
37805
  // ../../packages/api-contracts/src/contracts/v1/pentest-purchase.ts
36665
- var c41 = initContract();
36666
- var pentestPurchaseContract = c41.router({
37806
+ var c44 = initContract();
37807
+ var pentestPurchaseContract = c44.router({
36667
37808
  listPurchases: {
36668
37809
  method: "GET",
36669
37810
  path: "/organizations/:organizationId/pentests/:pentestId/purchases",
@@ -36695,8 +37836,8 @@ var pentestPurchaseContract = c41.router({
36695
37836
  });
36696
37837
 
36697
37838
  // ../../packages/api-contracts/src/contracts/v1/pentest-report-pdf.ts
36698
- var c42 = initContract();
36699
- var pentestReportPdfContract = c42.router({
37839
+ var c45 = initContract();
37840
+ var pentestReportPdfContract = c45.router({
36700
37841
  getCurrent: {
36701
37842
  method: "GET",
36702
37843
  path: "/organizations/:organizationId/pentests/:pentestId/report-pdf",
@@ -36789,7 +37930,7 @@ var pentestReportPdfContract = c42.router({
36789
37930
  // No body: the render always reads current DB state (cover derived via
36790
37931
  // deriveReportCover(), narrative/scope from the row's columns). The legacy
36791
37932
  // dialog payload was retired with the Generate dialog (report-session RS5).
36792
- body: c42.noBody(),
37933
+ body: c45.noBody(),
36793
37934
  responses: {
36794
37935
  202: StartReportPdfGenerationTaskResponseSchema,
36795
37936
  400: ErrorResponseSchema,
@@ -36986,9 +38127,87 @@ var pentestReportPdfContract = c42.router({
36986
38127
  }
36987
38128
  });
36988
38129
 
38130
+ // ../../packages/api-contracts/src/contracts/v1/pentest-tag.ts
38131
+ var c46 = initContract();
38132
+ var pentestTagContract = c46.router({
38133
+ listPentestTags: {
38134
+ method: "GET",
38135
+ path: "/organizations/:organizationId/pentests/:pentestId/tags",
38136
+ pathParams: PentestTagsParamsSchema,
38137
+ responses: {
38138
+ 200: ListPentestTagsResponseSchema,
38139
+ 401: ErrorResponseSchema,
38140
+ 403: ErrorResponseSchema,
38141
+ 404: ErrorResponseSchema,
38142
+ 500: ErrorResponseSchema
38143
+ }
38144
+ },
38145
+ createPentestTag: {
38146
+ method: "POST",
38147
+ path: "/organizations/:organizationId/pentests/:pentestId/tags",
38148
+ pathParams: PentestTagsParamsSchema,
38149
+ body: CreatePentestTagRequestSchema,
38150
+ responses: {
38151
+ 201: PentestTagResponseSchema,
38152
+ 400: ErrorResponseSchema,
38153
+ 401: ErrorResponseSchema,
38154
+ 403: ErrorResponseSchema,
38155
+ 404: ErrorResponseSchema,
38156
+ // PENTEST_TAG_NAME_TAKEN (case-insensitive duplicate) or PENTEST_TAG_LIMIT.
38157
+ 409: ErrorResponseSchema,
38158
+ 500: ErrorResponseSchema
38159
+ }
38160
+ },
38161
+ updatePentestTag: {
38162
+ method: "PATCH",
38163
+ path: "/organizations/:organizationId/pentests/:pentestId/tags/:pentestTagId",
38164
+ pathParams: PentestTagIdParamsSchema,
38165
+ body: UpdatePentestTagRequestSchema,
38166
+ responses: {
38167
+ 200: PentestTagResponseSchema,
38168
+ 400: ErrorResponseSchema,
38169
+ 401: ErrorResponseSchema,
38170
+ 403: ErrorResponseSchema,
38171
+ 404: ErrorResponseSchema,
38172
+ 409: ErrorResponseSchema,
38173
+ 500: ErrorResponseSchema
38174
+ }
38175
+ },
38176
+ deletePentestTag: {
38177
+ method: "DELETE",
38178
+ path: "/organizations/:organizationId/pentests/:pentestId/tags/:pentestTagId",
38179
+ pathParams: PentestTagIdParamsSchema,
38180
+ responses: {
38181
+ 204: DeleteResponseSchema,
38182
+ 401: ErrorResponseSchema,
38183
+ 403: ErrorResponseSchema,
38184
+ 404: ErrorResponseSchema,
38185
+ 500: ErrorResponseSchema
38186
+ }
38187
+ },
38188
+ // Replaces the finding's tag set. Lives beside the tag routes rather than on
38189
+ // `updateFinding` so the classification write has its own audit reason and
38190
+ // never rides along with (or invalidates) a prose or status edit.
38191
+ setPentestFindingTags: {
38192
+ method: "PUT",
38193
+ path: "/organizations/:organizationId/pentests/:pentestId/findings/:pentestFindingId/tags",
38194
+ pathParams: PentestFindingIdParamsSchema,
38195
+ body: SetPentestFindingTagsRequestSchema,
38196
+ responses: {
38197
+ 200: PentestFindingResponseSchema,
38198
+ // PENTEST_TAG_NOT_ON_ENGAGEMENT when an id belongs to another engagement or does not exist.
38199
+ 400: ErrorResponseSchema,
38200
+ 401: ErrorResponseSchema,
38201
+ 403: ErrorResponseSchema,
38202
+ 404: ErrorResponseSchema,
38203
+ 500: ErrorResponseSchema
38204
+ }
38205
+ }
38206
+ });
38207
+
36989
38208
  // ../../packages/api-contracts/src/contracts/v1/pentest-validation.ts
36990
- var c43 = initContract();
36991
- var pentestValidationContract = c43.router({
38209
+ var c47 = initContract();
38210
+ var pentestValidationContract = c47.router({
36992
38211
  listValidationRuns: {
36993
38212
  method: "GET",
36994
38213
  path: "/organizations/:organizationId/pentests/:pentestId/validation-runs",
@@ -37096,8 +38315,8 @@ var pentestValidationContract = c43.router({
37096
38315
  });
37097
38316
 
37098
38317
  // ../../packages/api-contracts/src/contracts/v1/repository.ts
37099
- var c44 = initContract();
37100
- var repositoryContract = c44.router({
38318
+ var c48 = initContract();
38319
+ var repositoryContract = c48.router({
37101
38320
  createRepository: {
37102
38321
  method: "POST",
37103
38322
  path: "/organizations/:organizationId/repositories",
@@ -37302,7 +38521,7 @@ var repositoryContract = c44.router({
37302
38521
  method: "POST",
37303
38522
  path: "/organizations/:organizationId/repositories/scanning-branch/confirm-defaults",
37304
38523
  pathParams: OrgIdParamsSchema,
37305
- body: c44.noBody(),
38524
+ body: c48.noBody(),
37306
38525
  responses: {
37307
38526
  200: ConfirmScanningBranchDefaultsResponseSchema,
37308
38527
  401: ErrorResponseSchema,
@@ -37436,8 +38655,8 @@ var ListScanLogsResponseSchema = external_exports.object({
37436
38655
  });
37437
38656
 
37438
38657
  // ../../packages/api-contracts/src/contracts/v1/scan.ts
37439
- var c45 = initContract();
37440
- var scanContract = c45.router({
38658
+ var c49 = initContract();
38659
+ var scanContract = c49.router({
37441
38660
  createScan: {
37442
38661
  method: "POST",
37443
38662
  path: "/organizations/:organizationId/scans",
@@ -37558,8 +38777,8 @@ var StaffPentestStatsResponseSchema = external_exports.object({
37558
38777
  }).strict();
37559
38778
 
37560
38779
  // ../../packages/api-contracts/src/contracts/v1/staff-pentest-stats.ts
37561
- var c46 = initContract();
37562
- var staffPentestStatsContract = c46.router({
38780
+ var c50 = initContract();
38781
+ var staffPentestStatsContract = c50.router({
37563
38782
  getStaffPentestStats: {
37564
38783
  method: "GET",
37565
38784
  path: "/staff/pentest-stats",
@@ -37605,8 +38824,8 @@ var RenameStaffOrganizationPentestRequestSchema = external_exports.object({
37605
38824
  }).strict();
37606
38825
 
37607
38826
  // ../../packages/api-contracts/src/contracts/v1/staff-pentests.ts
37608
- var c47 = initContract();
37609
- var staffPentestsContract = c47.router({
38827
+ var c51 = initContract();
38828
+ var staffPentestsContract = c51.router({
37610
38829
  listStaffOrganizationPentests: {
37611
38830
  method: "GET",
37612
38831
  path: "/organizations/:organizationId/staff/pentests",
@@ -37773,8 +38992,8 @@ var StaffQueueResponseSchema = external_exports.object({
37773
38992
  }).strict();
37774
38993
 
37775
38994
  // ../../packages/api-contracts/src/contracts/v1/staff-queue.ts
37776
- var c48 = initContract();
37777
- var staffQueueContract = c48.router({
38995
+ var c52 = initContract();
38996
+ var staffQueueContract = c52.router({
37778
38997
  getStaffQueue: {
37779
38998
  method: "GET",
37780
38999
  path: "/staff/queue",
@@ -37838,8 +39057,8 @@ var UpdateTestIntegrationRequestSchema = external_exports.object({
37838
39057
  }).strict();
37839
39058
 
37840
39059
  // ../../packages/api-contracts/src/contracts/v1/test-integration.ts
37841
- var c49 = initContract();
37842
- var testIntegrationContract = c49.router({
39060
+ var c53 = initContract();
39061
+ var testIntegrationContract = c53.router({
37843
39062
  // -- Fixture CRUD (org-less, staff-only) ----------------------------------
37844
39063
  listTestIntegrations: {
37845
39064
  method: "GET",
@@ -37919,7 +39138,7 @@ var testIntegrationContract = c49.router({
37919
39138
  method: "POST",
37920
39139
  path: "/staff/test-integrations/:testIntegrationId/mfa/code",
37921
39140
  pathParams: TestIntegrationIdParamsSchema,
37922
- body: c49.noBody(),
39141
+ body: c53.noBody(),
37923
39142
  responses: {
37924
39143
  200: CredentialMfaCodeResponseSchema,
37925
39144
  401: ErrorResponseSchema,
@@ -38030,8 +39249,8 @@ var MyContextResponseSchema = external_exports.object({
38030
39249
  });
38031
39250
 
38032
39251
  // ../../packages/api-contracts/src/contracts/v1/user.ts
38033
- var c50 = initContract();
38034
- var userContract = c50.router({
39252
+ var c54 = initContract();
39253
+ var userContract = c54.router({
38035
39254
  getStaffProfile: {
38036
39255
  method: "GET",
38037
39256
  path: "/staff/profile",
@@ -38146,8 +39365,8 @@ var VantaIntegrationResponseSchema = external_exports.object({
38146
39365
  });
38147
39366
 
38148
39367
  // ../../packages/api-contracts/src/contracts/v1/vanta-integration.ts
38149
- var c51 = initContract();
38150
- var vantaIntegrationContract = c51.router({
39368
+ var c55 = initContract();
39369
+ var vantaIntegrationContract = c55.router({
38151
39370
  createVantaIntegration: {
38152
39371
  method: "POST",
38153
39372
  path: "/organizations/:organizationId/vanta-integration",
@@ -38231,6 +39450,7 @@ var VulnerabilityCodeSnippetSchema = external_exports.object({
38231
39450
  endLine: external_exports.number().nullable(),
38232
39451
  snippet: external_exports.string().nullable()
38233
39452
  });
39453
+ var FindingReachabilitySchema = external_exports.enum(["reachable", "unreachable"]);
38234
39454
  var VulnerabilityLatestFindingSchema = external_exports.object({
38235
39455
  attackVector: external_exports.string(),
38236
39456
  exploitScenario: external_exports.string(),
@@ -38275,6 +39495,12 @@ var VulnerabilityResponseSchema = external_exports.object({
38275
39495
  codeSnippet: VulnerabilityCodeSnippetSchema,
38276
39496
  explanation: external_exports.string().nullable(),
38277
39497
  latestFinding: VulnerabilityLatestFindingSchema.nullable(),
39498
+ /**
39499
+ * The scanning branch's latest reachability verdict; the dashboard list
39500
+ * filters and tags by it. Null when that branch has not assessed it (reads
39501
+ * as reachable). PR surfaces read `latestFinding.reachability` instead.
39502
+ */
39503
+ scanningBranchReachability: FindingReachabilitySchema.nullable(),
38278
39504
  dependencyGraph: DependencyGraphSchema.nullable(),
38279
39505
  firstDetectedAt: external_exports.coerce.date(),
38280
39506
  lastDetectedAt: external_exports.coerce.date(),
@@ -38314,6 +39540,11 @@ var VulnerabilityFilterRequestSchema = external_exports.object({
38314
39540
  * no branch set are also included to preserve pre-per-branch-labeling rows.
38315
39541
  */
38316
39542
  scanningBranchOnly: external_exports.boolean().default(false).optional(),
39543
+ /**
39544
+ * Restrict to one side of the reachability verdict; omit for both.
39545
+ * `reachable` includes findings no scan assessed.
39546
+ */
39547
+ reachability: FindingReachabilitySchema.optional(),
38317
39548
  page: external_exports.number().int().min(1).default(1).optional(),
38318
39549
  pageSize: external_exports.number().int().min(1).max(200).default(25).optional(),
38319
39550
  sortBy: external_exports.enum(["severity", "status", "createdAt", "updatedAt", "title"]).default("createdAt").optional(),
@@ -38326,6 +39557,11 @@ var VulnerabilityStatusGroupSchema = external_exports.object({
38326
39557
  });
38327
39558
  var FilterVulnerabilitiesResponseSchema = external_exports.object({
38328
39559
  total: external_exports.number(),
39560
+ /**
39561
+ * Unreachable vulnerabilities that match every other filter and the search,
39562
+ * left out because `reachability` was `reachable`. Zero otherwise.
39563
+ */
39564
+ hiddenUnreachableCount: external_exports.number(),
38329
39565
  page: external_exports.number(),
38330
39566
  pageSize: external_exports.number(),
38331
39567
  statusGroups: external_exports.array(VulnerabilityStatusGroupSchema)
@@ -38360,7 +39596,9 @@ var VulnerabilityAggregatedCountsRequestSchema = external_exports.object({
38360
39596
  /** Lower bound for time-series data. Only vulnerabilities created on or after this date are included in the timeSeries field. Does not affect byRepoAndSeverity or byStatusAndSeverity. */
38361
39597
  timeSeriesSince: external_exports.coerce.date().optional(),
38362
39598
  /** When provided, only include vulnerabilities belonging to this repository. */
38363
- repositoryId: external_exports.uuid().optional()
39599
+ repositoryId: external_exports.uuid().optional(),
39600
+ /** Restrict every count to one side of the reachability verdict; omit for both. */
39601
+ reachability: FindingReachabilitySchema.optional()
38364
39602
  });
38365
39603
  var VulnerabilityAggregatedCountsResponseSchema = external_exports.object({
38366
39604
  byRepoAndSeverity: external_exports.array(RepoSeverityCountSchema),
@@ -38489,8 +39727,8 @@ var VerifySharedVulnerabilityEmailCodeResponseSchema = external_exports.object({
38489
39727
  });
38490
39728
 
38491
39729
  // ../../packages/api-contracts/src/contracts/v1/vulnerability.ts
38492
- var c52 = initContract();
38493
- var vulnerabilityContract = c52.router({
39730
+ var c56 = initContract();
39731
+ var vulnerabilityContract = c56.router({
38494
39732
  filterVulnerabilities: {
38495
39733
  method: "POST",
38496
39734
  path: "/organizations/:organizationId/vulnerabilities/filter",
@@ -38715,8 +39953,8 @@ var UpdateVulnerabilityNoteRequestSchema = external_exports.object({
38715
39953
  });
38716
39954
 
38717
39955
  // ../../packages/api-contracts/src/contracts/v1/vulnerability-note.ts
38718
- var c53 = initContract();
38719
- var vulnerabilityNoteContract = c53.router({
39956
+ var c57 = initContract();
39957
+ var vulnerabilityNoteContract = c57.router({
38720
39958
  listNotes: {
38721
39959
  method: "GET",
38722
39960
  path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/notes",
@@ -38897,8 +40135,8 @@ var ListWebhookDeliveriesResponseSchema = external_exports.object({
38897
40135
  });
38898
40136
 
38899
40137
  // ../../packages/api-contracts/src/contracts/v1/webhook-settings.ts
38900
- var c54 = initContract();
38901
- var webhookSettingsContract = c54.router({
40138
+ var c58 = initContract();
40139
+ var webhookSettingsContract = c58.router({
38902
40140
  listWebhookEndpoints: {
38903
40141
  method: "GET",
38904
40142
  path: "/organizations/:organizationId/webhook-settings/endpoints",
@@ -39036,8 +40274,8 @@ var webhookSettingsContract = c54.router({
39036
40274
  });
39037
40275
 
39038
40276
  // ../../packages/api-contracts/src/contracts/v1/index.ts
39039
- var c55 = initContract();
39040
- var v1Contract = c55.router(
40277
+ var c59 = initContract();
40278
+ var v1Contract = c59.router(
39041
40279
  {
39042
40280
  admin: adminContract,
39043
40281
  cloudIntegration: cloudIntegrationContract,
@@ -39045,6 +40283,7 @@ var v1Contract = c55.router(
39045
40283
  codeUpload: codeUploadContract,
39046
40284
  scan: scanContract,
39047
40285
  organization: organizationContract,
40286
+ oobListener: oobListenerContract,
39048
40287
  user: userContract,
39049
40288
  repository: repositoryContract,
39050
40289
  github: githubContract,
@@ -39071,9 +40310,12 @@ var v1Contract = c55.router(
39071
40310
  pentestManualFinding: pentestManualFindingContract,
39072
40311
  pentestAuditLog: pentestAuditLogContract,
39073
40312
  pentestEnvironment: pentestEnvironmentContract,
40313
+ applicationSurfaceMap: applicationSurfaceMapContract,
40314
+ pentestCoverage: pentestCoverageContract,
39074
40315
  pentestEngagementExclusion: pentestEngagementExclusionContract,
39075
40316
  pentestAuthorizedDomain: pentestAuthorizedDomainContract,
39076
40317
  pentestFinding: pentestFindingContract,
40318
+ pentestTag: pentestTagContract,
39077
40319
  pentestAttackChain: pentestAttackChainContract,
39078
40320
  pentestHypothesis: pentestHypothesisContract,
39079
40321
  pentestValidation: pentestValidationContract,
@@ -39100,13 +40342,13 @@ var v1Contract = c55.router(
39100
40342
  );
39101
40343
 
39102
40344
  // ../../packages/api-contracts/src/contracts/index.ts
39103
- var c56 = initContract();
39104
- var contract = c56.router({
40345
+ var c60 = initContract();
40346
+ var contract = c60.router({
39105
40347
  v1: v1Contract
39106
40348
  });
39107
40349
 
39108
40350
  // ../../packages/api-contracts/src/contracts/v1/desktop-host-internal.ts
39109
- var c57 = initContract();
40351
+ var c61 = initContract();
39110
40352
  var MAX_VMS_PER_SYNC = 16;
39111
40353
  var DesktopHostSyncRequestSchema = external_exports.object({
39112
40354
  /** Integer protocol the runner speaks. Below the api's minimum, the host gets
@@ -39131,7 +40373,7 @@ var DesktopHostSyncResponseSchema = external_exports.object({
39131
40373
  * id not listed here is deleted. */
39132
40374
  targets: external_exports.array(DesktopHostSyncTargetSchema).max(MAX_VMS_PER_SYNC)
39133
40375
  });
39134
- var desktopHostInternalContract = c57.router({
40376
+ var desktopHostInternalContract = c61.router({
39135
40377
  sync: {
39136
40378
  method: "POST",
39137
40379
  path: "/internal/v1/desktop-hosts/sync",
@@ -39152,8 +40394,8 @@ var GitHubWebhookResponseSchema = external_exports.object({
39152
40394
  });
39153
40395
 
39154
40396
  // ../../packages/api-contracts/src/contracts/webhooks/github.ts
39155
- var c58 = initContract();
39156
- var githubWebhookContract = c58.router(
40397
+ var c62 = initContract();
40398
+ var githubWebhookContract = c62.router(
39157
40399
  {
39158
40400
  handleWebhook: {
39159
40401
  method: "POST",
@@ -39171,7 +40413,7 @@ var githubWebhookContract = c58.router(
39171
40413
  pathPrefix: "/webhooks"
39172
40414
  }
39173
40415
  );
39174
- var githubReadonlyWebhookContract = c58.router(
40416
+ var githubReadonlyWebhookContract = c62.router(
39175
40417
  {
39176
40418
  handleWebhook: {
39177
40419
  method: "POST",
@@ -39191,9 +40433,9 @@ var githubReadonlyWebhookContract = c58.router(
39191
40433
  );
39192
40434
 
39193
40435
  // ../../packages/api-contracts/src/contracts/webhooks/linear.ts
39194
- var c59 = initContract();
40436
+ var c63 = initContract();
39195
40437
  var LinearWebhookResponseSchema = external_exports.object({ ok: external_exports.boolean() });
39196
- var linearWebhookContract = c59.router(
40438
+ var linearWebhookContract = c63.router(
39197
40439
  {
39198
40440
  handleWebhook: {
39199
40441
  method: "POST",
@@ -39213,7 +40455,7 @@ var linearWebhookContract = c59.router(
39213
40455
  );
39214
40456
 
39215
40457
  // ../../packages/api-contracts/src/contracts/forge/bitbucket.ts
39216
- var c60 = initContract();
40458
+ var c64 = initContract();
39217
40459
  var InstallEventSchema = external_exports.object({
39218
40460
  eventType: external_exports.enum(["avi:forge:installed:app", "avi:forge:upgraded:app"]),
39219
40461
  context: external_exports.object({ cloudId: external_exports.string().min(1) }).loose(),
@@ -39242,7 +40484,7 @@ var ForgePairingCodeResponseSchema = external_exports.discriminatedUnion("state"
39242
40484
  expiresInSeconds: external_exports.number().int()
39243
40485
  })
39244
40486
  ]);
39245
- var forgeBitbucketContract = c60.router(
40487
+ var forgeBitbucketContract = c64.router(
39246
40488
  {
39247
40489
  lifecycle: {
39248
40490
  method: "POST",
@@ -39289,8 +40531,8 @@ var HealthResponseSchema = external_exports.object({
39289
40531
  });
39290
40532
 
39291
40533
  // ../../packages/api-contracts/src/contracts/health.ts
39292
- var c61 = initContract();
39293
- var healthContract = c61.router({
40534
+ var c65 = initContract();
40535
+ var healthContract = c65.router({
39294
40536
  getHealth: {
39295
40537
  method: "GET",
39296
40538
  path: "/health",
@@ -39302,8 +40544,8 @@ var healthContract = c61.router({
39302
40544
  });
39303
40545
 
39304
40546
  // ../../packages/api-contracts/src/contracts/v1/vulnerability-share.ts
39305
- var c62 = initContract();
39306
- var vulnerabilityShareContract = c62.router(
40547
+ var c66 = initContract();
40548
+ var vulnerabilityShareContract = c66.router(
39307
40549
  {
39308
40550
  resolveShareLink: {
39309
40551
  method: "GET",
@@ -39390,8 +40632,8 @@ var UpdatePrVulnerabilityRequestSchema = external_exports.object({
39390
40632
  });
39391
40633
 
39392
40634
  // ../../packages/api-contracts/src/contracts/v1/pr-vulnerability.ts
39393
- var c63 = initContract();
39394
- var prVulnerabilityContract = c63.router(
40635
+ var c67 = initContract();
40636
+ var prVulnerabilityContract = c67.router(
39395
40637
  {
39396
40638
  listPrVulnerabilities: {
39397
40639
  method: "GET",
@@ -42317,12 +43559,12 @@ function buildApplicationsTable(apps) {
42317
43559
  repos: String(a2.repositories.length),
42318
43560
  url: a2.applicationUrl ? sanitizeDisplay(a2.applicationUrl) : "\u2014"
42319
43561
  }));
42320
- const idWidth = Math.max(2, ...cells.map((c65) => c65.id.length));
42321
- const nameWidth = Math.max(4, ...cells.map((c65) => c65.name.length));
42322
- const typeWidth = Math.max(4, ...cells.map((c65) => c65.type.length));
43562
+ const idWidth = Math.max(2, ...cells.map((c69) => c69.id.length));
43563
+ const nameWidth = Math.max(4, ...cells.map((c69) => c69.name.length));
43564
+ const typeWidth = Math.max(4, ...cells.map((c69) => c69.type.length));
42323
43565
  const header = `${"ID".padEnd(idWidth)} ${"NAME".padEnd(nameWidth)} ${"TYPE".padEnd(typeWidth)} REPOS URL`;
42324
43566
  const rows = cells.map(
42325
- (c65) => `${c65.id.padEnd(idWidth)} ${c65.name.padEnd(nameWidth)} ${c65.type.padEnd(typeWidth)} ${c65.repos.padStart(5)} ${c65.url}`
43567
+ (c69) => `${c69.id.padEnd(idWidth)} ${c69.name.padEnd(nameWidth)} ${c69.type.padEnd(typeWidth)} ${c69.repos.padStart(5)} ${c69.url}`
42326
43568
  );
42327
43569
  return { header, rows };
42328
43570
  }
@@ -42342,12 +43584,12 @@ function buildApplicationRepositoriesTable(links) {
42342
43584
  path: l2.repositoryPath ? sanitizeDisplay(l2.repositoryPath) : "\u2014",
42343
43585
  status: formatStatus(l2.repositoryStatus)
42344
43586
  }));
42345
- const nameWidth = Math.max(10, ...cells.map((c65) => c65.name.length));
42346
- const roleWidth = Math.max(4, ...cells.map((c65) => c65.role.length));
42347
- const pathWidth = Math.max(4, ...cells.map((c65) => c65.path.length));
43587
+ const nameWidth = Math.max(10, ...cells.map((c69) => c69.name.length));
43588
+ const roleWidth = Math.max(4, ...cells.map((c69) => c69.role.length));
43589
+ const pathWidth = Math.max(4, ...cells.map((c69) => c69.path.length));
42348
43590
  const header = `${"REPOSITORY".padEnd(nameWidth)} SCAN ${"ROLE".padEnd(roleWidth)} ${"PATH".padEnd(pathWidth)} STATUS`;
42349
43591
  const rows = cells.map(
42350
- (c65) => `${c65.name.padEnd(nameWidth)} ${c65.scan.padEnd(4)} ${c65.role.padEnd(roleWidth)} ${c65.path.padEnd(pathWidth)} ${c65.status}`
43592
+ (c69) => `${c69.name.padEnd(nameWidth)} ${c69.scan.padEnd(4)} ${c69.role.padEnd(roleWidth)} ${c69.path.padEnd(pathWidth)} ${c69.status}`
42351
43593
  );
42352
43594
  return { header, rows };
42353
43595
  }
@@ -43132,8 +44374,8 @@ function wrapTextWithPrefix(e, r2, o2, t2 = o2, s = o2, n3) {
43132
44374
  hard: true,
43133
44375
  trim: false
43134
44376
  }).split(`
43135
- `).map((c65, i2, m2) => {
43136
- const d = n3 ? n3(c65, i2) : c65;
44377
+ `).map((c69, i2, m2) => {
44378
+ const d = n3 ? n3(c69, i2) : c69;
43137
44379
  return i2 === 0 ? `${t2}${d}` : i2 === m2.length - 1 ? `${s}${d}` : `${o2}${d}`;
43138
44380
  }).join(`
43139
44381
  `);
@@ -43631,14 +44873,14 @@ var limitOptions = ({
43631
44873
  Math.min(l2 - a2 + 3, e.length - a2),
43632
44874
  0
43633
44875
  ));
43634
- let d = a2 < e.length && f > 0, c65 = a2 < e.length && f + a2 < e.length;
44876
+ let d = a2 < e.length && f > 0, c69 = a2 < e.length && f + a2 < e.length;
43635
44877
  const W = Math.min(
43636
44878
  f + a2,
43637
44879
  e.length
43638
44880
  ), s = [];
43639
44881
  let g = 0;
43640
- d && g++, c65 && g++;
43641
- const T = f + (d ? 1 : 0), y = W - (c65 ? 1 : 0);
44882
+ d && g++, c69 && g++;
44883
+ const T = f + (d ? 1 : 0), y = W - (c69 ? 1 : 0);
43642
44884
  for (let t2 = T; t2 < y; t2++) {
43643
44885
  const n3 = e[t2], o2 = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o2, i2, {
43644
44886
  hard: true,
@@ -43659,14 +44901,14 @@ var limitOptions = ({
43659
44901
  u4,
43660
44902
  true
43661
44903
  );
43662
- d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u4 && (c65 || (u4 -= 1), { lineCount: o2, removals: n3 } = E())) : (c65 || (u4 -= 1), { lineCount: o2, removals: n3 } = E(), o2 > u4 && (u4 -= 1, { lineCount: o2, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c65 = true, s.splice(s.length - n3, n3));
44904
+ d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u4 && (c69 || (u4 -= 1), { lineCount: o2, removals: n3 } = E())) : (c69 || (u4 -= 1), { lineCount: o2, removals: n3 } = E(), o2 > u4 && (u4 -= 1, { lineCount: o2, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c69 = true, s.splice(s.length - n3, n3));
43663
44905
  }
43664
44906
  const x = [];
43665
44907
  d && x.push(M);
43666
44908
  for (const t2 of s)
43667
44909
  for (const n3 of t2)
43668
44910
  x.push(n3);
43669
- return c65 && x.push(M), x;
44911
+ return c69 && x.push(M), x;
43670
44912
  };
43671
44913
  var confirm = (i2) => {
43672
44914
  const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
@@ -43685,15 +44927,15 @@ var confirm = (i2) => {
43685
44927
  u4
43686
44928
  ), o2 = `${e ? `${styleText2("gray", S_BAR)}
43687
44929
  ` : ""}${f}
43688
- `, c65 = this.value ? a2 : s;
44930
+ `, c69 = this.value ? a2 : s;
43689
44931
  switch (this.state) {
43690
44932
  case "submit": {
43691
44933
  const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
43692
- return `${o2}${r2}${styleText2("dim", c65)}`;
44934
+ return `${o2}${r2}${styleText2("dim", c69)}`;
43693
44935
  }
43694
44936
  case "cancel": {
43695
44937
  const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
43696
- return `${o2}${r2}${styleText2(["strikethrough", "dim"], c65)}${e ? `
44938
+ return `${o2}${r2}${styleText2(["strikethrough", "dim"], c69)}${e ? `
43697
44939
  ${styleText2("gray", S_BAR)}` : ""}`;
43698
44940
  }
43699
44941
  default: {
@@ -43841,13 +45083,13 @@ var multiline = (e) => new h({
43841
45083
  `, m2 = e.placeholder && e.placeholder.length > 0 ? (
43842
45084
  // biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
43843
45085
  styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1))
43844
- ) : styleText2(["inverse", "hidden"], "_"), a2 = this.userInput ? this.userInputWithCursor : m2, l2 = this.value ?? "", c65 = e.showSubmit ? `
45086
+ ) : styleText2(["inverse", "hidden"], "_"), a2 = this.userInput ? this.userInputWithCursor : m2, l2 = this.value ?? "", c69 = e.showSubmit ? `
43845
45087
  ${styleText2(this.focused === "submit" ? "cyan" : "dim", "[ submit ]")}` : "";
43846
45088
  switch (this.state) {
43847
45089
  case "error": {
43848
45090
  const n3 = `${styleText2("yellow", S_BAR)} `, r2 = i2 ? wrapTextWithPrefix(e.output, a2, n3, void 0) : a2, u4 = styleText2("yellow", S_BAR_END);
43849
45091
  return `${o2}${r2}
43850
- ${u4} ${styleText2("yellow", this.error)}${c65}
45092
+ ${u4} ${styleText2("yellow", this.error)}${c69}
43851
45093
  `;
43852
45094
  }
43853
45095
  case "submit": {
@@ -43875,7 +45117,7 @@ ${u4} ${styleText2("yellow", this.error)}${c65}
43875
45117
  default: {
43876
45118
  const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "", u4 = i2 ? wrapTextWithPrefix(e.output, a2, n3) : a2;
43877
45119
  return `${o2}${u4}
43878
- ${r2}${c65}
45120
+ ${r2}${c69}
43879
45121
  `;
43880
45122
  }
43881
45123
  }
@@ -43890,7 +45132,7 @@ var password = (r2) => new u$1({
43890
45132
  render() {
43891
45133
  const e = r2.withGuide ?? settings.withGuide, o2 = `${e ? `${styleText2("gray", S_BAR)}
43892
45134
  ` : ""}${symbol2(this.state)} ${r2.message}
43893
- `, c65 = this.userInputWithCursor, i2 = this.masked;
45135
+ `, c69 = this.userInputWithCursor, i2 = this.masked;
43894
45136
  switch (this.state) {
43895
45137
  case "error": {
43896
45138
  const s = e ? `${styleText2("yellow", S_BAR)} ` : "", n3 = e ? `${styleText2("yellow", S_BAR_END)} ` : "", l2 = i2 ?? "";
@@ -43910,7 +45152,7 @@ ${styleText2("gray", S_BAR)}` : ""}`;
43910
45152
  }
43911
45153
  default: {
43912
45154
  const s = e ? `${styleText2("cyan", S_BAR)} ` : "", n3 = e ? styleText2("cyan", S_BAR_END) : "";
43913
- return `${o2}${s}${c65}
45155
+ return `${o2}${s}${c69}
43914
45156
  ${n3}
43915
45157
  `;
43916
45158
  }
@@ -43926,7 +45168,7 @@ var SELECT_INSTRUCTIONS = [
43926
45168
  `${styleText2("dim", "\u2191/\u2193")} to navigate`,
43927
45169
  `${styleText2("dim", "Enter:")} confirm`
43928
45170
  ];
43929
- var c64 = (t2, o2) => t2.includes(`
45171
+ var c68 = (t2, o2) => t2.includes(`
43930
45172
  `) ? t2.split(`
43931
45173
  `).map((d) => o2(d)).join(`
43932
45174
  `) : o2(t2);
@@ -43937,15 +45179,15 @@ var select = (t2) => {
43937
45179
  const s = n3.label ?? String(n3.value);
43938
45180
  switch (m2) {
43939
45181
  case "disabled":
43940
- return `${styleText2("gray", S_RADIO_INACTIVE)} ${c64(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
45182
+ return `${styleText2("gray", S_RADIO_INACTIVE)} ${c68(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
43941
45183
  case "selected":
43942
- return `${c64(s, (i2) => styleText2("dim", i2))}`;
45184
+ return `${c68(s, (i2) => styleText2("dim", i2))}`;
43943
45185
  case "active":
43944
45186
  return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
43945
45187
  case "cancelled":
43946
- return `${c64(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
45188
+ return `${c68(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
43947
45189
  default:
43948
- return `${styleText2("dim", S_RADIO_INACTIVE)} ${c64(s, (i2) => styleText2("dim", i2))}`;
45190
+ return `${styleText2("dim", S_RADIO_INACTIVE)} ${c68(s, (i2) => styleText2("dim", i2))}`;
43949
45191
  }
43950
45192
  }, d = t2.showInstructions ?? true;
43951
45193
  return new n$1({
@@ -44004,6 +45246,124 @@ ${b}
44004
45246
  };
44005
45247
  var i = `${styleText2("gray", S_BAR)} `;
44006
45248
 
45249
+ // src/org/invite.ts
45250
+ var MEMBER_ROLE_SLUGS = MemberRoleSlugSchema.options;
45251
+ var DEFAULT_INVITE_ROLE = CreateMemberInvitationRequestSchema.shape.roleSlug.parse(void 0);
45252
+ var InviteEmailSchema = CreateMemberInvitationRequestSchema.shape.email;
45253
+ function planInvite(emailArg, options) {
45254
+ const email3 = emailArg.trim();
45255
+ if (email3.length === 0) {
45256
+ return { error: "Email is required." };
45257
+ }
45258
+ if (!InviteEmailSchema.safeParse(email3).success) {
45259
+ return { error: `'${sanitizeDisplay(email3)}' is not a valid email address.` };
45260
+ }
45261
+ const role = options.role.trim().toLowerCase();
45262
+ const parsedRole = MemberRoleSlugSchema.safeParse(role);
45263
+ if (!parsedRole.success) {
45264
+ return {
45265
+ error: `Invalid --role '${sanitizeDisplay(options.role)}'. Use one of: ${MEMBER_ROLE_SLUGS.join(", ")}.`
45266
+ };
45267
+ }
45268
+ return { plan: { email: email3, roleSlug: parsedRole.data } };
45269
+ }
45270
+ function failInvite(status, body) {
45271
+ const { message } = readErrorFields(body);
45272
+ if (status === UNAUTHORIZED_STATUS2) {
45273
+ exitAuthFailed();
45274
+ }
45275
+ if (status === 403) {
45276
+ const hint = "Inviting members requires an organization admin or analyst signed in with `tracecli auth login` (API keys are rejected).";
45277
+ console.error(
45278
+ colorError(message === void 0 || message === "Insufficient permissions" ? hint : message)
45279
+ );
45280
+ process.exit(1);
45281
+ }
45282
+ if (status === 409) {
45283
+ console.error(
45284
+ colorError(message ?? "This person is already a member or already has a pending invitation.")
45285
+ );
45286
+ process.exit(1);
45287
+ }
45288
+ if (status === 503) {
45289
+ console.error(
45290
+ colorError(message ?? "Member invitations are not available in this environment.")
45291
+ );
45292
+ process.exit(1);
45293
+ }
45294
+ if (status === 400 || status === 404 || status === 422) {
45295
+ console.error(colorError(message ?? `Failed to send invitation (status ${status}).`));
45296
+ process.exit(1);
45297
+ }
45298
+ console.error(
45299
+ colorError(`Failed to send invitation (status ${status})${message ? `: ${message}` : "."}`)
45300
+ );
45301
+ process.exit(1);
45302
+ }
45303
+ function outputInvitation(invitation, output) {
45304
+ if (output === "json") {
45305
+ printJson(invitation);
45306
+ return;
45307
+ }
45308
+ if (output === "tsv") {
45309
+ console.log("invitationId email roleSlug");
45310
+ console.log(
45311
+ [
45312
+ tsvSafe(sanitizeDisplay(invitation.invitationId)),
45313
+ tsvSafe(formulaSafe(sanitizeDisplay(invitation.email))),
45314
+ tsvSafe(sanitizeDisplay(invitation.roleSlug))
45315
+ ].join(" ")
45316
+ );
45317
+ return;
45318
+ }
45319
+ console.log(
45320
+ colorSuccess(
45321
+ `Invitation sent to ${sanitizeDisplay(invitation.email)} as ${sanitizeDisplay(invitation.roleSlug)}`
45322
+ )
45323
+ );
45324
+ console.log(` Invitation ID: ${sanitizeDisplay(invitation.invitationId)}`);
45325
+ }
45326
+ async function runInvite(emailArg, options) {
45327
+ const output = parseOutput(options.output);
45328
+ const planned = planInvite(emailArg, options);
45329
+ if ("error" in planned) {
45330
+ console.error(colorError(planned.error));
45331
+ process.exit(1);
45332
+ }
45333
+ const { plan } = planned;
45334
+ const organizationId = await resolveOrganizationId();
45335
+ const result = await authenticatedRequest(
45336
+ (client) => client.member.createInvitation({
45337
+ params: { organizationId },
45338
+ body: { email: plan.email, roleSlug: plan.roleSlug }
45339
+ })
45340
+ );
45341
+ if (result.status !== CREATED_STATUS) {
45342
+ failInvite(result.status, result.body);
45343
+ }
45344
+ outputInvitation(result.body, output);
45345
+ }
45346
+ function createOrgInviteCommand() {
45347
+ return new Command("invite").description("Invite someone to the active organization by email").argument("<email>", "Email address to invite").option(
45348
+ "-r, --role <role>",
45349
+ `Role to grant: ${MEMBER_ROLE_SLUGS.join(", ")}`,
45350
+ DEFAULT_INVITE_ROLE
45351
+ ).option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
45352
+ "after",
45353
+ `
45354
+ Sends the same invitation email as the dashboard's Settings > Members page.
45355
+ Requires an organization admin or analyst signed in with \`tracecli auth login\`;
45356
+ API keys are rejected. Only admins can invite someone as an admin.
45357
+
45358
+ Examples:
45359
+ tracecli org invite dev@acme.com
45360
+ tracecli org invite sec@acme.com --role analyst
45361
+ tracecli org invite cto@acme.com --role admin --output json`
45362
+ ).action(async (email3, options) => {
45363
+ await runInvite(email3, options);
45364
+ });
45365
+ }
45366
+
44007
45367
  // src/org/update.ts
44008
45368
  import { readFileSync as readFileSync2, statSync } from "fs";
44009
45369
  import { basename, extname } from "path";
@@ -45094,6 +46454,7 @@ function createOrgCommand() {
45094
46454
  org.addCommand(createOrgCurrentCommand());
45095
46455
  org.addCommand(createOrgSwitchCommand());
45096
46456
  org.addCommand(createOrgUpdateCommand());
46457
+ org.addCommand(createOrgInviteCommand());
45097
46458
  return org;
45098
46459
  }
45099
46460
  function createAuthCommand() {
@@ -45323,7 +46684,7 @@ function extractCommandTree(cmd) {
45323
46684
  description: o2.description,
45324
46685
  takesValue: o2.required || o2.optional
45325
46686
  }));
45326
- const subcommands = cmd.commands.filter((c65) => !c65._hidden).map((c65) => extractCommandTree(c65));
46687
+ const subcommands = cmd.commands.filter((c69) => !c69._hidden).map((c69) => extractCommandTree(c69));
45327
46688
  return {
45328
46689
  name: cmd.name(),
45329
46690
  description: cmd.description(),
@@ -45389,7 +46750,7 @@ function generateBashCompletion(tree, binName) {
45389
46750
  }
45390
46751
  function collectBashCases(tree, prefix) {
45391
46752
  const cases = /* @__PURE__ */ new Map();
45392
- const subcommandNames = tree.subcommands.map((c65) => c65.name);
46753
+ const subcommandNames = tree.subcommands.map((c69) => c69.name);
45393
46754
  const optionNames = tree.options.flatMap((o2) => o2.short ? [o2.long, o2.short] : [o2.long]);
45394
46755
  const extraOptions = prefix === "" ? ["--help", "--version"] : ["--help"];
45395
46756
  const allOptions = [.../* @__PURE__ */ new Set([...optionNames, ...extraOptions])];
@@ -45804,9 +47165,9 @@ function buildInboxesTable(inboxes) {
45804
47165
  address: sanitizeDisplay(inbox.address),
45805
47166
  label: sanitizeDisplay(inbox.label)
45806
47167
  }));
45807
- const addressWidth = Math.max(7, ...cells.map((c65) => c65.address.length));
47168
+ const addressWidth = Math.max(7, ...cells.map((c69) => c69.address.length));
45808
47169
  const header = `${"ADDRESS".padEnd(addressWidth)} LABEL`;
45809
- const rows = cells.map((c65) => `${c65.address.padEnd(addressWidth)} ${c65.label}`);
47170
+ const rows = cells.map((c69) => `${c69.address.padEnd(addressWidth)} ${c69.label}`);
45810
47171
  return { header, rows };
45811
47172
  }
45812
47173
  function formatInboxQuota(quota) {
@@ -45830,14 +47191,14 @@ function buildInboxEmailsTable(messages) {
45830
47191
  subject: sanitizeDisplay(message.subject ?? ""),
45831
47192
  unread: message.unread ? "yes" : "no"
45832
47193
  }));
45833
- const idWidth = Math.max(2, ...cells.map((c65) => c65.id.length));
45834
- const receivedWidth = Math.max(8, ...cells.map((c65) => c65.received.length));
45835
- const fromWidth = Math.max(4, ...cells.map((c65) => c65.from.length));
45836
- const toWidth = Math.max(2, ...cells.map((c65) => c65.to.length));
45837
- const subjectWidth = Math.max(7, ...cells.map((c65) => c65.subject.length));
47194
+ const idWidth = Math.max(2, ...cells.map((c69) => c69.id.length));
47195
+ const receivedWidth = Math.max(8, ...cells.map((c69) => c69.received.length));
47196
+ const fromWidth = Math.max(4, ...cells.map((c69) => c69.from.length));
47197
+ const toWidth = Math.max(2, ...cells.map((c69) => c69.to.length));
47198
+ const subjectWidth = Math.max(7, ...cells.map((c69) => c69.subject.length));
45838
47199
  const header = `${"ID".padEnd(idWidth)} ${"RECEIVED".padEnd(receivedWidth)} ${"FROM".padEnd(fromWidth)} ${"TO".padEnd(toWidth)} ${"SUBJECT".padEnd(subjectWidth)} UNREAD`;
45839
47200
  const rows = cells.map(
45840
- (c65) => `${c65.id.padEnd(idWidth)} ${c65.received.padEnd(receivedWidth)} ${c65.from.padEnd(fromWidth)} ${c65.to.padEnd(toWidth)} ${c65.subject.padEnd(subjectWidth)} ${c65.unread}`
47201
+ (c69) => `${c69.id.padEnd(idWidth)} ${c69.received.padEnd(receivedWidth)} ${c69.from.padEnd(fromWidth)} ${c69.to.padEnd(toWidth)} ${c69.subject.padEnd(subjectWidth)} ${c69.unread}`
45841
47202
  );
45842
47203
  return { header, rows };
45843
47204
  }
@@ -46612,16 +47973,16 @@ function printCredentialsTsv(creds) {
46612
47973
  }
46613
47974
  }
46614
47975
  function buildCredentialsTable(creds) {
46615
- const cells = creds.map((c65) => ({
46616
- id: c65.credentialId,
46617
- label: sanitizeDisplay(c65.label),
46618
- type: c65.credentialType
47976
+ const cells = creds.map((c69) => ({
47977
+ id: c69.credentialId,
47978
+ label: sanitizeDisplay(c69.label),
47979
+ type: c69.credentialType
46619
47980
  }));
46620
- const idWidth = Math.max(2, ...cells.map((c65) => c65.id.length));
46621
- const labelWidth = Math.max(5, ...cells.map((c65) => c65.label.length));
47981
+ const idWidth = Math.max(2, ...cells.map((c69) => c69.id.length));
47982
+ const labelWidth = Math.max(5, ...cells.map((c69) => c69.label.length));
46622
47983
  const header = `${"ID".padEnd(idWidth)} ${"LABEL".padEnd(labelWidth)} TYPE`;
46623
47984
  const rows = cells.map(
46624
- (c65) => `${c65.id.padEnd(idWidth)} ${c65.label.padEnd(labelWidth)} ${c65.type}`
47985
+ (c69) => `${c69.id.padEnd(idWidth)} ${c69.label.padEnd(labelWidth)} ${c69.type}`
46625
47986
  );
46626
47987
  return { header, rows };
46627
47988
  }
@@ -47391,14 +48752,14 @@ function buildEnvironmentTable(envs, leading) {
47391
48752
  url: e.primaryUrl != null ? sanitizeDisplay(e.primaryUrl) : "\u2014"
47392
48753
  }));
47393
48754
  const leadingWidths = leading.map(
47394
- (column, i2) => Math.max(column.header.length, ...cells.map((c65) => c65.leading[i2]?.length ?? 0))
48755
+ (column, i2) => Math.max(column.header.length, ...cells.map((c69) => c69.leading[i2]?.length ?? 0))
47395
48756
  );
47396
- const nameWidth = Math.max(4, ...cells.map((c65) => c65.name.length));
48757
+ const nameWidth = Math.max(4, ...cells.map((c69) => c69.name.length));
47397
48758
  const padLeading = (values) => values.map((v, i2) => v.padEnd(leadingWidths[i2] ?? 0)).join(" ");
47398
48759
  return {
47399
- header: `${padLeading(leading.map((c65) => c65.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
48760
+ header: `${padLeading(leading.map((c69) => c69.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
47400
48761
  rows: cells.map(
47401
- (c65) => `${padLeading(c65.leading)} ${c65.name.padEnd(nameWidth)} ${c65.prod.padEnd(4)} ${c65.url}`
48762
+ (c69) => `${padLeading(c69.leading)} ${c69.name.padEnd(nameWidth)} ${c69.prod.padEnd(4)} ${c69.url}`
47402
48763
  )
47403
48764
  };
47404
48765
  }
@@ -49441,6 +50802,10 @@ function formatFindingMarkdown(finding) {
49441
50802
  if (finding.owaspCategory) {
49442
50803
  lines.push(`- OWASP: ${sanitizeDisplay(finding.owaspCategory)}`);
49443
50804
  }
50805
+ const tags = finding.tags ?? [];
50806
+ if (tags.length > 0) {
50807
+ lines.push(`- Tags: ${tags.map((tag) => sanitizeDisplay(tag.name)).join(", ")}`);
50808
+ }
49444
50809
  if (finding.cvssScore !== null || finding.cvssVector) {
49445
50810
  const parts = [
49446
50811
  finding.cvssScore !== null ? String(finding.cvssScore) : null,
@@ -51826,13 +53191,13 @@ function buildUploadsTable(uploads) {
51826
53191
  size: formatArchiveBytes(upload.sizeBytes),
51827
53192
  id: upload.codeUploadId
51828
53193
  }));
51829
- const nameWidth = Math.max(4, ...cells.map((c65) => c65.name.length));
51830
- const kindWidth = Math.max(4, ...cells.map((c65) => c65.kind.length));
51831
- const statusWidth = Math.max(6, ...cells.map((c65) => c65.status.length));
51832
- const sizeWidth = Math.max(4, ...cells.map((c65) => c65.size.length));
53194
+ const nameWidth = Math.max(4, ...cells.map((c69) => c69.name.length));
53195
+ const kindWidth = Math.max(4, ...cells.map((c69) => c69.kind.length));
53196
+ const statusWidth = Math.max(6, ...cells.map((c69) => c69.status.length));
53197
+ const sizeWidth = Math.max(4, ...cells.map((c69) => c69.size.length));
51833
53198
  const header = `${"NAME".padEnd(nameWidth)} ${"KIND".padEnd(kindWidth)} ${"STATUS".padEnd(statusWidth)} ${"SIZE".padEnd(sizeWidth)} ID`;
51834
53199
  const rows = cells.map(
51835
- (c65) => `${c65.name.padEnd(nameWidth)} ${c65.kind.padEnd(kindWidth)} ${c65.status.padEnd(statusWidth)} ${c65.size.padEnd(sizeWidth)} ${c65.id}`
53200
+ (c69) => `${c69.name.padEnd(nameWidth)} ${c69.kind.padEnd(kindWidth)} ${c69.status.padEnd(statusWidth)} ${c69.size.padEnd(sizeWidth)} ${c69.id}`
51836
53201
  );
51837
53202
  return { header, rows };
51838
53203
  }