securewithtrace 0.37.0 → 0.38.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 +653 -373
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6276,7 +6276,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
6276
6276
  function isValidBase64URL(data) {
6277
6277
  if (!base64url.test(data))
6278
6278
  return false;
6279
- const base643 = data.replace(/[-_]/g, (c58) => c58 === "-" ? "+" : "/");
6279
+ const base643 = data.replace(/[-_]/g, (c59) => c59 === "-" ? "+" : "/");
6280
6280
  const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
6281
6281
  return isValidBase64(padded);
6282
6282
  }
@@ -16320,9 +16320,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
16320
16320
  inst._zod.processJSONSchema = (ctx, json2, params) => dateProcessor(inst, ctx, json2, params);
16321
16321
  inst.min = (value, params) => inst.check(_gte(value, params));
16322
16322
  inst.max = (value, params) => inst.check(_lte(value, params));
16323
- const c58 = inst._zod.bag;
16324
- inst.minDate = c58.minimum ? new Date(c58.minimum) : null;
16325
- inst.maxDate = c58.maximum ? new Date(c58.maximum) : null;
16323
+ const c59 = inst._zod.bag;
16324
+ inst.minDate = c59.minimum ? new Date(c59.minimum) : null;
16325
+ inst.maxDate = c59.maximum ? new Date(c59.maximum) : null;
16326
16326
  });
16327
16327
  function date3(params) {
16328
16328
  return _date(ZodDate, params);
@@ -21998,7 +21998,7 @@ var PentestEditActionValues = [
21998
21998
  "DELIVER"
21999
21999
  ];
22000
22000
  var PentestEditAction = external_exports.enum(PentestEditActionValues);
22001
- var PentestAuditActorTypeValues = ["USER", "SYSTEM", "AGENT"];
22001
+ var PentestAuditActorTypeValues = ["USER", "SYSTEM", "AGENT", "API_KEY"];
22002
22002
  var PentestAuditActorType = external_exports.enum(PentestAuditActorTypeValues);
22003
22003
  var PentestHypothesisStatusValues = [
22004
22004
  "DRAFTED",
@@ -23008,6 +23008,263 @@ var LinearTicketContextResponseSchema = external_exports.object({
23008
23008
  var AttestationClassificationValues = ["PUBLIC", "CONFIDENTIAL"];
23009
23009
  var AttestationClassification = external_exports.enum(AttestationClassificationValues);
23010
23010
 
23011
+ // ../../packages/api-contracts/src/schemas/api/v1/repository.api.ts
23012
+ var PlatformValues = ["GITHUB", "GITLAB", "BITBUCKET", "UPLOAD"];
23013
+ var RepositoryStatusValues = ["CONNECTED", "DISCONNECTED"];
23014
+ var RepositoryIdParamsSchema = OrgIdParamsSchema.extend({
23015
+ repositoryId: external_exports.uuid()
23016
+ });
23017
+ var CreateRepositoryRequestSchema = external_exports.object({
23018
+ repositoryUrl: external_exports.url(),
23019
+ platform: external_exports.enum(PlatformValues),
23020
+ githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
23021
+ status: external_exports.enum(RepositoryStatusValues).optional()
23022
+ });
23023
+ var UpdateRepositoryRequestSchema = external_exports.object({
23024
+ repositoryUrl: external_exports.url().optional(),
23025
+ platform: external_exports.enum(PlatformValues).optional(),
23026
+ githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
23027
+ status: external_exports.enum(RepositoryStatusValues).optional()
23028
+ });
23029
+ var RepositoryResponseSchema = external_exports.object({
23030
+ repositoryId: external_exports.uuid(),
23031
+ organizationId: external_exports.uuid(),
23032
+ repositoryUrl: external_exports.url(),
23033
+ platform: external_exports.enum(PlatformValues),
23034
+ status: external_exports.enum(RepositoryStatusValues),
23035
+ githubDefaultBranch: external_exports.string(),
23036
+ scanningBranch: external_exports.string().nullable(),
23037
+ primaryLanguage: external_exports.string().nullable().optional(),
23038
+ /** Staff-set opt-in: automated PR scans run on this repo even without a FULL SAST baseline. */
23039
+ prScansEnabled: external_exports.boolean(),
23040
+ createdAt: external_exports.date(),
23041
+ updatedAt: external_exports.date()
23042
+ });
23043
+ var ListRepositoriesResponseSchema = external_exports.array(RepositoryResponseSchema);
23044
+ var SetPrScansEnabledRequestSchema = external_exports.object({
23045
+ enabled: external_exports.boolean()
23046
+ });
23047
+ var StaffRepositoryPrScanSettingSchema = external_exports.object({
23048
+ repositoryId: external_exports.uuid(),
23049
+ /** GitHub owner/name when synced; null for rows created before the sync backfill. */
23050
+ fullName: external_exports.string().nullable(),
23051
+ repositoryUrl: external_exports.url(),
23052
+ /** The staff-set opt-in arm of the gate. */
23053
+ prScansEnabled: external_exports.boolean(),
23054
+ /**
23055
+ * The implicit arm: a completed FULL SAST scan exists for this repo (any
23056
+ * branch). With the org capability granted, either arm open means PR scans run.
23057
+ */
23058
+ hasSastBaseline: external_exports.boolean()
23059
+ });
23060
+ var StaffPrScanSettingsResponseSchema = external_exports.object({
23061
+ /** Org-level gate: without AUTO_PR_SCANS the per-repo switches are inert. */
23062
+ orgHasAutoPrScans: external_exports.boolean(),
23063
+ repositories: external_exports.array(StaffRepositoryPrScanSettingSchema)
23064
+ });
23065
+ var CloneTokenRequestSchema = external_exports.object({
23066
+ repositoryUrl: external_exports.string().url()
23067
+ });
23068
+ var CloneTokenResponseSchema = external_exports.object({
23069
+ token: external_exports.string(),
23070
+ expiresAt: external_exports.string().datetime(),
23071
+ // Git username scheme to pair with this token. GitHub installation tokens
23072
+ // use `x-access-token`; Bitbucket app tokens use `x-token-auth`. Optional
23073
+ // for back-compat with CLIs that predate Bitbucket support and hardcode
23074
+ // `x-access-token` (the correct value for the GitHub-only flow they gate on).
23075
+ username: external_exports.enum(["x-access-token", "x-token-auth"]).optional()
23076
+ });
23077
+ var ScanningBranchHistoryEntrySchema = external_exports.object({
23078
+ historyId: external_exports.uuid(),
23079
+ branch: external_exports.string(),
23080
+ configuredAt: external_exports.date(),
23081
+ replacedAt: external_exports.date(),
23082
+ configuredByUserId: external_exports.uuid().nullable()
23083
+ });
23084
+ var ScanningBranchStateSchema = external_exports.object({
23085
+ scanningBranch: external_exports.string().nullable(),
23086
+ githubDefaultBranch: external_exports.string(),
23087
+ history: external_exports.array(ScanningBranchHistoryEntrySchema)
23088
+ });
23089
+ var SetScanningBranchRequestSchema = external_exports.object({
23090
+ branch: external_exports.string().min(1).max(255),
23091
+ migrateOpenVulnerabilities: external_exports.boolean(),
23092
+ /**
23093
+ * Optional compare-and-swap guard. When provided, the switch only commits
23094
+ * if the repo's current `scanningBranch` matches. Mismatch → HTTP 409.
23095
+ * `null` means "expect this repo to still be unconfigured."
23096
+ */
23097
+ expectedCurrentBranch: external_exports.string().nullable().optional()
23098
+ });
23099
+ var SetScanningBranchResponseSchema = external_exports.object({
23100
+ previousBranch: external_exports.string().nullable(),
23101
+ newBranch: external_exports.string(),
23102
+ relabeledVulnerabilityCount: external_exports.number().int().min(0),
23103
+ /** Null when previousBranch was null (initial configuration). */
23104
+ historyId: external_exports.uuid().nullable()
23105
+ });
23106
+ var BulkSetScanningBranchBranchSchema = external_exports.discriminatedUnion("kind", [
23107
+ external_exports.object({ kind: external_exports.literal("literal"), value: external_exports.string().min(1).max(255) }),
23108
+ external_exports.object({ kind: external_exports.literal("github-default") })
23109
+ ]);
23110
+ var BulkSetScanningBranchRequestSchema = external_exports.object({
23111
+ branch: BulkSetScanningBranchBranchSchema,
23112
+ repositoryIds: external_exports.array(external_exports.uuid()).min(1).max(100),
23113
+ migrateOpenVulnerabilities: external_exports.boolean()
23114
+ });
23115
+ var BulkSetScanningBranchResultStatusValues = [
23116
+ "switched",
23117
+ "branch-missing-on-github",
23118
+ "forbidden",
23119
+ "already-on-branch",
23120
+ "not-found",
23121
+ "error"
23122
+ ];
23123
+ var BulkSetScanningBranchResultSchema = external_exports.object({
23124
+ repositoryId: external_exports.uuid(),
23125
+ status: external_exports.enum(BulkSetScanningBranchResultStatusValues),
23126
+ relabeledVulnerabilityCount: external_exports.number().int().min(0).optional(),
23127
+ historyId: external_exports.uuid().nullable().optional(),
23128
+ errorMessage: external_exports.string().optional()
23129
+ });
23130
+ var BulkSetScanningBranchResponseSchema = external_exports.object({
23131
+ results: external_exports.array(BulkSetScanningBranchResultSchema)
23132
+ });
23133
+ var ScanningBranchPreferenceSchema = external_exports.object({
23134
+ autoConfigureScanningBranch: external_exports.boolean()
23135
+ });
23136
+ var ConfirmScanningBranchDefaultsResponseSchema = external_exports.object({
23137
+ autoConfigureScanningBranch: external_exports.literal(true),
23138
+ /** Repos the sweep configured to their default-branch mirror. */
23139
+ configuredCount: external_exports.number().int().min(0),
23140
+ /**
23141
+ * Rows skipped by the sweep's domain guards (empty or >255-char mirror).
23142
+ * They stay NULL and keep the "waiting on a scanning branch" banner alive.
23143
+ */
23144
+ skippedCount: external_exports.number().int().min(0)
23145
+ });
23146
+
23147
+ // ../../packages/api-contracts/src/schemas/api/v1/application.api.ts
23148
+ var ApplicationTypeValues = ["WEB", "CLI", "MOBILE", "DESKTOP", "API_SERVICE"];
23149
+ var APPLICATION_NOTES_MAX_CHARS = 2e3;
23150
+ var ApplicationRepositoryRoleValues = [
23151
+ "FRONTEND",
23152
+ "BACKEND_API",
23153
+ "AUTH_SERVICE",
23154
+ "WORKER_JOB_SERVICE",
23155
+ "SHARED_PACKAGE_SDK",
23156
+ "INFRASTRUCTURE_IAC",
23157
+ "MOBILE_CLIENT",
23158
+ "MONOREPO",
23159
+ "OTHER"
23160
+ ];
23161
+ var ApplicationIdParamsSchema = OrgIdParamsSchema.extend({
23162
+ applicationId: external_exports.uuid()
23163
+ });
23164
+ var ApplicationRepositoryIdParamsSchema = ApplicationIdParamsSchema.extend({
23165
+ applicationRepositoryId: external_exports.uuid()
23166
+ });
23167
+ var ApplicationRepositorySummarySchema = external_exports.object({
23168
+ applicationRepositoryId: external_exports.uuid().nullable(),
23169
+ applicationId: external_exports.uuid(),
23170
+ organizationId: external_exports.uuid(),
23171
+ repositoryId: external_exports.uuid(),
23172
+ repositoryName: external_exports.string(),
23173
+ repositoryUrl: external_exports.string(),
23174
+ repositoryStatus: external_exports.enum(RepositoryStatusValues),
23175
+ htmlUrl: external_exports.string().nullable(),
23176
+ createdAt: external_exports.date(),
23177
+ updatedAt: external_exports.date()
23178
+ });
23179
+ var ApplicationRepositoryRolesSchema = external_exports.array(external_exports.enum(ApplicationRepositoryRoleValues)).max(ApplicationRepositoryRoleValues.length);
23180
+ var ApplicationRepositoryLinkResponseSchema = ApplicationRepositorySummarySchema.extend({
23181
+ // First of `roles` (enum order), or null when unspecified. Kept so a new
23182
+ // client reading a pre-this-release API during a rolling deploy still parses.
23183
+ role: external_exports.enum(ApplicationRepositoryRoleValues).nullable(),
23184
+ // Source of truth. Defaulted empty so a new client reading a pre-this-release
23185
+ // API that omitted the field doesn't reject the row; the client then falls
23186
+ // back to wrapping `role`.
23187
+ roles: ApplicationRepositoryRolesSchema.default([]),
23188
+ roleLabel: external_exports.string().max(120).nullable(),
23189
+ repositoryPath: external_exports.string().max(500).nullable(),
23190
+ scanEnabled: external_exports.boolean()
23191
+ });
23192
+ var ListApplicationRepositoryLinksResponseSchema = external_exports.array(
23193
+ ApplicationRepositoryLinkResponseSchema
23194
+ );
23195
+ var ApplicationResponseSchema = external_exports.object({
23196
+ applicationId: external_exports.uuid(),
23197
+ organizationId: external_exports.uuid(),
23198
+ name: external_exports.string(),
23199
+ // `.default('WEB')` keeps responses backward-compatible: a pre-P1.3 API that
23200
+ // never emitted `type` parses cleanly (existing apps are semantically WEB),
23201
+ // so a new frontend reading an old API during a mixed-version rollout doesn't
23202
+ // reject application rows.
23203
+ type: external_exports.enum(ApplicationTypeValues).default("WEB"),
23204
+ applicationUrl: external_exports.string().nullable(),
23205
+ // Customer-authored free-text context, any type ("Advanced → Notes").
23206
+ notes: external_exports.string().nullable(),
23207
+ helpCenterUrl: external_exports.string().nullable(),
23208
+ documentationUrl: external_exports.string().nullable(),
23209
+ repositories: external_exports.array(ApplicationRepositorySummarySchema),
23210
+ // Registrable domains RECON is authorized to discover subdomains under. The
23211
+ // Environments-tab panel hydrates from this payload (no client GET). Defaulted
23212
+ // (like `type`) so a new client reading a pre-this-release API during a rolling
23213
+ // deploy doesn't reject application rows that predate the field.
23214
+ // Signed S3 URL for the Overview screenshot. Defaulted null so a new client
23215
+ // reading a pre-this-release API during a rolling deploy doesn't reject rows
23216
+ // that omit the field. The raw S3 key is never on the wire.
23217
+ screenshotUrl: external_exports.url().nullable().default(null),
23218
+ // Defaulted null so a new client reading a pre-this-release API during a
23219
+ // rolling deploy doesn't reject application rows that omit the field.
23220
+ credentialsNudgeDismissedAt: external_exports.date().nullable().default(null),
23221
+ createdAt: external_exports.date(),
23222
+ updatedAt: external_exports.date()
23223
+ });
23224
+ var ListApplicationsResponseSchema = external_exports.array(ApplicationResponseSchema);
23225
+ var CreateApplicationRequestSchema = external_exports.object({
23226
+ name: external_exports.string().min(1).max(200),
23227
+ type: external_exports.enum(ApplicationTypeValues).default("WEB"),
23228
+ applicationUrl: external_exports.url().max(2048).optional(),
23229
+ notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).optional(),
23230
+ repositoryId: external_exports.uuid().optional(),
23231
+ repositoryPath: external_exports.string().max(500).optional(),
23232
+ helpCenterUrl: external_exports.url().max(2048).optional(),
23233
+ documentationUrl: external_exports.url().max(2048).optional()
23234
+ }).strict().refine((data) => !isUrlBearingApplicationType(data.type) || data.applicationUrl != null, {
23235
+ path: ["applicationUrl"],
23236
+ message: "A web or API application requires an application URL."
23237
+ }).refine((data) => isUrlBearingApplicationType(data.type) || data.applicationUrl == null, {
23238
+ path: ["applicationUrl"],
23239
+ message: "Only web or API applications can have an application URL."
23240
+ });
23241
+ var CreateApplicationRepositoryLinkRequestSchema = external_exports.object({
23242
+ repositoryId: external_exports.uuid(),
23243
+ // Legacy single-role write. Ignored when `roles` is also sent.
23244
+ role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
23245
+ roles: ApplicationRepositoryRolesSchema.optional(),
23246
+ roleLabel: external_exports.string().max(120).nullable().optional(),
23247
+ repositoryPath: external_exports.string().max(500).nullable().optional(),
23248
+ scanEnabled: external_exports.boolean().optional()
23249
+ }).strict();
23250
+ var UpdateApplicationRepositoryLinkRequestSchema = external_exports.object({
23251
+ // Legacy single-role write. Ignored when `roles` is also sent.
23252
+ role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
23253
+ roles: ApplicationRepositoryRolesSchema.optional(),
23254
+ roleLabel: external_exports.string().max(120).nullable().optional(),
23255
+ repositoryPath: external_exports.string().max(500).nullable().optional(),
23256
+ scanEnabled: external_exports.boolean().optional()
23257
+ }).strict();
23258
+ var UpdateApplicationRequestSchema = external_exports.object({
23259
+ name: external_exports.string().min(1).max(200).optional(),
23260
+ applicationUrl: external_exports.url().max(2048).optional(),
23261
+ notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).nullable().optional(),
23262
+ repositoryId: external_exports.uuid().nullable().optional(),
23263
+ repositoryPath: external_exports.string().max(500).nullable().optional(),
23264
+ helpCenterUrl: external_exports.url().max(2048).nullable().optional(),
23265
+ documentationUrl: external_exports.url().max(2048).nullable().optional()
23266
+ }).strict();
23267
+
23011
23268
  // ../../packages/api-contracts/src/schemas/api/v1/pentest-report-pdf.api.ts
23012
23269
  var ReportPdfPentestParamsSchema = OrgIdParamsSchema.extend({
23013
23270
  pentestId: external_exports.uuid()
@@ -23093,6 +23350,28 @@ var PartnerNarrativeJsonSchema = external_exports.object({
23093
23350
  notExploitable: external_exports.string().max(4e3).optional()
23094
23351
  })
23095
23352
  });
23353
+ var BskNarrativeSectionIdValues = [
23354
+ "engagement_context",
23355
+ "platform_and_data",
23356
+ "overall_assessment",
23357
+ "findings_overview",
23358
+ "target",
23359
+ "approach",
23360
+ "limitations",
23361
+ "not_exploitable"
23362
+ ];
23363
+ var BskNarrativeSectionId = external_exports.enum(BskNarrativeSectionIdValues);
23364
+ var TraceNarrativeSectionIdValues = [
23365
+ "executive_summary",
23366
+ "scope_summary",
23367
+ "key_themes"
23368
+ ];
23369
+ var ReportWriteSectionIdValues = [
23370
+ ...TraceNarrativeSectionIdValues,
23371
+ ...BskNarrativeSectionIdValues
23372
+ ];
23373
+ var ReportWriteSectionId = external_exports.enum(ReportWriteSectionIdValues);
23374
+ var REPORT_SECTION_CONTENT_MAX_CHARS = 4e3;
23096
23375
  var SeverityCountsSchema = external_exports.object({
23097
23376
  critical: external_exports.int().min(0),
23098
23377
  high: external_exports.int().min(0),
@@ -23415,6 +23694,8 @@ var ApplyReportSettingsRequestSchema = external_exports.object({
23415
23694
  includeRemediationTimeline: external_exports.boolean(),
23416
23695
  expectedUpdatedAt: external_exports.coerce.date().nullable()
23417
23696
  });
23697
+ var CustomerReportDownloadFormatValues = ["pdf", "bundle"];
23698
+ var CustomerReportDownloadFormatSchema = external_exports.enum(CustomerReportDownloadFormatValues);
23418
23699
  var CustomerReportPdfResponseSchema = ReportPdfResponseSchema.omit({
23419
23700
  organizationId: true,
23420
23701
  pentestId: true,
@@ -23446,7 +23727,14 @@ var CustomerReportPdfResponseSchema = ReportPdfResponseSchema.omit({
23446
23727
  * before the API's, so a new bundle briefly reads an old API's response, where
23447
23728
  * this field does not exist. Consumers default it to false.
23448
23729
  */
23449
- canViewInline: external_exports.boolean().optional()
23730
+ canViewInline: external_exports.boolean().optional(),
23731
+ /**
23732
+ * What the Download action hands the customer: the PDF alone, or one zip
23733
+ * carrying the PDF, the markdown report, and the evidence files (partner
23734
+ * templates whose tooling consumes the markdown). Preview always opens the
23735
+ * PDF. Optional for the deploy-order reason above; consumers default to 'pdf'.
23736
+ */
23737
+ downloadFormat: CustomerReportDownloadFormatSchema.optional()
23450
23738
  });
23451
23739
  var GetCustomerReportPdfResponseSchema = external_exports.object({
23452
23740
  report: CustomerReportPdfResponseSchema.nullable()
@@ -23566,6 +23854,12 @@ var IssuedReportSnapshotSchema = external_exports.object({
23566
23854
  * parses those rows for the changelog diff — a required field would throw
23567
23855
  * there and break issuing a new version of any pre-feature report. */
23568
23856
  testType: PentestTestType.optional(),
23857
+ /** Types of the applications bound at issuance: the archival record of which
23858
+ * OWASP families the delivered PDF named. Optional for the same reason as
23859
+ * `testType` above: a pre-feature snapshot has no value, and
23860
+ * `latestIssuedSnapshot` parses those rows for the changelog diff. Absent
23861
+ * re-renders as the web family, matching what those reports contain. */
23862
+ applicationTypes: external_exports.array(external_exports.enum(ApplicationTypeValues)).optional(),
23569
23863
  versionLabel: external_exports.string(),
23570
23864
  revisionCount: external_exports.int().min(1)
23571
23865
  }),
@@ -24390,15 +24684,34 @@ var StartProgressPentestFindingRequestSchema = external_exports.object({});
24390
24684
  var ReportRemediationPentestFindingRequestSchema = external_exports.object({
24391
24685
  note: external_exports.string().trim().min(1).max(1e4).optional()
24392
24686
  });
24687
+ var AutomationFindingTransitionSchema = external_exports.enum(["IN_PROGRESS", "REMEDIATED"]);
24688
+ var AutomationStatusUpdateRequestSchema = external_exports.object({
24689
+ status: AutomationFindingTransitionSchema,
24690
+ note: external_exports.string().trim().min(1).max(1e4).optional()
24691
+ }).refine((value) => value.note === void 0 || value.status === "REMEDIATED", {
24692
+ message: "note is only accepted when reporting remediation (status REMEDIATED)",
24693
+ path: ["note"]
24694
+ });
24393
24695
  var ReopenPentestFindingTargetStatusSchema = external_exports.enum(["OPEN", "IN_PROGRESS"]);
24394
24696
  var ReopenPentestFindingRequestSchema = external_exports.object({
24395
24697
  targetStatus: ReopenPentestFindingTargetStatusSchema,
24396
24698
  noteContent: external_exports.string().trim().min(1).max(1e4)
24397
24699
  });
24700
+ var retestVerificationOnlyOnFixed = (value, ctx) => {
24701
+ if (value.outcome !== "FIXED" && value.verification !== void 0) {
24702
+ ctx.addIssue({
24703
+ code: "custom",
24704
+ message: "verification report prose is only allowed when outcome is FIXED",
24705
+ path: ["verification"]
24706
+ });
24707
+ }
24708
+ };
24398
24709
  var CreatePentestFindingRetestRequestSchema = external_exports.object({
24399
24710
  outcome: ManualRetestOutcome,
24400
- notes: external_exports.string().trim().min(1).max(1e4)
24711
+ notes: external_exports.string().trim().min(1).max(1e4),
24712
+ verification: external_exports.string().trim().min(1).max(8e3).optional()
24401
24713
  });
24714
+ var CreatePentestFindingRetestBodySchema = CreatePentestFindingRetestRequestSchema.superRefine(retestVerificationOnlyOnFixed);
24402
24715
  var CreatePentestFindingNoteRequestSchema = external_exports.object({
24403
24716
  content: external_exports.string().min(1).max(1e4)
24404
24717
  });
@@ -24592,263 +24905,6 @@ var PromotePentestHypothesisRequestSchema = external_exports.object({
24592
24905
  manualFindingIds: HypothesisSourceIdsSchema.optional()
24593
24906
  }).strict().optional();
24594
24907
 
24595
- // ../../packages/api-contracts/src/schemas/api/v1/repository.api.ts
24596
- var PlatformValues = ["GITHUB", "GITLAB", "BITBUCKET", "UPLOAD"];
24597
- var RepositoryStatusValues = ["CONNECTED", "DISCONNECTED"];
24598
- var RepositoryIdParamsSchema = OrgIdParamsSchema.extend({
24599
- repositoryId: external_exports.uuid()
24600
- });
24601
- var CreateRepositoryRequestSchema = external_exports.object({
24602
- repositoryUrl: external_exports.url(),
24603
- platform: external_exports.enum(PlatformValues),
24604
- githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
24605
- status: external_exports.enum(RepositoryStatusValues).optional()
24606
- });
24607
- var UpdateRepositoryRequestSchema = external_exports.object({
24608
- repositoryUrl: external_exports.url().optional(),
24609
- platform: external_exports.enum(PlatformValues).optional(),
24610
- githubDefaultBranch: external_exports.string().min(1).max(255).optional(),
24611
- status: external_exports.enum(RepositoryStatusValues).optional()
24612
- });
24613
- var RepositoryResponseSchema = external_exports.object({
24614
- repositoryId: external_exports.uuid(),
24615
- organizationId: external_exports.uuid(),
24616
- repositoryUrl: external_exports.url(),
24617
- platform: external_exports.enum(PlatformValues),
24618
- status: external_exports.enum(RepositoryStatusValues),
24619
- githubDefaultBranch: external_exports.string(),
24620
- scanningBranch: external_exports.string().nullable(),
24621
- primaryLanguage: external_exports.string().nullable().optional(),
24622
- /** Staff-set opt-in: automated PR scans run on this repo even without a FULL SAST baseline. */
24623
- prScansEnabled: external_exports.boolean(),
24624
- createdAt: external_exports.date(),
24625
- updatedAt: external_exports.date()
24626
- });
24627
- var ListRepositoriesResponseSchema = external_exports.array(RepositoryResponseSchema);
24628
- var SetPrScansEnabledRequestSchema = external_exports.object({
24629
- enabled: external_exports.boolean()
24630
- });
24631
- var StaffRepositoryPrScanSettingSchema = external_exports.object({
24632
- repositoryId: external_exports.uuid(),
24633
- /** GitHub owner/name when synced; null for rows created before the sync backfill. */
24634
- fullName: external_exports.string().nullable(),
24635
- repositoryUrl: external_exports.url(),
24636
- /** The staff-set opt-in arm of the gate. */
24637
- prScansEnabled: external_exports.boolean(),
24638
- /**
24639
- * The implicit arm: a completed FULL SAST scan exists for this repo (any
24640
- * branch). With the org capability granted, either arm open means PR scans run.
24641
- */
24642
- hasSastBaseline: external_exports.boolean()
24643
- });
24644
- var StaffPrScanSettingsResponseSchema = external_exports.object({
24645
- /** Org-level gate: without AUTO_PR_SCANS the per-repo switches are inert. */
24646
- orgHasAutoPrScans: external_exports.boolean(),
24647
- repositories: external_exports.array(StaffRepositoryPrScanSettingSchema)
24648
- });
24649
- var CloneTokenRequestSchema = external_exports.object({
24650
- repositoryUrl: external_exports.string().url()
24651
- });
24652
- var CloneTokenResponseSchema = external_exports.object({
24653
- token: external_exports.string(),
24654
- expiresAt: external_exports.string().datetime(),
24655
- // Git username scheme to pair with this token. GitHub installation tokens
24656
- // use `x-access-token`; Bitbucket app tokens use `x-token-auth`. Optional
24657
- // for back-compat with CLIs that predate Bitbucket support and hardcode
24658
- // `x-access-token` (the correct value for the GitHub-only flow they gate on).
24659
- username: external_exports.enum(["x-access-token", "x-token-auth"]).optional()
24660
- });
24661
- var ScanningBranchHistoryEntrySchema = external_exports.object({
24662
- historyId: external_exports.uuid(),
24663
- branch: external_exports.string(),
24664
- configuredAt: external_exports.date(),
24665
- replacedAt: external_exports.date(),
24666
- configuredByUserId: external_exports.uuid().nullable()
24667
- });
24668
- var ScanningBranchStateSchema = external_exports.object({
24669
- scanningBranch: external_exports.string().nullable(),
24670
- githubDefaultBranch: external_exports.string(),
24671
- history: external_exports.array(ScanningBranchHistoryEntrySchema)
24672
- });
24673
- var SetScanningBranchRequestSchema = external_exports.object({
24674
- branch: external_exports.string().min(1).max(255),
24675
- migrateOpenVulnerabilities: external_exports.boolean(),
24676
- /**
24677
- * Optional compare-and-swap guard. When provided, the switch only commits
24678
- * if the repo's current `scanningBranch` matches. Mismatch → HTTP 409.
24679
- * `null` means "expect this repo to still be unconfigured."
24680
- */
24681
- expectedCurrentBranch: external_exports.string().nullable().optional()
24682
- });
24683
- var SetScanningBranchResponseSchema = external_exports.object({
24684
- previousBranch: external_exports.string().nullable(),
24685
- newBranch: external_exports.string(),
24686
- relabeledVulnerabilityCount: external_exports.number().int().min(0),
24687
- /** Null when previousBranch was null (initial configuration). */
24688
- historyId: external_exports.uuid().nullable()
24689
- });
24690
- var BulkSetScanningBranchBranchSchema = external_exports.discriminatedUnion("kind", [
24691
- external_exports.object({ kind: external_exports.literal("literal"), value: external_exports.string().min(1).max(255) }),
24692
- external_exports.object({ kind: external_exports.literal("github-default") })
24693
- ]);
24694
- var BulkSetScanningBranchRequestSchema = external_exports.object({
24695
- branch: BulkSetScanningBranchBranchSchema,
24696
- repositoryIds: external_exports.array(external_exports.uuid()).min(1).max(100),
24697
- migrateOpenVulnerabilities: external_exports.boolean()
24698
- });
24699
- var BulkSetScanningBranchResultStatusValues = [
24700
- "switched",
24701
- "branch-missing-on-github",
24702
- "forbidden",
24703
- "already-on-branch",
24704
- "not-found",
24705
- "error"
24706
- ];
24707
- var BulkSetScanningBranchResultSchema = external_exports.object({
24708
- repositoryId: external_exports.uuid(),
24709
- status: external_exports.enum(BulkSetScanningBranchResultStatusValues),
24710
- relabeledVulnerabilityCount: external_exports.number().int().min(0).optional(),
24711
- historyId: external_exports.uuid().nullable().optional(),
24712
- errorMessage: external_exports.string().optional()
24713
- });
24714
- var BulkSetScanningBranchResponseSchema = external_exports.object({
24715
- results: external_exports.array(BulkSetScanningBranchResultSchema)
24716
- });
24717
- var ScanningBranchPreferenceSchema = external_exports.object({
24718
- autoConfigureScanningBranch: external_exports.boolean()
24719
- });
24720
- var ConfirmScanningBranchDefaultsResponseSchema = external_exports.object({
24721
- autoConfigureScanningBranch: external_exports.literal(true),
24722
- /** Repos the sweep configured to their default-branch mirror. */
24723
- configuredCount: external_exports.number().int().min(0),
24724
- /**
24725
- * Rows skipped by the sweep's domain guards (empty or >255-char mirror).
24726
- * They stay NULL and keep the "waiting on a scanning branch" banner alive.
24727
- */
24728
- skippedCount: external_exports.number().int().min(0)
24729
- });
24730
-
24731
- // ../../packages/api-contracts/src/schemas/api/v1/application.api.ts
24732
- var ApplicationTypeValues = ["WEB", "CLI", "MOBILE", "DESKTOP", "API_SERVICE"];
24733
- var APPLICATION_NOTES_MAX_CHARS = 2e3;
24734
- var ApplicationRepositoryRoleValues = [
24735
- "FRONTEND",
24736
- "BACKEND_API",
24737
- "AUTH_SERVICE",
24738
- "WORKER_JOB_SERVICE",
24739
- "SHARED_PACKAGE_SDK",
24740
- "INFRASTRUCTURE_IAC",
24741
- "MOBILE_CLIENT",
24742
- "MONOREPO",
24743
- "OTHER"
24744
- ];
24745
- var ApplicationIdParamsSchema = OrgIdParamsSchema.extend({
24746
- applicationId: external_exports.uuid()
24747
- });
24748
- var ApplicationRepositoryIdParamsSchema = ApplicationIdParamsSchema.extend({
24749
- applicationRepositoryId: external_exports.uuid()
24750
- });
24751
- var ApplicationRepositorySummarySchema = external_exports.object({
24752
- applicationRepositoryId: external_exports.uuid().nullable(),
24753
- applicationId: external_exports.uuid(),
24754
- organizationId: external_exports.uuid(),
24755
- repositoryId: external_exports.uuid(),
24756
- repositoryName: external_exports.string(),
24757
- repositoryUrl: external_exports.string(),
24758
- repositoryStatus: external_exports.enum(RepositoryStatusValues),
24759
- htmlUrl: external_exports.string().nullable(),
24760
- createdAt: external_exports.date(),
24761
- updatedAt: external_exports.date()
24762
- });
24763
- var ApplicationRepositoryRolesSchema = external_exports.array(external_exports.enum(ApplicationRepositoryRoleValues)).max(ApplicationRepositoryRoleValues.length);
24764
- var ApplicationRepositoryLinkResponseSchema = ApplicationRepositorySummarySchema.extend({
24765
- // First of `roles` (enum order), or null when unspecified. Kept so a new
24766
- // client reading a pre-this-release API during a rolling deploy still parses.
24767
- role: external_exports.enum(ApplicationRepositoryRoleValues).nullable(),
24768
- // Source of truth. Defaulted empty so a new client reading a pre-this-release
24769
- // API that omitted the field doesn't reject the row; the client then falls
24770
- // back to wrapping `role`.
24771
- roles: ApplicationRepositoryRolesSchema.default([]),
24772
- roleLabel: external_exports.string().max(120).nullable(),
24773
- repositoryPath: external_exports.string().max(500).nullable(),
24774
- scanEnabled: external_exports.boolean()
24775
- });
24776
- var ListApplicationRepositoryLinksResponseSchema = external_exports.array(
24777
- ApplicationRepositoryLinkResponseSchema
24778
- );
24779
- var ApplicationResponseSchema = external_exports.object({
24780
- applicationId: external_exports.uuid(),
24781
- organizationId: external_exports.uuid(),
24782
- name: external_exports.string(),
24783
- // `.default('WEB')` keeps responses backward-compatible: a pre-P1.3 API that
24784
- // never emitted `type` parses cleanly (existing apps are semantically WEB),
24785
- // so a new frontend reading an old API during a mixed-version rollout doesn't
24786
- // reject application rows.
24787
- type: external_exports.enum(ApplicationTypeValues).default("WEB"),
24788
- applicationUrl: external_exports.string().nullable(),
24789
- // Customer-authored free-text context, any type ("Advanced → Notes").
24790
- notes: external_exports.string().nullable(),
24791
- helpCenterUrl: external_exports.string().nullable(),
24792
- documentationUrl: external_exports.string().nullable(),
24793
- repositories: external_exports.array(ApplicationRepositorySummarySchema),
24794
- // Registrable domains RECON is authorized to discover subdomains under. The
24795
- // Environments-tab panel hydrates from this payload (no client GET). Defaulted
24796
- // (like `type`) so a new client reading a pre-this-release API during a rolling
24797
- // deploy doesn't reject application rows that predate the field.
24798
- // Signed S3 URL for the Overview screenshot. Defaulted null so a new client
24799
- // reading a pre-this-release API during a rolling deploy doesn't reject rows
24800
- // that omit the field. The raw S3 key is never on the wire.
24801
- screenshotUrl: external_exports.url().nullable().default(null),
24802
- // Defaulted null so a new client reading a pre-this-release API during a
24803
- // rolling deploy doesn't reject application rows that omit the field.
24804
- credentialsNudgeDismissedAt: external_exports.date().nullable().default(null),
24805
- createdAt: external_exports.date(),
24806
- updatedAt: external_exports.date()
24807
- });
24808
- var ListApplicationsResponseSchema = external_exports.array(ApplicationResponseSchema);
24809
- var CreateApplicationRequestSchema = external_exports.object({
24810
- name: external_exports.string().min(1).max(200),
24811
- type: external_exports.enum(ApplicationTypeValues).default("WEB"),
24812
- applicationUrl: external_exports.url().max(2048).optional(),
24813
- notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).optional(),
24814
- repositoryId: external_exports.uuid().optional(),
24815
- repositoryPath: external_exports.string().max(500).optional(),
24816
- helpCenterUrl: external_exports.url().max(2048).optional(),
24817
- documentationUrl: external_exports.url().max(2048).optional()
24818
- }).strict().refine((data) => !isUrlBearingApplicationType(data.type) || data.applicationUrl != null, {
24819
- path: ["applicationUrl"],
24820
- message: "A web or API application requires an application URL."
24821
- }).refine((data) => isUrlBearingApplicationType(data.type) || data.applicationUrl == null, {
24822
- path: ["applicationUrl"],
24823
- message: "Only web or API applications can have an application URL."
24824
- });
24825
- var CreateApplicationRepositoryLinkRequestSchema = external_exports.object({
24826
- repositoryId: external_exports.uuid(),
24827
- // Legacy single-role write. Ignored when `roles` is also sent.
24828
- role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
24829
- roles: ApplicationRepositoryRolesSchema.optional(),
24830
- roleLabel: external_exports.string().max(120).nullable().optional(),
24831
- repositoryPath: external_exports.string().max(500).nullable().optional(),
24832
- scanEnabled: external_exports.boolean().optional()
24833
- }).strict();
24834
- var UpdateApplicationRepositoryLinkRequestSchema = external_exports.object({
24835
- // Legacy single-role write. Ignored when `roles` is also sent.
24836
- role: external_exports.enum(ApplicationRepositoryRoleValues).nullable().optional(),
24837
- roles: ApplicationRepositoryRolesSchema.optional(),
24838
- roleLabel: external_exports.string().max(120).nullable().optional(),
24839
- repositoryPath: external_exports.string().max(500).nullable().optional(),
24840
- scanEnabled: external_exports.boolean().optional()
24841
- }).strict();
24842
- var UpdateApplicationRequestSchema = external_exports.object({
24843
- name: external_exports.string().min(1).max(200).optional(),
24844
- applicationUrl: external_exports.url().max(2048).optional(),
24845
- notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).nullable().optional(),
24846
- repositoryId: external_exports.uuid().nullable().optional(),
24847
- repositoryPath: external_exports.string().max(500).nullable().optional(),
24848
- helpCenterUrl: external_exports.url().max(2048).nullable().optional(),
24849
- documentationUrl: external_exports.url().max(2048).nullable().optional()
24850
- }).strict();
24851
-
24852
24908
  // ../../packages/api-contracts/src/schemas/api/v1/pentest.api.ts
24853
24909
  var PentestIdParamsSchema = OrgIdParamsSchema.extend({
24854
24910
  pentestId: external_exports.string().min(1)
@@ -25289,13 +25345,13 @@ var StorageStateSchema = external_exports.object({
25289
25345
  } catch {
25290
25346
  return;
25291
25347
  }
25292
- s.cookies.forEach((c58, i2) => {
25293
- const d = c58.domain.replace(/^\./, "").toLowerCase();
25348
+ s.cookies.forEach((c59, i2) => {
25349
+ const d = c59.domain.replace(/^\./, "").toLowerCase();
25294
25350
  if (d !== host && !host.endsWith(`.${d}`)) {
25295
25351
  ctx.addIssue({
25296
25352
  code: "custom",
25297
25353
  path: ["cookies", i2, "domain"],
25298
- message: `cookie domain "${c58.domain}" is not the capture origin host "${host}" or a parent domain of it`
25354
+ message: `cookie domain "${c59.domain}" is not the capture origin host "${host}" or a parent domain of it`
25299
25355
  });
25300
25356
  }
25301
25357
  });
@@ -25993,7 +26049,19 @@ var AgentSessionLoginCodeResponseSchema = external_exports.object({
25993
26049
  var AgentSessionTotpCodeRequestSchema = external_exports.object({
25994
26050
  runVersion: external_exports.number().int().nonnegative(),
25995
26051
  /** Which account (by `Credential.label`); omit if exactly one is enrolled. */
25996
- credentialLabel: external_exports.string().min(1).max(200).optional()
26052
+ credentialLabel: external_exports.string().min(1).max(200).optional(),
26053
+ /**
26054
+ * Which account by ID, which is what a DESKTOP session holds.
26055
+ *
26056
+ * `Credential.label` is unique per ENVIRONMENT, not per pentest, so an
26057
+ * engagement spanning staging and production can carry two accounts labelled
26058
+ * `admin` and the label identifies neither. The desktop credential catalog
26059
+ * hands the agent an unambiguous id, and without this the only way to use an
26060
+ * enrolled desktop account was to ask staff to relabel one mid-engagement.
26061
+ *
26062
+ * Wins over `credentialLabel` when both are given.
26063
+ */
26064
+ credentialId: external_exports.uuid().optional()
25997
26065
  });
25998
26066
  var AgentSessionTotpCodeResponseSchema = external_exports.object({
25999
26067
  /** The account the code belongs to, echoed so the agent can name it. */
@@ -26393,17 +26461,9 @@ var OperatorRecordFindingRetestRequestSchema = CreatePentestFindingRetestRequest
26393
26461
  runVersion: operatorRunVersion,
26394
26462
  reason: operatorReason,
26395
26463
  pentestFindingId: external_exports.uuid(),
26396
- outcome: RetestOutcome,
26397
- verification: external_exports.string().min(1).max(8e3).optional()
26398
- }).superRefine((v, ctx) => {
26399
- if (v.outcome !== "FIXED" && v.verification !== void 0) {
26400
- ctx.addIssue({
26401
- code: "custom",
26402
- message: "verification report prose is only allowed when outcome is FIXED",
26403
- path: ["verification"]
26404
- });
26405
- }
26406
- });
26464
+ // Widened from the dashboard's 3 values; `verification` comes from the base.
26465
+ outcome: RetestOutcome
26466
+ }).superRefine(retestVerificationOnlyOnFixed);
26407
26467
  var OperatorRetestAckSchema = OperatorFindingReadSchema.extend({
26408
26468
  retestId: external_exports.uuid()
26409
26469
  });
@@ -26564,7 +26624,21 @@ var ReportSessionCoverSchema = external_exports.object({
26564
26624
  classification: AttestationClassification,
26565
26625
  documentId: external_exports.string(),
26566
26626
  testingWindowStart: external_exports.string().nullable(),
26567
- testingWindowEnd: external_exports.string().nullable()
26627
+ testingWindowEnd: external_exports.string().nullable(),
26628
+ /**
26629
+ * The engagement approach in the exact words the rendered document prints
26630
+ * ("white-box" / "authenticated grey-box" / "black-box", from the pentest's
26631
+ * `testType`).
26632
+ *
26633
+ * Here because the agent writing an Approach section otherwise cannot know it,
26634
+ * while the BSK document's methodology appendix prints it three paragraphs
26635
+ * later — one page apart and flatly contradictory in a partner deliverable.
26636
+ *
26637
+ * Optional for the reason the whole view is: the host reads this response with
26638
+ * a raw cast and no validation, so a host running against an older api would
26639
+ * read a required-typed field as `undefined`.
26640
+ */
26641
+ approachLabel: external_exports.string().optional()
26568
26642
  });
26569
26643
  var ReportSessionViewSchema = external_exports.object({
26570
26644
  rendered: external_exports.boolean(),
@@ -26575,7 +26649,19 @@ var ReportSessionViewSchema = external_exports.object({
26575
26649
  keyThemes: external_exports.array(KeyThemeSchema)
26576
26650
  }),
26577
26651
  scopeRows: external_exports.array(ScopeRowSchema),
26578
- updatedAt: external_exports.string().nullable()
26652
+ updatedAt: external_exports.string().nullable(),
26653
+ /** Which template this org's report renders with. Absent = TRACE (older api). */
26654
+ reportTemplate: PentestReportTemplateSchema.optional(),
26655
+ /**
26656
+ * The BSK partner narrative as stored; null when nothing is written, absent on
26657
+ * a TRACE org (or an older api).
26658
+ *
26659
+ * A section key ABSENT from `sections` has not been written yet. That is the
26660
+ * BSK agent's only channel for "which of my eight sections already exist", and
26661
+ * every write returns this view, so a follow-up or resumed session reads it
26662
+ * back rather than re-authoring all eight.
26663
+ */
26664
+ partnerNarrative: PartnerNarrativeJsonSchema.nullable().optional()
26579
26665
  });
26580
26666
  var reportRunVersion = external_exports.number().int().nonnegative();
26581
26667
  var reportReason = external_exports.string().min(1).max(2e3);
@@ -26587,8 +26673,8 @@ var ReportWriteSectionRequestSchema = external_exports.object({
26587
26673
  runVersion: reportRunVersion,
26588
26674
  reason: reportReason,
26589
26675
  expectedUpdatedAt: reportExpectedUpdatedAt,
26590
- section: external_exports.enum(["executive_summary", "scope_summary", "key_themes"]),
26591
- content: external_exports.string().min(1).max(2e3).optional(),
26676
+ section: ReportWriteSectionId,
26677
+ content: external_exports.string().min(1).max(REPORT_SECTION_CONTENT_MAX_CHARS).optional(),
26592
26678
  themes: external_exports.array(KeyThemeSchema).max(4).optional()
26593
26679
  });
26594
26680
  var ReportUpdateScopeRequestSchema = external_exports.object({
@@ -26602,13 +26688,24 @@ var RequestDesktopTargetRequestSchema = external_exports.object({
26602
26688
  /** Only Windows exists; a literal keeps the macOS follow-on additive. */
26603
26689
  platform: external_exports.literal("WINDOWS")
26604
26690
  });
26691
+ var DesktopCredentialRefSchema = external_exports.object({
26692
+ credentialId: external_exports.uuid(),
26693
+ label: external_exports.string(),
26694
+ credentialType: external_exports.enum(CredentialTypeValues),
26695
+ environmentId: external_exports.uuid(),
26696
+ /** Present when the account has a second factor enrolled. `get_totp_code`
26697
+ * resolves by LABEL, which is not unique per pentest, so an enrolled desktop
26698
+ * account would otherwise dead-end. */
26699
+ mfaKind: CredentialMfaKind.nullable()
26700
+ });
26605
26701
  var RequestDesktopTargetResponseSchema = external_exports.object({
26606
26702
  desktopTargetId: external_exports.uuid(),
26607
26703
  status: external_exports.enum(DesktopTargetStatusValues),
26608
26704
  /** True when this session already owned a live box, so a second call in one
26609
26705
  * assistant turn cannot bill a second instance. */
26610
26706
  reused: external_exports.boolean(),
26611
- screen: external_exports.object({ width: external_exports.number().int().positive(), height: external_exports.number().int().positive() })
26707
+ screen: external_exports.object({ width: external_exports.number().int().positive(), height: external_exports.number().int().positive() }),
26708
+ credentials: external_exports.array(DesktopCredentialRefSchema)
26612
26709
  });
26613
26710
  var DesktopTargetStatusRequestSchema = external_exports.object({
26614
26711
  runVersion: external_exports.number().int().min(0),
@@ -26654,7 +26751,15 @@ var DesktopActionViewSchema = external_exports.object({
26654
26751
  * so a caller-chosen name is how an unredacted clip would publish as a
26655
26752
  * customer-facing screenshot.
26656
26753
  */
26657
- artifactName: external_exports.string().max(256).nullable()
26754
+ artifactName: external_exports.string().max(256).nullable(),
26755
+ /**
26756
+ * Shape-only reason a FAILED action carries. Load-bearing for `type_secret`:
26757
+ * claim-time substitution fails the action with one of three codes
26758
+ * (`credential_not_found`, `credential_field_absent`, `decrypt_failed`), and
26759
+ * without this projection the agent could not tell those apart from a box
26760
+ * that crashed.
26761
+ */
26762
+ failureDetails: external_exports.string().nullable()
26658
26763
  });
26659
26764
  var ReadDesktopActionRequestSchema = external_exports.object({
26660
26765
  runVersion: external_exports.number().int().min(0),
@@ -31977,7 +32082,8 @@ var OrgCapabilityValues = [
31977
32082
  "SCAN_SECRETS",
31978
32083
  "SCAN_DAST",
31979
32084
  "AUTO_PR_SCANS",
31980
- "AUTO_PUSH_SCANS"
32085
+ "AUTO_PUSH_SCANS",
32086
+ "PENTEST_FINDING_AUTOMATION"
31981
32087
  ];
31982
32088
  var UpdateOrganizationRequestSchema = external_exports.object({
31983
32089
  name: external_exports.string().min(1).max(255).optional(),
@@ -34270,6 +34376,28 @@ var pentestFindingContract = c35.router({
34270
34376
  500: ErrorResponseSchema
34271
34377
  }
34272
34378
  },
34379
+ // ─── Automation lifecycle transition (API keys) ───
34380
+ // A separate route rather than a widened `start-progress` / `report-remediation`:
34381
+ // those stay human-only, and everything that makes a machine-driven write
34382
+ // different lives here. API-key principals only, gated on the org owning
34383
+ // PENTEST_FINDING_AUTOMATION, and audited as API_KEY with the key's name.
34384
+ automationStatusUpdate: {
34385
+ method: "POST",
34386
+ path: "/organizations/:organizationId/customer-pentests/:pentestId/findings/:pentestFindingId/automation/status",
34387
+ pathParams: CustomerPentestFindingIdParamsSchema,
34388
+ body: AutomationStatusUpdateRequestSchema,
34389
+ responses: {
34390
+ 200: CustomerPentestFindingResponseSchema,
34391
+ 400: ErrorResponseSchema,
34392
+ 401: ErrorResponseSchema,
34393
+ 403: ErrorResponseSchema,
34394
+ 404: ErrorResponseSchema,
34395
+ // FINDING_TRANSITION_NOT_ALLOWED (bad source status), FINDING_STALE
34396
+ // (concurrent write), or PENTEST_CLOSED.
34397
+ 409: ErrorResponseSchema,
34398
+ 500: ErrorResponseSchema
34399
+ }
34400
+ },
34273
34401
  // Customer opens a dispute (PR 3) → finding status CONTESTED. Same auth as the
34274
34402
  // other customer transitions (VIEW_RESULTS + user principal + customer visibility).
34275
34403
  contest: {
@@ -34362,7 +34490,7 @@ var pentestFindingContract = c35.router({
34362
34490
  method: "POST",
34363
34491
  path: "/organizations/:organizationId/pentests/:pentestId/findings/:pentestFindingId/retests",
34364
34492
  pathParams: PentestFindingIdParamsSchema,
34365
- body: CreatePentestFindingRetestRequestSchema,
34493
+ body: CreatePentestFindingRetestBodySchema,
34366
34494
  responses: {
34367
34495
  201: PentestFindingRetestResponseSchema,
34368
34496
  400: ErrorResponseSchema,
@@ -35466,6 +35594,128 @@ var staffPentestStatsContract = c42.router({
35466
35594
  }
35467
35595
  });
35468
35596
 
35597
+ // ../../packages/api-contracts/src/schemas/api/v1/staff-queue.api.ts
35598
+ var StaffQueueItemKindValues = [
35599
+ "RETEST_OWED",
35600
+ "CONTESTED",
35601
+ "SESSION_WAITING",
35602
+ "SESSION_FAILED",
35603
+ "REVIEW_GATE",
35604
+ "INTAKE_SUBMITTED"
35605
+ ];
35606
+ var StaffQueueItemKind = external_exports.enum(StaffQueueItemKindValues);
35607
+ var STAFF_QUEUE_EXCERPT_MAX = 280;
35608
+ var since = external_exports.iso.datetime();
35609
+ var findingIdentity = {
35610
+ pentestFindingId: external_exports.uuid(),
35611
+ /** Null until published; the finding is then named by title alone. */
35612
+ displayId: external_exports.int().positive().nullable(),
35613
+ title: external_exports.string(),
35614
+ severity: PentestFindingSeverity,
35615
+ /** False for a finding the customer has never seen; they are not the one waiting. */
35616
+ published: external_exports.boolean()
35617
+ };
35618
+ var StaffQueueRetestOwedItemSchema = external_exports.object({
35619
+ kind: external_exports.literal("RETEST_OWED"),
35620
+ since,
35621
+ ...findingIdentity,
35622
+ /** The most recent automatic retest, when one ran and did not settle it. */
35623
+ lastAutoRetest: external_exports.object({ outcome: RetestOutcome, testedAt: external_exports.iso.datetime() }).nullable()
35624
+ }).strict();
35625
+ var StaffQueueContestedItemSchema = external_exports.object({
35626
+ kind: external_exports.literal("CONTESTED"),
35627
+ since,
35628
+ ...findingIdentity,
35629
+ /** The open contest row. Null only if a finding is CONTESTED with no open row. */
35630
+ contest: external_exports.object({
35631
+ reason: ContestReason,
35632
+ justification: external_exports.string().max(STAFF_QUEUE_EXCERPT_MAX),
35633
+ contestedBy: external_exports.string()
35634
+ }).strict().nullable()
35635
+ }).strict();
35636
+ var StaffQueueSessionWaitingItemSchema = external_exports.object({
35637
+ kind: external_exports.literal("SESSION_WAITING"),
35638
+ since,
35639
+ agentSessionId: external_exports.uuid(),
35640
+ sessionType: AgentSessionType,
35641
+ waitingReason: AgentSessionWaitingReason.nullable(),
35642
+ /** The console's session list names sessions by objective, so the row carries it. */
35643
+ objective: external_exports.string().max(STAFF_QUEUE_EXCERPT_MAX),
35644
+ /** The agent's question when the park carries one. */
35645
+ question: external_exports.string().max(STAFF_QUEUE_EXCERPT_MAX).nullable()
35646
+ }).strict();
35647
+ var StaffQueueSessionFailedItemSchema = external_exports.object({
35648
+ kind: external_exports.literal("SESSION_FAILED"),
35649
+ since,
35650
+ agentSessionId: external_exports.uuid(),
35651
+ sessionType: AgentSessionType,
35652
+ objective: external_exports.string().max(STAFF_QUEUE_EXCERPT_MAX),
35653
+ failureReason: AgentSessionFailureReason.nullable()
35654
+ }).strict();
35655
+ var StaffQueueReviewGateItemSchema = external_exports.object({
35656
+ kind: external_exports.literal("REVIEW_GATE"),
35657
+ since,
35658
+ stage: PentestStage
35659
+ }).strict();
35660
+ var StaffQueueIntakeSubmittedItemSchema = external_exports.object({
35661
+ kind: external_exports.literal("INTAKE_SUBMITTED"),
35662
+ since
35663
+ }).strict();
35664
+ var StaffQueueItemSchema = external_exports.discriminatedUnion("kind", [
35665
+ StaffQueueRetestOwedItemSchema,
35666
+ StaffQueueContestedItemSchema,
35667
+ StaffQueueSessionWaitingItemSchema,
35668
+ StaffQueueSessionFailedItemSchema,
35669
+ StaffQueueReviewGateItemSchema,
35670
+ StaffQueueIntakeSubmittedItemSchema
35671
+ ]);
35672
+ var StaffQueueEngagementSchema = external_exports.object({
35673
+ organization: external_exports.object({
35674
+ organizationId: external_exports.uuid(),
35675
+ slug: external_exports.string(),
35676
+ name: external_exports.string(),
35677
+ logoUrl: external_exports.string().nullable(),
35678
+ darkModeLogoUrl: external_exports.string().nullable()
35679
+ }).strict(),
35680
+ pentest: external_exports.object({
35681
+ pentestId: external_exports.uuid(),
35682
+ displayId: external_exports.int().positive(),
35683
+ title: external_exports.string(),
35684
+ status: PentestStatus,
35685
+ currentStage: PentestStage
35686
+ }).strict(),
35687
+ /** Oldest first within the engagement. */
35688
+ items: external_exports.array(StaffQueueItemSchema).min(1),
35689
+ /** The `since` of the oldest item; engagements sort by it ascending. */
35690
+ oldestSince: external_exports.iso.datetime()
35691
+ }).strict();
35692
+ var StaffQueueCountsSchema = external_exports.object(
35693
+ Object.fromEntries(StaffQueueItemKindValues.map((kind) => [kind, external_exports.int().nonnegative()]))
35694
+ ).strict();
35695
+ var StaffQueueResponseSchema = external_exports.object({
35696
+ generatedAt: external_exports.iso.datetime(),
35697
+ /** Non-deleted, non-closed pentests considered, so an empty queue can prove the query ran. */
35698
+ liveEngagementCount: external_exports.int().nonnegative(),
35699
+ counts: StaffQueueCountsSchema,
35700
+ engagements: external_exports.array(StaffQueueEngagementSchema)
35701
+ }).strict();
35702
+
35703
+ // ../../packages/api-contracts/src/contracts/v1/staff-queue.ts
35704
+ var c43 = initContract();
35705
+ var staffQueueContract = c43.router({
35706
+ getStaffQueue: {
35707
+ method: "GET",
35708
+ path: "/staff/queue",
35709
+ responses: {
35710
+ 200: StaffQueueResponseSchema,
35711
+ 401: ErrorResponseSchema,
35712
+ 403: ErrorResponseSchema,
35713
+ 500: ErrorResponseSchema
35714
+ },
35715
+ summary: "Engagements where the next move is staff\u2019s, grouped by engagement"
35716
+ }
35717
+ });
35718
+
35469
35719
  // ../../packages/api-contracts/src/schemas/api/v1/test-integration.api.ts
35470
35720
  var NOTES_MAX = 2e3;
35471
35721
  var TestIntegrationIdParamsSchema = external_exports.object({
@@ -35522,8 +35772,8 @@ var AttachTestIntegrationRequestSchema = external_exports.object({
35522
35772
  }).strict();
35523
35773
 
35524
35774
  // ../../packages/api-contracts/src/contracts/v1/test-integration.ts
35525
- var c43 = initContract();
35526
- var testIntegrationContract = c43.router({
35775
+ var c44 = initContract();
35776
+ var testIntegrationContract = c44.router({
35527
35777
  // -- Fixture CRUD (org-less, staff-only) ----------------------------------
35528
35778
  listTestIntegrations: {
35529
35779
  method: "GET",
@@ -35655,8 +35905,8 @@ var MyContextResponseSchema = external_exports.object({
35655
35905
  });
35656
35906
 
35657
35907
  // ../../packages/api-contracts/src/contracts/v1/user.ts
35658
- var c44 = initContract();
35659
- var userContract = c44.router({
35908
+ var c45 = initContract();
35909
+ var userContract = c45.router({
35660
35910
  getStaffProfile: {
35661
35911
  method: "GET",
35662
35912
  path: "/staff/profile",
@@ -35771,8 +36021,8 @@ var VantaIntegrationResponseSchema = external_exports.object({
35771
36021
  });
35772
36022
 
35773
36023
  // ../../packages/api-contracts/src/contracts/v1/vanta-integration.ts
35774
- var c45 = initContract();
35775
- var vantaIntegrationContract = c45.router({
36024
+ var c46 = initContract();
36025
+ var vantaIntegrationContract = c46.router({
35776
36026
  createVantaIntegration: {
35777
36027
  method: "POST",
35778
36028
  path: "/organizations/:organizationId/vanta-integration",
@@ -36104,8 +36354,8 @@ var VerifySharedVulnerabilityEmailCodeResponseSchema = external_exports.object({
36104
36354
  });
36105
36355
 
36106
36356
  // ../../packages/api-contracts/src/contracts/v1/vulnerability.ts
36107
- var c46 = initContract();
36108
- var vulnerabilityContract = c46.router({
36357
+ var c47 = initContract();
36358
+ var vulnerabilityContract = c47.router({
36109
36359
  filterVulnerabilities: {
36110
36360
  method: "POST",
36111
36361
  path: "/organizations/:organizationId/vulnerabilities/filter",
@@ -36313,8 +36563,8 @@ var UpdateVulnerabilityNoteRequestSchema = external_exports.object({
36313
36563
  });
36314
36564
 
36315
36565
  // ../../packages/api-contracts/src/contracts/v1/vulnerability-note.ts
36316
- var c47 = initContract();
36317
- var vulnerabilityNoteContract = c47.router({
36566
+ var c48 = initContract();
36567
+ var vulnerabilityNoteContract = c48.router({
36318
36568
  listNotes: {
36319
36569
  method: "GET",
36320
36570
  path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/notes",
@@ -36495,8 +36745,8 @@ var ListWebhookDeliveriesResponseSchema = external_exports.object({
36495
36745
  });
36496
36746
 
36497
36747
  // ../../packages/api-contracts/src/contracts/v1/webhook-settings.ts
36498
- var c48 = initContract();
36499
- var webhookSettingsContract = c48.router({
36748
+ var c49 = initContract();
36749
+ var webhookSettingsContract = c49.router({
36500
36750
  listWebhookEndpoints: {
36501
36751
  method: "GET",
36502
36752
  path: "/organizations/:organizationId/webhook-settings/endpoints",
@@ -36634,8 +36884,8 @@ var webhookSettingsContract = c48.router({
36634
36884
  });
36635
36885
 
36636
36886
  // ../../packages/api-contracts/src/contracts/v1/index.ts
36637
- var c49 = initContract();
36638
- var v1Contract = c49.router(
36887
+ var c50 = initContract();
36888
+ var v1Contract = c50.router(
36639
36889
  {
36640
36890
  admin: adminContract,
36641
36891
  cloudIntegration: cloudIntegrationContract,
@@ -36684,7 +36934,8 @@ var v1Contract = c49.router(
36684
36934
  engagement: engagementContract,
36685
36935
  testIntegration: testIntegrationContract,
36686
36936
  pentestEgress: pentestEgressContract,
36687
- staffPentestStats: staffPentestStatsContract
36937
+ staffPentestStats: staffPentestStatsContract,
36938
+ staffQueue: staffQueueContract
36688
36939
  },
36689
36940
  {
36690
36941
  pathPrefix: "/v1"
@@ -36692,8 +36943,8 @@ var v1Contract = c49.router(
36692
36943
  );
36693
36944
 
36694
36945
  // ../../packages/api-contracts/src/contracts/index.ts
36695
- var c50 = initContract();
36696
- var contract = c50.router({
36946
+ var c51 = initContract();
36947
+ var contract = c51.router({
36697
36948
  v1: v1Contract
36698
36949
  });
36699
36950
 
@@ -36703,8 +36954,8 @@ var GitHubWebhookResponseSchema = external_exports.object({
36703
36954
  });
36704
36955
 
36705
36956
  // ../../packages/api-contracts/src/contracts/webhooks/github.ts
36706
- var c51 = initContract();
36707
- var githubWebhookContract = c51.router(
36957
+ var c52 = initContract();
36958
+ var githubWebhookContract = c52.router(
36708
36959
  {
36709
36960
  handleWebhook: {
36710
36961
  method: "POST",
@@ -36722,7 +36973,7 @@ var githubWebhookContract = c51.router(
36722
36973
  pathPrefix: "/webhooks"
36723
36974
  }
36724
36975
  );
36725
- var githubReadonlyWebhookContract = c51.router(
36976
+ var githubReadonlyWebhookContract = c52.router(
36726
36977
  {
36727
36978
  handleWebhook: {
36728
36979
  method: "POST",
@@ -36742,9 +36993,9 @@ var githubReadonlyWebhookContract = c51.router(
36742
36993
  );
36743
36994
 
36744
36995
  // ../../packages/api-contracts/src/contracts/webhooks/linear.ts
36745
- var c52 = initContract();
36996
+ var c53 = initContract();
36746
36997
  var LinearWebhookResponseSchema = external_exports.object({ ok: external_exports.boolean() });
36747
- var linearWebhookContract = c52.router(
36998
+ var linearWebhookContract = c53.router(
36748
36999
  {
36749
37000
  handleWebhook: {
36750
37001
  method: "POST",
@@ -36764,7 +37015,7 @@ var linearWebhookContract = c52.router(
36764
37015
  );
36765
37016
 
36766
37017
  // ../../packages/api-contracts/src/contracts/forge/bitbucket.ts
36767
- var c53 = initContract();
37018
+ var c54 = initContract();
36768
37019
  var InstallEventSchema = external_exports.object({
36769
37020
  eventType: external_exports.enum(["avi:forge:installed:app", "avi:forge:upgraded:app"]),
36770
37021
  context: external_exports.object({ cloudId: external_exports.string().min(1) }).loose(),
@@ -36793,7 +37044,7 @@ var ForgePairingCodeResponseSchema = external_exports.discriminatedUnion("state"
36793
37044
  expiresInSeconds: external_exports.number().int()
36794
37045
  })
36795
37046
  ]);
36796
- var forgeBitbucketContract = c53.router(
37047
+ var forgeBitbucketContract = c54.router(
36797
37048
  {
36798
37049
  lifecycle: {
36799
37050
  method: "POST",
@@ -36840,8 +37091,8 @@ var HealthResponseSchema = external_exports.object({
36840
37091
  });
36841
37092
 
36842
37093
  // ../../packages/api-contracts/src/contracts/health.ts
36843
- var c54 = initContract();
36844
- var healthContract = c54.router({
37094
+ var c55 = initContract();
37095
+ var healthContract = c55.router({
36845
37096
  getHealth: {
36846
37097
  method: "GET",
36847
37098
  path: "/health",
@@ -36853,8 +37104,8 @@ var healthContract = c54.router({
36853
37104
  });
36854
37105
 
36855
37106
  // ../../packages/api-contracts/src/contracts/v1/vulnerability-share.ts
36856
- var c55 = initContract();
36857
- var vulnerabilityShareContract = c55.router(
37107
+ var c56 = initContract();
37108
+ var vulnerabilityShareContract = c56.router(
36858
37109
  {
36859
37110
  resolveShareLink: {
36860
37111
  method: "GET",
@@ -36941,8 +37192,8 @@ var UpdatePrVulnerabilityRequestSchema = external_exports.object({
36941
37192
  });
36942
37193
 
36943
37194
  // ../../packages/api-contracts/src/contracts/v1/pr-vulnerability.ts
36944
- var c56 = initContract();
36945
- var prVulnerabilityContract = c56.router(
37195
+ var c57 = initContract();
37196
+ var prVulnerabilityContract = c57.router(
36946
37197
  {
36947
37198
  listPrVulnerabilities: {
36948
37199
  method: "GET",
@@ -37811,6 +38062,10 @@ function getApiBaseUrl() {
37811
38062
  }
37812
38063
  return raw.replace(/\/+$/, "");
37813
38064
  }
38065
+ function requireAuth() {
38066
+ const credential = loadCredentialOrExit();
38067
+ return { token: credential.token, kind: credential.kind };
38068
+ }
37814
38069
  function loadCredentialOrExit() {
37815
38070
  const credential = resolveCredentialOrExit();
37816
38071
  if (!credential) {
@@ -39646,12 +39901,12 @@ function buildApplicationsTable(apps) {
39646
39901
  repos: String(a2.repositories.length),
39647
39902
  url: a2.applicationUrl ? sanitizeDisplay(a2.applicationUrl) : "\u2014"
39648
39903
  }));
39649
- const idWidth = Math.max(2, ...cells.map((c58) => c58.id.length));
39650
- const nameWidth = Math.max(4, ...cells.map((c58) => c58.name.length));
39651
- const typeWidth = Math.max(4, ...cells.map((c58) => c58.type.length));
39904
+ const idWidth = Math.max(2, ...cells.map((c59) => c59.id.length));
39905
+ const nameWidth = Math.max(4, ...cells.map((c59) => c59.name.length));
39906
+ const typeWidth = Math.max(4, ...cells.map((c59) => c59.type.length));
39652
39907
  const header = `${"ID".padEnd(idWidth)} ${"NAME".padEnd(nameWidth)} ${"TYPE".padEnd(typeWidth)} REPOS URL`;
39653
39908
  const rows = cells.map(
39654
- (c58) => `${c58.id.padEnd(idWidth)} ${c58.name.padEnd(nameWidth)} ${c58.type.padEnd(typeWidth)} ${c58.repos.padStart(5)} ${c58.url}`
39909
+ (c59) => `${c59.id.padEnd(idWidth)} ${c59.name.padEnd(nameWidth)} ${c59.type.padEnd(typeWidth)} ${c59.repos.padStart(5)} ${c59.url}`
39655
39910
  );
39656
39911
  return { header, rows };
39657
39912
  }
@@ -39671,12 +39926,12 @@ function buildApplicationRepositoriesTable(links) {
39671
39926
  path: l2.repositoryPath ? sanitizeDisplay(l2.repositoryPath) : "\u2014",
39672
39927
  status: formatStatus(l2.repositoryStatus)
39673
39928
  }));
39674
- const nameWidth = Math.max(10, ...cells.map((c58) => c58.name.length));
39675
- const roleWidth = Math.max(4, ...cells.map((c58) => c58.role.length));
39676
- const pathWidth = Math.max(4, ...cells.map((c58) => c58.path.length));
39929
+ const nameWidth = Math.max(10, ...cells.map((c59) => c59.name.length));
39930
+ const roleWidth = Math.max(4, ...cells.map((c59) => c59.role.length));
39931
+ const pathWidth = Math.max(4, ...cells.map((c59) => c59.path.length));
39677
39932
  const header = `${"REPOSITORY".padEnd(nameWidth)} SCAN ${"ROLE".padEnd(roleWidth)} ${"PATH".padEnd(pathWidth)} STATUS`;
39678
39933
  const rows = cells.map(
39679
- (c58) => `${c58.name.padEnd(nameWidth)} ${c58.scan.padEnd(4)} ${c58.role.padEnd(roleWidth)} ${c58.path.padEnd(pathWidth)} ${c58.status}`
39934
+ (c59) => `${c59.name.padEnd(nameWidth)} ${c59.scan.padEnd(4)} ${c59.role.padEnd(roleWidth)} ${c59.path.padEnd(pathWidth)} ${c59.status}`
39680
39935
  );
39681
39936
  return { header, rows };
39682
39937
  }
@@ -40461,8 +40716,8 @@ function wrapTextWithPrefix(e, r2, o2, t2 = o2, s = o2, n3) {
40461
40716
  hard: true,
40462
40717
  trim: false
40463
40718
  }).split(`
40464
- `).map((c58, i2, m2) => {
40465
- const d = n3 ? n3(c58, i2) : c58;
40719
+ `).map((c59, i2, m2) => {
40720
+ const d = n3 ? n3(c59, i2) : c59;
40466
40721
  return i2 === 0 ? `${t2}${d}` : i2 === m2.length - 1 ? `${s}${d}` : `${o2}${d}`;
40467
40722
  }).join(`
40468
40723
  `);
@@ -40960,14 +41215,14 @@ var limitOptions = ({
40960
41215
  Math.min(l2 - a2 + 3, e.length - a2),
40961
41216
  0
40962
41217
  ));
40963
- let d = a2 < e.length && f > 0, c58 = a2 < e.length && f + a2 < e.length;
41218
+ let d = a2 < e.length && f > 0, c59 = a2 < e.length && f + a2 < e.length;
40964
41219
  const W = Math.min(
40965
41220
  f + a2,
40966
41221
  e.length
40967
41222
  ), s = [];
40968
41223
  let g = 0;
40969
- d && g++, c58 && g++;
40970
- const T = f + (d ? 1 : 0), y = W - (c58 ? 1 : 0);
41224
+ d && g++, c59 && g++;
41225
+ const T = f + (d ? 1 : 0), y = W - (c59 ? 1 : 0);
40971
41226
  for (let t2 = T; t2 < y; t2++) {
40972
41227
  const n3 = e[t2], o2 = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o2, i2, {
40973
41228
  hard: true,
@@ -40988,14 +41243,14 @@ var limitOptions = ({
40988
41243
  u4,
40989
41244
  true
40990
41245
  );
40991
- d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u4 && (c58 || (u4 -= 1), { lineCount: o2, removals: n3 } = E())) : (c58 || (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 && (c58 = true, s.splice(s.length - n3, n3));
41246
+ d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u4 && (c59 || (u4 -= 1), { lineCount: o2, removals: n3 } = E())) : (c59 || (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 && (c59 = true, s.splice(s.length - n3, n3));
40992
41247
  }
40993
41248
  const x = [];
40994
41249
  d && x.push(M);
40995
41250
  for (const t2 of s)
40996
41251
  for (const n3 of t2)
40997
41252
  x.push(n3);
40998
- return c58 && x.push(M), x;
41253
+ return c59 && x.push(M), x;
40999
41254
  };
41000
41255
  var confirm = (i2) => {
41001
41256
  const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
@@ -41014,15 +41269,15 @@ var confirm = (i2) => {
41014
41269
  u4
41015
41270
  ), o2 = `${e ? `${styleText2("gray", S_BAR)}
41016
41271
  ` : ""}${f}
41017
- `, c58 = this.value ? a2 : s;
41272
+ `, c59 = this.value ? a2 : s;
41018
41273
  switch (this.state) {
41019
41274
  case "submit": {
41020
41275
  const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
41021
- return `${o2}${r2}${styleText2("dim", c58)}`;
41276
+ return `${o2}${r2}${styleText2("dim", c59)}`;
41022
41277
  }
41023
41278
  case "cancel": {
41024
41279
  const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
41025
- return `${o2}${r2}${styleText2(["strikethrough", "dim"], c58)}${e ? `
41280
+ return `${o2}${r2}${styleText2(["strikethrough", "dim"], c59)}${e ? `
41026
41281
  ${styleText2("gray", S_BAR)}` : ""}`;
41027
41282
  }
41028
41283
  default: {
@@ -41170,13 +41425,13 @@ var multiline = (e) => new h({
41170
41425
  `, m2 = e.placeholder && e.placeholder.length > 0 ? (
41171
41426
  // biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
41172
41427
  styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1))
41173
- ) : styleText2(["inverse", "hidden"], "_"), a2 = this.userInput ? this.userInputWithCursor : m2, l2 = this.value ?? "", c58 = e.showSubmit ? `
41428
+ ) : styleText2(["inverse", "hidden"], "_"), a2 = this.userInput ? this.userInputWithCursor : m2, l2 = this.value ?? "", c59 = e.showSubmit ? `
41174
41429
  ${styleText2(this.focused === "submit" ? "cyan" : "dim", "[ submit ]")}` : "";
41175
41430
  switch (this.state) {
41176
41431
  case "error": {
41177
41432
  const n3 = `${styleText2("yellow", S_BAR)} `, r2 = i2 ? wrapTextWithPrefix(e.output, a2, n3, void 0) : a2, u4 = styleText2("yellow", S_BAR_END);
41178
41433
  return `${o2}${r2}
41179
- ${u4} ${styleText2("yellow", this.error)}${c58}
41434
+ ${u4} ${styleText2("yellow", this.error)}${c59}
41180
41435
  `;
41181
41436
  }
41182
41437
  case "submit": {
@@ -41204,7 +41459,7 @@ ${u4} ${styleText2("yellow", this.error)}${c58}
41204
41459
  default: {
41205
41460
  const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "", u4 = i2 ? wrapTextWithPrefix(e.output, a2, n3) : a2;
41206
41461
  return `${o2}${u4}
41207
- ${r2}${c58}
41462
+ ${r2}${c59}
41208
41463
  `;
41209
41464
  }
41210
41465
  }
@@ -41219,7 +41474,7 @@ var password = (r2) => new u$1({
41219
41474
  render() {
41220
41475
  const e = r2.withGuide ?? settings.withGuide, o2 = `${e ? `${styleText2("gray", S_BAR)}
41221
41476
  ` : ""}${symbol2(this.state)} ${r2.message}
41222
- `, c58 = this.userInputWithCursor, i2 = this.masked;
41477
+ `, c59 = this.userInputWithCursor, i2 = this.masked;
41223
41478
  switch (this.state) {
41224
41479
  case "error": {
41225
41480
  const s = e ? `${styleText2("yellow", S_BAR)} ` : "", n3 = e ? `${styleText2("yellow", S_BAR_END)} ` : "", l2 = i2 ?? "";
@@ -41239,7 +41494,7 @@ ${styleText2("gray", S_BAR)}` : ""}`;
41239
41494
  }
41240
41495
  default: {
41241
41496
  const s = e ? `${styleText2("cyan", S_BAR)} ` : "", n3 = e ? styleText2("cyan", S_BAR_END) : "";
41242
- return `${o2}${s}${c58}
41497
+ return `${o2}${s}${c59}
41243
41498
  ${n3}
41244
41499
  `;
41245
41500
  }
@@ -41255,7 +41510,7 @@ var SELECT_INSTRUCTIONS = [
41255
41510
  `${styleText2("dim", "\u2191/\u2193")} to navigate`,
41256
41511
  `${styleText2("dim", "Enter:")} confirm`
41257
41512
  ];
41258
- var c57 = (t2, o2) => t2.includes(`
41513
+ var c58 = (t2, o2) => t2.includes(`
41259
41514
  `) ? t2.split(`
41260
41515
  `).map((d) => o2(d)).join(`
41261
41516
  `) : o2(t2);
@@ -41266,15 +41521,15 @@ var select = (t2) => {
41266
41521
  const s = n3.label ?? String(n3.value);
41267
41522
  switch (m2) {
41268
41523
  case "disabled":
41269
- return `${styleText2("gray", S_RADIO_INACTIVE)} ${c57(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
41524
+ return `${styleText2("gray", S_RADIO_INACTIVE)} ${c58(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
41270
41525
  case "selected":
41271
- return `${c57(s, (i2) => styleText2("dim", i2))}`;
41526
+ return `${c58(s, (i2) => styleText2("dim", i2))}`;
41272
41527
  case "active":
41273
41528
  return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
41274
41529
  case "cancelled":
41275
- return `${c57(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
41530
+ return `${c58(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
41276
41531
  default:
41277
- return `${styleText2("dim", S_RADIO_INACTIVE)} ${c57(s, (i2) => styleText2("dim", i2))}`;
41532
+ return `${styleText2("dim", S_RADIO_INACTIVE)} ${c58(s, (i2) => styleText2("dim", i2))}`;
41278
41533
  }
41279
41534
  }, d = t2.showInstructions ?? true;
41280
41535
  return new n$1({
@@ -42334,7 +42589,7 @@ function extractCommandTree(cmd) {
42334
42589
  description: o2.description,
42335
42590
  takesValue: o2.required || o2.optional
42336
42591
  }));
42337
- const subcommands = cmd.commands.filter((c58) => !c58._hidden).map((c58) => extractCommandTree(c58));
42592
+ const subcommands = cmd.commands.filter((c59) => !c59._hidden).map((c59) => extractCommandTree(c59));
42338
42593
  return {
42339
42594
  name: cmd.name(),
42340
42595
  description: cmd.description(),
@@ -42400,7 +42655,7 @@ function generateBashCompletion(tree, binName) {
42400
42655
  }
42401
42656
  function collectBashCases(tree, prefix) {
42402
42657
  const cases = /* @__PURE__ */ new Map();
42403
- const subcommandNames = tree.subcommands.map((c58) => c58.name);
42658
+ const subcommandNames = tree.subcommands.map((c59) => c59.name);
42404
42659
  const optionNames = tree.options.flatMap((o2) => o2.short ? [o2.long, o2.short] : [o2.long]);
42405
42660
  const extraOptions = prefix === "" ? ["--help", "--version"] : ["--help"];
42406
42661
  const allOptions = [.../* @__PURE__ */ new Set([...optionNames, ...extraOptions])];
@@ -42815,9 +43070,9 @@ function buildInboxesTable(inboxes) {
42815
43070
  address: sanitizeDisplay(inbox.address),
42816
43071
  label: sanitizeDisplay(inbox.label)
42817
43072
  }));
42818
- const addressWidth = Math.max(7, ...cells.map((c58) => c58.address.length));
43073
+ const addressWidth = Math.max(7, ...cells.map((c59) => c59.address.length));
42819
43074
  const header = `${"ADDRESS".padEnd(addressWidth)} LABEL`;
42820
- const rows = cells.map((c58) => `${c58.address.padEnd(addressWidth)} ${c58.label}`);
43075
+ const rows = cells.map((c59) => `${c59.address.padEnd(addressWidth)} ${c59.label}`);
42821
43076
  return { header, rows };
42822
43077
  }
42823
43078
  function formatInboxQuota(quota) {
@@ -42841,14 +43096,14 @@ function buildInboxEmailsTable(messages) {
42841
43096
  subject: sanitizeDisplay(message.subject ?? ""),
42842
43097
  unread: message.unread ? "yes" : "no"
42843
43098
  }));
42844
- const idWidth = Math.max(2, ...cells.map((c58) => c58.id.length));
42845
- const receivedWidth = Math.max(8, ...cells.map((c58) => c58.received.length));
42846
- const fromWidth = Math.max(4, ...cells.map((c58) => c58.from.length));
42847
- const toWidth = Math.max(2, ...cells.map((c58) => c58.to.length));
42848
- const subjectWidth = Math.max(7, ...cells.map((c58) => c58.subject.length));
43099
+ const idWidth = Math.max(2, ...cells.map((c59) => c59.id.length));
43100
+ const receivedWidth = Math.max(8, ...cells.map((c59) => c59.received.length));
43101
+ const fromWidth = Math.max(4, ...cells.map((c59) => c59.from.length));
43102
+ const toWidth = Math.max(2, ...cells.map((c59) => c59.to.length));
43103
+ const subjectWidth = Math.max(7, ...cells.map((c59) => c59.subject.length));
42849
43104
  const header = `${"ID".padEnd(idWidth)} ${"RECEIVED".padEnd(receivedWidth)} ${"FROM".padEnd(fromWidth)} ${"TO".padEnd(toWidth)} ${"SUBJECT".padEnd(subjectWidth)} UNREAD`;
42850
43105
  const rows = cells.map(
42851
- (c58) => `${c58.id.padEnd(idWidth)} ${c58.received.padEnd(receivedWidth)} ${c58.from.padEnd(fromWidth)} ${c58.to.padEnd(toWidth)} ${c58.subject.padEnd(subjectWidth)} ${c58.unread}`
43106
+ (c59) => `${c59.id.padEnd(idWidth)} ${c59.received.padEnd(receivedWidth)} ${c59.from.padEnd(fromWidth)} ${c59.to.padEnd(toWidth)} ${c59.subject.padEnd(subjectWidth)} ${c59.unread}`
42852
43107
  );
42853
43108
  return { header, rows };
42854
43109
  }
@@ -43076,14 +43331,14 @@ async function runEmails(label, options) {
43076
43331
  const output = parseOutput(options.output);
43077
43332
  requireInboxLabel(label);
43078
43333
  const limit = parseEmailLimit(options.limit);
43079
- const since = parseEmailSince(options.since);
43334
+ const since2 = parseEmailSince(options.since);
43080
43335
  const organizationId = await resolveOrganizationId();
43081
43336
  const result = await authenticatedRequest(
43082
43337
  (client) => client.inbox.listInboxMessages({
43083
43338
  params: { organizationId, label },
43084
43339
  query: {
43085
43340
  ...limit !== void 0 ? { limit } : {},
43086
- ...since !== void 0 ? { since } : {}
43341
+ ...since2 !== void 0 ? { since: since2 } : {}
43087
43342
  }
43088
43343
  })
43089
43344
  );
@@ -43576,16 +43831,16 @@ function printCredentialsTsv(creds) {
43576
43831
  }
43577
43832
  }
43578
43833
  function buildCredentialsTable(creds) {
43579
- const cells = creds.map((c58) => ({
43580
- id: c58.credentialId,
43581
- label: sanitizeDisplay(c58.label),
43582
- type: c58.credentialType
43834
+ const cells = creds.map((c59) => ({
43835
+ id: c59.credentialId,
43836
+ label: sanitizeDisplay(c59.label),
43837
+ type: c59.credentialType
43583
43838
  }));
43584
- const idWidth = Math.max(2, ...cells.map((c58) => c58.id.length));
43585
- const labelWidth = Math.max(5, ...cells.map((c58) => c58.label.length));
43839
+ const idWidth = Math.max(2, ...cells.map((c59) => c59.id.length));
43840
+ const labelWidth = Math.max(5, ...cells.map((c59) => c59.label.length));
43586
43841
  const header = `${"ID".padEnd(idWidth)} ${"LABEL".padEnd(labelWidth)} TYPE`;
43587
43842
  const rows = cells.map(
43588
- (c58) => `${c58.id.padEnd(idWidth)} ${c58.label.padEnd(labelWidth)} ${c58.type}`
43843
+ (c59) => `${c59.id.padEnd(idWidth)} ${c59.label.padEnd(labelWidth)} ${c59.type}`
43589
43844
  );
43590
43845
  return { header, rows };
43591
43846
  }
@@ -44313,14 +44568,14 @@ function buildEnvironmentTable(envs, leading) {
44313
44568
  url: e.primaryUrl != null ? sanitizeDisplay(e.primaryUrl) : "\u2014"
44314
44569
  }));
44315
44570
  const leadingWidths = leading.map(
44316
- (column, i2) => Math.max(column.header.length, ...cells.map((c58) => c58.leading[i2]?.length ?? 0))
44571
+ (column, i2) => Math.max(column.header.length, ...cells.map((c59) => c59.leading[i2]?.length ?? 0))
44317
44572
  );
44318
- const nameWidth = Math.max(4, ...cells.map((c58) => c58.name.length));
44573
+ const nameWidth = Math.max(4, ...cells.map((c59) => c59.name.length));
44319
44574
  const padLeading = (values) => values.map((v, i2) => v.padEnd(leadingWidths[i2] ?? 0)).join(" ");
44320
44575
  return {
44321
- header: `${padLeading(leading.map((c58) => c58.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
44576
+ header: `${padLeading(leading.map((c59) => c59.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
44322
44577
  rows: cells.map(
44323
- (c58) => `${padLeading(c58.leading)} ${c58.name.padEnd(nameWidth)} ${c58.prod.padEnd(4)} ${c58.url}`
44578
+ (c59) => `${padLeading(c59.leading)} ${c59.name.padEnd(nameWidth)} ${c59.prod.padEnd(4)} ${c59.url}`
44324
44579
  )
44325
44580
  };
44326
44581
  }
@@ -45317,11 +45572,26 @@ function isPentestIdentifier(value) {
45317
45572
  function isFindingIdentifier(value) {
45318
45573
  return FINDING_IDENTIFIER_PATTERN.test(value);
45319
45574
  }
45320
- function failStatusUpdate(status, body) {
45575
+ function failStatusUpdate(status, body, viaApiKey) {
45321
45576
  const { message, errorCode } = readErrorFields(body);
45322
45577
  if (status === UNAUTHORIZED_STATUS2) {
45323
45578
  exitAuthFailed();
45324
45579
  }
45580
+ if (status === 403 && viaApiKey) {
45581
+ console.error(
45582
+ colorError(
45583
+ `${message ?? "Request failed (status 403)."}
45584
+ API keys can update finding status once Trace enables finding automation for your organization. Ask Trace to turn it on, or run this with \`tracecli auth login\`.`
45585
+ )
45586
+ );
45587
+ process.exit(1);
45588
+ }
45589
+ if (status === 409 && errorCode === "FINDING_STALE") {
45590
+ console.error(
45591
+ colorError(message ?? "The finding changed while this update was in flight. Retry it.")
45592
+ );
45593
+ process.exit(1);
45594
+ }
45325
45595
  if (status === 404) {
45326
45596
  console.error(colorError(message ?? "Pentest or finding not found."));
45327
45597
  process.exit(1);
@@ -45398,13 +45668,19 @@ async function runStatusUpdate(options) {
45398
45668
  );
45399
45669
  process.exit(1);
45400
45670
  }
45671
+ const viaApiKey = requireAuth().kind === "api_key";
45401
45672
  const organizationId = await resolveOrganizationId();
45402
45673
  const params = {
45403
45674
  organizationId,
45404
45675
  pentestId: options.pentest,
45405
45676
  pentestFindingId: options.finding
45406
45677
  };
45407
- const result = target === "IN_PROGRESS" ? await authenticatedRequest(
45678
+ const result = viaApiKey ? await authenticatedRequest(
45679
+ (client) => client.pentestFinding.automationStatusUpdate({
45680
+ params,
45681
+ body: { status: target, ...note !== void 0 ? { note } : {} }
45682
+ })
45683
+ ) : target === "IN_PROGRESS" ? await authenticatedRequest(
45408
45684
  (client) => client.pentestFinding.startProgress({ params, body: {} })
45409
45685
  ) : await authenticatedRequest(
45410
45686
  (client) => client.pentestFinding.reportRemediation({
@@ -45413,7 +45689,7 @@ async function runStatusUpdate(options) {
45413
45689
  })
45414
45690
  );
45415
45691
  if (result.status !== 200) {
45416
- failStatusUpdate(result.status, result.body);
45692
+ failStatusUpdate(result.status, result.body, viaApiKey);
45417
45693
  }
45418
45694
  if (options.output === "json") {
45419
45695
  console.log(JSON.stringify(result.body, null, 2));
@@ -45436,8 +45712,12 @@ fix is ready for Trace to re-test. Leaving the finding IN_PROGRESS (and not
45436
45712
  sending REMEDIATED) keeps it out of the retest queue.
45437
45713
 
45438
45714
  IN_PROGRESS is allowed from OPEN or VERIFIED_OPEN. REMEDIATED is allowed from
45439
- OPEN, IN_PROGRESS, or VERIFIED_OPEN. Requires \`tracecli auth login\` (API keys
45440
- are rejected \u2014 the change is attributed to the signed-in user).
45715
+ OPEN, IN_PROGRESS, or VERIFIED_OPEN.
45716
+
45717
+ A signed-in session (\`tracecli auth login\`) attributes the change to you. A
45718
+ Trace API key works too, once Trace enables finding automation for your
45719
+ organization: those writes are recorded as \`api-key:<key name>\` and show up as
45720
+ yours in the finding's history.
45441
45721
 
45442
45722
  Examples:
45443
45723
  tracecli pentest findings status-update --pentest PT-3 --finding 7 --status IN_PROGRESS