securewithtrace 0.40.1 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1193 -194
- 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, (
|
|
6279
|
+
const base643 = data.replace(/[-_]/g, (c62) => c62 === "-" ? "+" : "/");
|
|
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
|
|
16324
|
-
inst.minDate =
|
|
16325
|
-
inst.maxDate =
|
|
16323
|
+
const c62 = inst._zod.bag;
|
|
16324
|
+
inst.minDate = c62.minimum ? new Date(c62.minimum) : null;
|
|
16325
|
+
inst.maxDate = c62.maximum ? new Date(c62.maximum) : null;
|
|
16326
16326
|
});
|
|
16327
16327
|
function date3(params) {
|
|
16328
16328
|
return _date(ZodDate, params);
|
|
@@ -21920,6 +21920,17 @@ var ContestReasonValues = [
|
|
|
21920
21920
|
"OTHER"
|
|
21921
21921
|
];
|
|
21922
21922
|
var ContestReason = external_exports.enum(ContestReasonValues);
|
|
21923
|
+
var PentestFindingFeedbackRatingValues = ["THUMBS_UP", "THUMBS_DOWN"];
|
|
21924
|
+
var PentestFindingFeedbackRating = external_exports.enum(PentestFindingFeedbackRatingValues);
|
|
21925
|
+
var PentestFindingFeedbackReasonValues = [
|
|
21926
|
+
"FALSE_POSITIVE",
|
|
21927
|
+
"SEVERITY_TOO_HIGH",
|
|
21928
|
+
"SEVERITY_TOO_LOW",
|
|
21929
|
+
"UNCLEAR_WRITEUP",
|
|
21930
|
+
"REMEDIATION_NOT_ACTIONABLE",
|
|
21931
|
+
"OTHER"
|
|
21932
|
+
];
|
|
21933
|
+
var PentestFindingFeedbackReason = external_exports.enum(PentestFindingFeedbackReasonValues);
|
|
21923
21934
|
var ManualRetestOutcomeValues = ["FIXED", "PARTIALLY_FIXED", "NOT_FIXED"];
|
|
21924
21935
|
var ManualRetestOutcome = external_exports.enum(ManualRetestOutcomeValues);
|
|
21925
21936
|
var RetestOutcomeValues = [...ManualRetestOutcomeValues, "UNABLE_TO_VERIFY"];
|
|
@@ -21998,7 +22009,7 @@ var PentestEditActionValues = [
|
|
|
21998
22009
|
"DELIVER"
|
|
21999
22010
|
];
|
|
22000
22011
|
var PentestEditAction = external_exports.enum(PentestEditActionValues);
|
|
22001
|
-
var PentestAuditActorTypeValues = ["USER", "SYSTEM", "AGENT", "API_KEY"];
|
|
22012
|
+
var PentestAuditActorTypeValues = ["USER", "SYSTEM", "AGENT", "API_KEY", "STAFF"];
|
|
22002
22013
|
var PentestAuditActorType = external_exports.enum(PentestAuditActorTypeValues);
|
|
22003
22014
|
var PentestHypothesisStatusValues = [
|
|
22004
22015
|
"DRAFTED",
|
|
@@ -22362,6 +22373,20 @@ var AgentSessionEventPayloadUrlResponseSchema = external_exports.object({
|
|
|
22362
22373
|
/** Presigned S3 GET for the overflow payload (short TTL). */
|
|
22363
22374
|
url: external_exports.url()
|
|
22364
22375
|
});
|
|
22376
|
+
var ExportAgentSessionTranscriptResponseSchema = external_exports.object({
|
|
22377
|
+
/** Presigned S3 GET with an attachment Content-Disposition (short TTL). */
|
|
22378
|
+
downloadUrl: external_exports.url(),
|
|
22379
|
+
expiresAt: external_exports.coerce.date(),
|
|
22380
|
+
fileName: external_exports.string(),
|
|
22381
|
+
/** Bytes of the exported document. */
|
|
22382
|
+
sizeBytes: external_exports.number().int().nonnegative(),
|
|
22383
|
+
eventCount: external_exports.number().int().nonnegative(),
|
|
22384
|
+
subagentCount: external_exports.number().int().nonnegative(),
|
|
22385
|
+
/** High-water mark captured by the export; a live session keeps moving past it. */
|
|
22386
|
+
lastEventSeq: external_exports.number().int().nonnegative(),
|
|
22387
|
+
/** Overflow payloads whose S3 object no longer exists; the export keeps the inline preview for those. */
|
|
22388
|
+
missingOverflowPayloadCount: external_exports.number().int().nonnegative()
|
|
22389
|
+
});
|
|
22365
22390
|
var SendAgentSessionMessageResponseSchema = external_exports.object({
|
|
22366
22391
|
event: AgentSessionEventResponseSchema,
|
|
22367
22392
|
/** True when the message relaunched a parked session. */
|
|
@@ -22507,6 +22532,21 @@ var agentSessionContract = c2.router({
|
|
|
22507
22532
|
500: ErrorResponseSchema
|
|
22508
22533
|
}
|
|
22509
22534
|
},
|
|
22535
|
+
// POST, not GET: each call assembles the transcript from Postgres + S3 overflow
|
|
22536
|
+
// objects and writes a new export object before presigning it.
|
|
22537
|
+
exportTranscript: {
|
|
22538
|
+
method: "POST",
|
|
22539
|
+
path: "/organizations/:organizationId/pentests/:pentestId/agent-sessions/:agentSessionId/transcript-export",
|
|
22540
|
+
pathParams: AgentSessionIdParamsSchema,
|
|
22541
|
+
body: null,
|
|
22542
|
+
responses: {
|
|
22543
|
+
200: ExportAgentSessionTranscriptResponseSchema,
|
|
22544
|
+
401: ErrorResponseSchema,
|
|
22545
|
+
403: ErrorResponseSchema,
|
|
22546
|
+
404: ErrorResponseSchema,
|
|
22547
|
+
500: ErrorResponseSchema
|
|
22548
|
+
}
|
|
22549
|
+
},
|
|
22510
22550
|
sendMessage: {
|
|
22511
22551
|
method: "POST",
|
|
22512
22552
|
path: "/organizations/:organizationId/pentests/:pentestId/agent-sessions/:agentSessionId/messages",
|
|
@@ -23731,11 +23771,19 @@ var CustomerReportPdfResponseSchema = ReportPdfResponseSchema.omit({
|
|
|
23731
23771
|
canViewInline: external_exports.boolean().optional(),
|
|
23732
23772
|
/**
|
|
23733
23773
|
* What the Download action hands the customer: the PDF alone, or one zip
|
|
23734
|
-
* carrying the PDF, the markdown report, and the evidence
|
|
23735
|
-
* templates whose tooling consumes the markdown). Preview
|
|
23736
|
-
* PDF. Optional for the deploy-order reason above; consumers
|
|
23774
|
+
* carrying the PDF, the Word document, the markdown report, and the evidence
|
|
23775
|
+
* files (partner templates whose tooling consumes the markdown). Preview
|
|
23776
|
+
* always opens the PDF. Optional for the deploy-order reason above; consumers
|
|
23777
|
+
* default to 'pdf'.
|
|
23778
|
+
*/
|
|
23779
|
+
downloadFormat: CustomerReportDownloadFormatSchema.optional(),
|
|
23780
|
+
/**
|
|
23781
|
+
* Whether a Word document (.docx) from the same render as the served PDF is
|
|
23782
|
+
* available through `downloadCustomer?artifact=docx`. Partner templates only;
|
|
23783
|
+
* resolved server-side from storage, never from the template alone. Optional
|
|
23784
|
+
* for the deploy-order reason above; consumers default to false.
|
|
23737
23785
|
*/
|
|
23738
|
-
|
|
23786
|
+
docxAvailable: external_exports.boolean().optional()
|
|
23739
23787
|
});
|
|
23740
23788
|
var GetCustomerReportPdfResponseSchema = external_exports.object({
|
|
23741
23789
|
report: CustomerReportPdfResponseSchema.nullable()
|
|
@@ -23749,8 +23797,13 @@ var DeleteReportPdfRequestSchema = external_exports.object({
|
|
|
23749
23797
|
var DeleteReportIssueRequestSchema = external_exports.object({
|
|
23750
23798
|
reason: external_exports.string().min(1).max(1e4).optional()
|
|
23751
23799
|
}).strict().optional();
|
|
23800
|
+
var ReportPdfDownloadArtifactValues = ["pdf", "markdown", "docx"];
|
|
23801
|
+
var ReportPdfDownloadArtifactSchema = external_exports.enum(ReportPdfDownloadArtifactValues);
|
|
23752
23802
|
var ReportPdfDownloadQuerySchema = external_exports.object({
|
|
23753
|
-
artifact:
|
|
23803
|
+
artifact: ReportPdfDownloadArtifactSchema.optional()
|
|
23804
|
+
});
|
|
23805
|
+
var CustomerReportPdfDownloadQuerySchema = PentestPdfDownloadQuerySchema.extend({
|
|
23806
|
+
artifact: external_exports.enum(["docx"]).optional()
|
|
23754
23807
|
});
|
|
23755
23808
|
var ReportPdfDownloadResponseSchema = external_exports.object({
|
|
23756
23809
|
report: ReportPdfResponseSchema,
|
|
@@ -24318,6 +24371,10 @@ var OperatorFindingListSchema = PentestFindingListItemSchema.omit({
|
|
|
24318
24371
|
var CustomerPentestFindingRepositorySchema = PentestFindingRepositorySchema.omit({
|
|
24319
24372
|
repositoryId: true
|
|
24320
24373
|
});
|
|
24374
|
+
var CustomerFindingPendingRetestSchema = external_exports.object({
|
|
24375
|
+
state: external_exports.enum(["QUEUED", "RUNNING"]),
|
|
24376
|
+
since: external_exports.coerce.date()
|
|
24377
|
+
}).nullable().default(null);
|
|
24321
24378
|
var CustomerPentestFindingResponseSchema = PentestFindingResponseSchema.omit({
|
|
24322
24379
|
organizationId: true,
|
|
24323
24380
|
pentestId: true,
|
|
@@ -24341,7 +24398,8 @@ var CustomerPentestFindingResponseSchema = PentestFindingResponseSchema.omit({
|
|
|
24341
24398
|
// customer "dispute under review" hint + suppresses the re-dispute affordance,
|
|
24342
24399
|
// even after a retest moved the finding off CONTESTED. Only this derived
|
|
24343
24400
|
// boolean crosses the trust boundary — never the staff contest list.
|
|
24344
|
-
hasOpenContest: external_exports.boolean()
|
|
24401
|
+
hasOpenContest: external_exports.boolean(),
|
|
24402
|
+
pendingRetest: CustomerFindingPendingRetestSchema
|
|
24345
24403
|
});
|
|
24346
24404
|
var CustomerPentestFindingListItemSchema = PentestFindingListItemSchema.omit({
|
|
24347
24405
|
organizationId: true,
|
|
@@ -24356,7 +24414,10 @@ var CustomerPentestFindingListItemSchema = PentestFindingListItemSchema.omit({
|
|
|
24356
24414
|
// Published-only, same as the customer detail schema above — re-narrowed from the
|
|
24357
24415
|
// nullable root.
|
|
24358
24416
|
displayId: external_exports.number().int().positive(),
|
|
24359
|
-
repositories: external_exports.array(CustomerPentestFindingRepositorySchema)
|
|
24417
|
+
repositories: external_exports.array(CustomerPentestFindingRepositorySchema),
|
|
24418
|
+
// On the list row too: the findings table is what the customer watches while a
|
|
24419
|
+
// retest they queued runs, and polling it is how the row flips without a reload.
|
|
24420
|
+
pendingRetest: CustomerFindingPendingRetestSchema
|
|
24360
24421
|
});
|
|
24361
24422
|
var ListCustomerPentestFindingsResponseSchema = external_exports.array(
|
|
24362
24423
|
CustomerPentestFindingListItemSchema
|
|
@@ -24365,6 +24426,7 @@ var ListCustomerPentestFindingDeliveryResponseSchema = external_exports.array(
|
|
|
24365
24426
|
CustomerPentestFindingListItemSchema
|
|
24366
24427
|
);
|
|
24367
24428
|
var ResolutionTimelineActor = external_exports.enum(["CUSTOMER", "TRACE"]);
|
|
24429
|
+
var ResolutionTimelineActorName = external_exports.string().nullable().default(null);
|
|
24368
24430
|
var ResolutionTimelineVia = external_exports.object({
|
|
24369
24431
|
provider: external_exports.enum(["LINEAR"]),
|
|
24370
24432
|
identifier: external_exports.string(),
|
|
@@ -24375,12 +24437,17 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24375
24437
|
kind: external_exports.literal("remediation_reported"),
|
|
24376
24438
|
at: external_exports.coerce.date(),
|
|
24377
24439
|
actor: ResolutionTimelineActor,
|
|
24440
|
+
actorName: ResolutionTimelineActorName,
|
|
24378
24441
|
note: external_exports.string().nullable(),
|
|
24379
24442
|
via: ResolutionTimelineVia
|
|
24380
24443
|
}),
|
|
24444
|
+
// Retests are run by Trace (staff or a Trace agent), so the actor is fixed;
|
|
24445
|
+
// the default keeps a web build ahead of the api parsing older payloads.
|
|
24381
24446
|
external_exports.object({
|
|
24382
24447
|
kind: external_exports.literal("retest"),
|
|
24383
24448
|
at: external_exports.coerce.date(),
|
|
24449
|
+
actor: external_exports.literal("TRACE").default("TRACE"),
|
|
24450
|
+
actorName: ResolutionTimelineActorName,
|
|
24384
24451
|
outcome: RetestOutcome,
|
|
24385
24452
|
note: external_exports.string().nullable()
|
|
24386
24453
|
}),
|
|
@@ -24388,12 +24455,14 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24388
24455
|
kind: external_exports.literal("accepted_with_controls"),
|
|
24389
24456
|
at: external_exports.coerce.date(),
|
|
24390
24457
|
actor: ResolutionTimelineActor,
|
|
24458
|
+
actorName: ResolutionTimelineActorName,
|
|
24391
24459
|
note: external_exports.string()
|
|
24392
24460
|
}),
|
|
24393
24461
|
external_exports.object({
|
|
24394
24462
|
kind: external_exports.literal("dismissed"),
|
|
24395
24463
|
at: external_exports.coerce.date(),
|
|
24396
24464
|
actor: ResolutionTimelineActor,
|
|
24465
|
+
actorName: ResolutionTimelineActorName,
|
|
24397
24466
|
reason: PentestFindingDismissReason,
|
|
24398
24467
|
note: external_exports.string()
|
|
24399
24468
|
}),
|
|
@@ -24403,6 +24472,7 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24403
24472
|
kind: external_exports.literal("reopened"),
|
|
24404
24473
|
at: external_exports.coerce.date(),
|
|
24405
24474
|
actor: ResolutionTimelineActor,
|
|
24475
|
+
actorName: ResolutionTimelineActorName,
|
|
24406
24476
|
toStatus: external_exports.enum(["OPEN", "IN_PROGRESS"]),
|
|
24407
24477
|
note: external_exports.string().nullable(),
|
|
24408
24478
|
via: ResolutionTimelineVia
|
|
@@ -24412,6 +24482,7 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24412
24482
|
kind: external_exports.literal("note"),
|
|
24413
24483
|
at: external_exports.coerce.date(),
|
|
24414
24484
|
actor: ResolutionTimelineActor,
|
|
24485
|
+
actorName: ResolutionTimelineActorName,
|
|
24415
24486
|
note: external_exports.string()
|
|
24416
24487
|
}),
|
|
24417
24488
|
// Customer opened a dispute (PR 3). `note` = the customer's justification.
|
|
@@ -24419,6 +24490,7 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24419
24490
|
kind: external_exports.literal("contested"),
|
|
24420
24491
|
at: external_exports.coerce.date(),
|
|
24421
24492
|
actor: ResolutionTimelineActor,
|
|
24493
|
+
actorName: ResolutionTimelineActorName,
|
|
24422
24494
|
reason: ContestReason,
|
|
24423
24495
|
note: external_exports.string()
|
|
24424
24496
|
}),
|
|
@@ -24429,6 +24501,7 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24429
24501
|
kind: external_exports.literal("contest_resolved"),
|
|
24430
24502
|
at: external_exports.coerce.date(),
|
|
24431
24503
|
actor: ResolutionTimelineActor,
|
|
24504
|
+
actorName: ResolutionTimelineActorName,
|
|
24432
24505
|
resultStatus: PentestFindingStatus.nullable(),
|
|
24433
24506
|
note: external_exports.string()
|
|
24434
24507
|
}),
|
|
@@ -24438,22 +24511,61 @@ var ResolutionTimelineEntrySchema = external_exports.discriminatedUnion("kind",
|
|
|
24438
24511
|
kind: external_exports.literal("ticket_created"),
|
|
24439
24512
|
at: external_exports.coerce.date(),
|
|
24440
24513
|
actor: ResolutionTimelineActor,
|
|
24514
|
+
actorName: ResolutionTimelineActorName,
|
|
24441
24515
|
provider: external_exports.enum(["LINEAR"]),
|
|
24442
24516
|
identifier: external_exports.string(),
|
|
24443
24517
|
url: external_exports.url()
|
|
24518
|
+
}),
|
|
24519
|
+
// A reader rated the finding. `reason` is set only on a thumbs down; `note` is
|
|
24520
|
+
// the optional comment left with the vote.
|
|
24521
|
+
external_exports.object({
|
|
24522
|
+
kind: external_exports.literal("feedback_rated"),
|
|
24523
|
+
at: external_exports.coerce.date(),
|
|
24524
|
+
actor: ResolutionTimelineActor,
|
|
24525
|
+
actorName: ResolutionTimelineActorName,
|
|
24526
|
+
rating: PentestFindingFeedbackRating,
|
|
24527
|
+
reason: PentestFindingFeedbackReason.nullable(),
|
|
24528
|
+
note: external_exports.string().nullable()
|
|
24529
|
+
}),
|
|
24530
|
+
// A reader left a comment without a vote.
|
|
24531
|
+
external_exports.object({
|
|
24532
|
+
kind: external_exports.literal("feedback_commented"),
|
|
24533
|
+
at: external_exports.coerce.date(),
|
|
24534
|
+
actor: ResolutionTimelineActor,
|
|
24535
|
+
actorName: ResolutionTimelineActorName,
|
|
24536
|
+
note: external_exports.string()
|
|
24444
24537
|
})
|
|
24445
24538
|
]);
|
|
24446
24539
|
var ResolutionTimelineSchema = external_exports.array(ResolutionTimelineEntrySchema);
|
|
24540
|
+
var PentestFindingFeedbackSummarySchema = external_exports.object({
|
|
24541
|
+
thumbsUp: external_exports.number().int().nonnegative(),
|
|
24542
|
+
thumbsDown: external_exports.number().int().nonnegative(),
|
|
24543
|
+
viewerRating: PentestFindingFeedbackRating.nullable()
|
|
24544
|
+
});
|
|
24545
|
+
var PentestFindingFeedbackSummaryField = PentestFindingFeedbackSummarySchema.default({
|
|
24546
|
+
thumbsUp: 0,
|
|
24547
|
+
thumbsDown: 0,
|
|
24548
|
+
viewerRating: null
|
|
24549
|
+
});
|
|
24447
24550
|
var PentestFindingDetailResponseSchema = PentestFindingResponseSchema.extend({
|
|
24448
|
-
resolutionTimeline: ResolutionTimelineSchema
|
|
24551
|
+
resolutionTimeline: ResolutionTimelineSchema,
|
|
24552
|
+
feedbackSummary: PentestFindingFeedbackSummaryField
|
|
24449
24553
|
});
|
|
24450
24554
|
var CustomerPentestFindingDetailResponseSchema = CustomerPentestFindingResponseSchema.extend({
|
|
24451
|
-
resolutionTimeline: ResolutionTimelineSchema
|
|
24555
|
+
resolutionTimeline: ResolutionTimelineSchema,
|
|
24556
|
+
feedbackSummary: PentestFindingFeedbackSummaryField
|
|
24452
24557
|
});
|
|
24453
24558
|
var ReadPentestFindingResponseSchema = external_exports.union([
|
|
24454
24559
|
PentestFindingDetailResponseSchema,
|
|
24455
24560
|
CustomerPentestFindingDetailResponseSchema
|
|
24456
24561
|
]);
|
|
24562
|
+
var PentestFindingPdfExportResponseSchema = external_exports.object({
|
|
24563
|
+
/** Download name the presigned URL carries, e.g. `PTF-12-idor-on-invoices.pdf`. */
|
|
24564
|
+
fileName: external_exports.string(),
|
|
24565
|
+
downloadUrl: external_exports.url(),
|
|
24566
|
+
/** False when an identical export already existed and was reused without a render. */
|
|
24567
|
+
rendered: external_exports.boolean()
|
|
24568
|
+
});
|
|
24457
24569
|
var ListReadPentestFindingsResponseSchema = external_exports.union([
|
|
24458
24570
|
ListPentestFindingsResponseSchema,
|
|
24459
24571
|
ListCustomerPentestFindingsResponseSchema
|
|
@@ -24644,6 +24756,18 @@ var ResolvePentestFindingContestRequestSchema = external_exports.object({
|
|
|
24644
24756
|
dismissReason: PentestFindingDismissReason.optional(),
|
|
24645
24757
|
note: external_exports.string().min(1).max(1e4)
|
|
24646
24758
|
});
|
|
24759
|
+
var PENTEST_FINDING_FEEDBACK_COMMENT_MAX_LENGTH = 5e3;
|
|
24760
|
+
var CreatePentestFindingFeedbackRequestSchema = external_exports.object({
|
|
24761
|
+
rating: PentestFindingFeedbackRating.nullable().default(null),
|
|
24762
|
+
reason: PentestFindingFeedbackReason.nullable().default(null),
|
|
24763
|
+
comment: external_exports.string().trim().max(PENTEST_FINDING_FEEDBACK_COMMENT_MAX_LENGTH).transform((value) => value.length === 0 ? null : value).nullable().default(null)
|
|
24764
|
+
}).refine((input) => input.rating !== null || input.comment !== null, {
|
|
24765
|
+
message: "Feedback needs a rating or a comment",
|
|
24766
|
+
path: ["comment"]
|
|
24767
|
+
}).refine((input) => input.reason === null || input.rating === "THUMBS_DOWN", {
|
|
24768
|
+
message: "A reason only accompanies a thumbs down",
|
|
24769
|
+
path: ["reason"]
|
|
24770
|
+
});
|
|
24647
24771
|
var PentestFindingRetestResponseSchema = external_exports.object({
|
|
24648
24772
|
retestId: external_exports.uuid(),
|
|
24649
24773
|
pentestFindingId: external_exports.uuid(),
|
|
@@ -25220,7 +25344,8 @@ var CredentialTypeValues = [
|
|
|
25220
25344
|
"USERNAME_PASSWORD",
|
|
25221
25345
|
"COOKIE",
|
|
25222
25346
|
"MAGIC_AUTH",
|
|
25223
|
-
"SESSION_STATE"
|
|
25347
|
+
"SESSION_STATE",
|
|
25348
|
+
"SSH_PRIVATE_KEY"
|
|
25224
25349
|
];
|
|
25225
25350
|
var CredentialType = external_exports.enum(CredentialTypeValues);
|
|
25226
25351
|
var BearerAuthConfigSchema = external_exports.object({
|
|
@@ -25318,17 +25443,94 @@ var StorageStateSchema = external_exports.object({
|
|
|
25318
25443
|
} catch {
|
|
25319
25444
|
return;
|
|
25320
25445
|
}
|
|
25321
|
-
s.cookies.forEach((
|
|
25322
|
-
const d =
|
|
25446
|
+
s.cookies.forEach((c62, i2) => {
|
|
25447
|
+
const d = c62.domain.replace(/^\./, "").toLowerCase();
|
|
25323
25448
|
if (d !== host && !host.endsWith(`.${d}`)) {
|
|
25324
25449
|
ctx.addIssue({
|
|
25325
25450
|
code: "custom",
|
|
25326
25451
|
path: ["cookies", i2, "domain"],
|
|
25327
|
-
message: `cookie domain "${
|
|
25452
|
+
message: `cookie domain "${c62.domain}" is not the capture origin host "${host}" or a parent domain of it`
|
|
25328
25453
|
});
|
|
25329
25454
|
}
|
|
25330
25455
|
});
|
|
25331
25456
|
});
|
|
25457
|
+
var SSH_DEFAULT_PORT = 22;
|
|
25458
|
+
var SSH_HOST_MAX_CHARS = 253;
|
|
25459
|
+
var SSH_USERNAME_MAX_CHARS = 128;
|
|
25460
|
+
var SSH_PRIVATE_KEY_PEM_MAX_BYTES = 16384;
|
|
25461
|
+
var SSH_PASSPHRASE_MAX_CHARS = 1024;
|
|
25462
|
+
var SSH_HOST_PATTERN = /^[A-Za-z0-9][A-Za-z0-9.:-]*$/;
|
|
25463
|
+
var SSH_USERNAME_PATTERN = /^[^\s\p{Cc}]+$/u;
|
|
25464
|
+
var SSH_HOST_KEY_FINGERPRINT_PATTERN = /^SHA256:[A-Za-z0-9+/]{43}=?$/;
|
|
25465
|
+
var SshPrivateKeyAuthConfigSchema = external_exports.object({
|
|
25466
|
+
type: external_exports.literal("SSH_PRIVATE_KEY"),
|
|
25467
|
+
host: external_exports.string().min(1, "host is required").max(SSH_HOST_MAX_CHARS).regex(SSH_HOST_PATTERN, "host must be a hostname or IP address"),
|
|
25468
|
+
port: external_exports.number().int().min(1).max(65535).default(SSH_DEFAULT_PORT),
|
|
25469
|
+
username: external_exports.string().min(1, "username is required").max(SSH_USERNAME_MAX_CHARS).regex(SSH_USERNAME_PATTERN, "username must not contain whitespace or control characters"),
|
|
25470
|
+
hostKeyFingerprint: external_exports.string().regex(SSH_HOST_KEY_FINGERPRINT_PATTERN, "host key fingerprint must be SHA256:<base64>").optional()
|
|
25471
|
+
}).strict();
|
|
25472
|
+
var SSH_PRIVATE_KEY_PEM_LABELS = [
|
|
25473
|
+
"OPENSSH PRIVATE KEY",
|
|
25474
|
+
"RSA PRIVATE KEY",
|
|
25475
|
+
"EC PRIVATE KEY",
|
|
25476
|
+
"PRIVATE KEY",
|
|
25477
|
+
"ENCRYPTED PRIVATE KEY"
|
|
25478
|
+
];
|
|
25479
|
+
var PEM_BEGIN_LINE = /^-----BEGIN ([A-Z ]+)-----$/;
|
|
25480
|
+
var PEM_END_LINE = /^-----END ([A-Z ]+)-----$/;
|
|
25481
|
+
var PEM_BASE64_LINE = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
25482
|
+
var PEM_HEADER_LINE = /^[A-Za-z0-9-]+: [\x20-\x7e]*$/;
|
|
25483
|
+
function sshPrivateKeyPemError(value) {
|
|
25484
|
+
if (new TextEncoder().encode(value).length > SSH_PRIVATE_KEY_PEM_MAX_BYTES) {
|
|
25485
|
+
return `private key must be at most ${SSH_PRIVATE_KEY_PEM_MAX_BYTES} bytes`;
|
|
25486
|
+
}
|
|
25487
|
+
if (/[^\P{Cc}\r\n]/u.test(value)) {
|
|
25488
|
+
return "private key contains control characters";
|
|
25489
|
+
}
|
|
25490
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n").map((line) => line.trimEnd());
|
|
25491
|
+
while (lines.length > 0 && lines[0] === "") lines.shift();
|
|
25492
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
25493
|
+
if (lines.length < 3) {
|
|
25494
|
+
return "private key must be a PEM block with BEGIN and END lines";
|
|
25495
|
+
}
|
|
25496
|
+
const begin = PEM_BEGIN_LINE.exec(lines[0] ?? "");
|
|
25497
|
+
if (begin === null) {
|
|
25498
|
+
return "private key must start with a -----BEGIN \u2026 PRIVATE KEY----- line";
|
|
25499
|
+
}
|
|
25500
|
+
const end = PEM_END_LINE.exec(lines[lines.length - 1] ?? "");
|
|
25501
|
+
if (end === null) {
|
|
25502
|
+
return "private key must end with a -----END \u2026 PRIVATE KEY----- line";
|
|
25503
|
+
}
|
|
25504
|
+
const label = begin[1];
|
|
25505
|
+
if (!SSH_PRIVATE_KEY_PEM_LABELS.includes(label ?? "")) {
|
|
25506
|
+
return `private key label must be one of: ${SSH_PRIVATE_KEY_PEM_LABELS.join(", ")}`;
|
|
25507
|
+
}
|
|
25508
|
+
if (end[1] !== label) {
|
|
25509
|
+
return "private key BEGIN and END labels do not match";
|
|
25510
|
+
}
|
|
25511
|
+
let sawBody = false;
|
|
25512
|
+
for (const line of lines.slice(1, -1)) {
|
|
25513
|
+
if (line === "") continue;
|
|
25514
|
+
if (PEM_BASE64_LINE.test(line)) {
|
|
25515
|
+
sawBody = true;
|
|
25516
|
+
continue;
|
|
25517
|
+
}
|
|
25518
|
+
if (PEM_HEADER_LINE.test(line) && !sawBody) continue;
|
|
25519
|
+
return "private key body must be base64 lines";
|
|
25520
|
+
}
|
|
25521
|
+
if (!sawBody) {
|
|
25522
|
+
return "private key body is empty";
|
|
25523
|
+
}
|
|
25524
|
+
return null;
|
|
25525
|
+
}
|
|
25526
|
+
var SshPrivateKeyPemSchema = external_exports.string().min(1, "private key is required").superRefine((value, ctx) => {
|
|
25527
|
+
const message = sshPrivateKeyPemError(value);
|
|
25528
|
+
if (message !== null) ctx.addIssue({ code: "custom", message });
|
|
25529
|
+
});
|
|
25530
|
+
var SshPrivateKeySecretSchema = external_exports.object({
|
|
25531
|
+
privateKeyPem: SshPrivateKeyPemSchema,
|
|
25532
|
+
passphrase: external_exports.string().min(1).max(SSH_PASSPHRASE_MAX_CHARS).optional()
|
|
25533
|
+
}).strict();
|
|
25332
25534
|
var CredentialMfaKindValues = ["TOTP"];
|
|
25333
25535
|
var CredentialMfaKind = external_exports.enum(CredentialMfaKindValues);
|
|
25334
25536
|
var TotpSetupKeySchema = external_exports.string().min(1).max(TOTP_MAX_SECRET_CHARS * 4).superRefine((value, ctx) => {
|
|
@@ -25362,7 +25564,8 @@ var CredentialAuthConfigSchema = external_exports.discriminatedUnion("type", [
|
|
|
25362
25564
|
UsernamePasswordAuthConfigSchema,
|
|
25363
25565
|
PassphraseAuthConfigSchema,
|
|
25364
25566
|
MagicAuthConfigSchema,
|
|
25365
|
-
SessionStateAuthConfigSchema
|
|
25567
|
+
SessionStateAuthConfigSchema,
|
|
25568
|
+
SshPrivateKeyAuthConfigSchema
|
|
25366
25569
|
]);
|
|
25367
25570
|
|
|
25368
25571
|
// ../../packages/api-contracts/src/schemas/domain/knowledge-fact.schema.ts
|
|
@@ -29594,6 +29797,11 @@ var ResumeCodeUploadResponseSchema = external_exports.object({
|
|
|
29594
29797
|
var ListCodeUploadsResponseSchema = external_exports.object({
|
|
29595
29798
|
uploads: external_exports.array(CodeUploadSchema)
|
|
29596
29799
|
});
|
|
29800
|
+
var DownloadCodeUploadResponseSchema = external_exports.object({
|
|
29801
|
+
upload: CodeUploadSchema,
|
|
29802
|
+
downloadUrl: external_exports.url(),
|
|
29803
|
+
expiresAt: external_exports.coerce.date()
|
|
29804
|
+
});
|
|
29597
29805
|
|
|
29598
29806
|
// ../../packages/api-contracts/src/contracts/v1/code-upload.ts
|
|
29599
29807
|
var c12 = initContract();
|
|
@@ -29647,6 +29855,15 @@ var codeUploadContract = c12.router({
|
|
|
29647
29855
|
...commonErrors
|
|
29648
29856
|
}
|
|
29649
29857
|
},
|
|
29858
|
+
downloadCodeUpload: {
|
|
29859
|
+
method: "GET",
|
|
29860
|
+
path: "/organizations/:organizationId/code-uploads/:codeUploadId/download",
|
|
29861
|
+
pathParams: CodeUploadIdParamsSchema,
|
|
29862
|
+
responses: {
|
|
29863
|
+
200: DownloadCodeUploadResponseSchema,
|
|
29864
|
+
...commonErrors
|
|
29865
|
+
}
|
|
29866
|
+
},
|
|
29650
29867
|
deleteCodeUpload: {
|
|
29651
29868
|
method: "DELETE",
|
|
29652
29869
|
path: "/organizations/:organizationId/code-uploads/:codeUploadId",
|
|
@@ -29702,7 +29919,13 @@ var SECRET_SHAPES = {
|
|
|
29702
29919
|
username: external_exports.string().min(1).max(500),
|
|
29703
29920
|
password: external_exports.string().min(1).max(2048)
|
|
29704
29921
|
},
|
|
29705
|
-
SESSION_STATE: { secretValue: SessionStateSecretValueSchema }
|
|
29922
|
+
SESSION_STATE: { secretValue: SessionStateSecretValueSchema },
|
|
29923
|
+
// The key and its passphrase are one secret: they are encrypted together and
|
|
29924
|
+
// replaced together (see SshPrivateKeySecretSchema for the stored shape).
|
|
29925
|
+
SSH_PRIVATE_KEY: {
|
|
29926
|
+
privateKeyPem: SshPrivateKeyPemSchema,
|
|
29927
|
+
passphrase: external_exports.string().min(1).max(SSH_PASSPHRASE_MAX_CHARS).optional()
|
|
29928
|
+
}
|
|
29706
29929
|
};
|
|
29707
29930
|
var CreateLabelSchema = external_exports.string().max(200).optional();
|
|
29708
29931
|
var CreateBearerSchema = external_exports.object({
|
|
@@ -29783,6 +30006,12 @@ var CreateSessionStateSchema = external_exports.object({
|
|
|
29783
30006
|
label: CreateLabelSchema,
|
|
29784
30007
|
...SECRET_SHAPES.SESSION_STATE
|
|
29785
30008
|
}).strict();
|
|
30009
|
+
var CreateSshPrivateKeySchema = external_exports.object({
|
|
30010
|
+
credentialType: external_exports.literal("SSH_PRIVATE_KEY"),
|
|
30011
|
+
label: CreateLabelSchema,
|
|
30012
|
+
...SECRET_SHAPES.SSH_PRIVATE_KEY,
|
|
30013
|
+
authConfig: SshPrivateKeyAuthConfigSchema
|
|
30014
|
+
}).strict();
|
|
29786
30015
|
var CreateCredentialRequestSchema = external_exports.discriminatedUnion("credentialType", [
|
|
29787
30016
|
CreateBearerSchema,
|
|
29788
30017
|
CreateJwtSchema,
|
|
@@ -29791,7 +30020,8 @@ var CreateCredentialRequestSchema = external_exports.discriminatedUnion("credent
|
|
|
29791
30020
|
CreateUsernamePasswordSchema,
|
|
29792
30021
|
CreateCookieSchema,
|
|
29793
30022
|
CreateMagicAuthSchema,
|
|
29794
|
-
CreateSessionStateSchema
|
|
30023
|
+
CreateSessionStateSchema,
|
|
30024
|
+
CreateSshPrivateKeySchema
|
|
29795
30025
|
]);
|
|
29796
30026
|
var CredentialResponseSchema = external_exports.object({
|
|
29797
30027
|
credentialId: external_exports.uuid(),
|
|
@@ -29834,7 +30064,8 @@ var RotateCredentialSecretRequestSchema = external_exports.discriminatedUnion("c
|
|
|
29834
30064
|
credentialType: external_exports.literal("USERNAME_PASSWORD"),
|
|
29835
30065
|
...SECRET_SHAPES.USERNAME_PASSWORD
|
|
29836
30066
|
}).strict(),
|
|
29837
|
-
external_exports.object({ credentialType: external_exports.literal("SESSION_STATE"), ...SECRET_SHAPES.SESSION_STATE }).strict()
|
|
30067
|
+
external_exports.object({ credentialType: external_exports.literal("SESSION_STATE"), ...SECRET_SHAPES.SESSION_STATE }).strict(),
|
|
30068
|
+
external_exports.object({ credentialType: external_exports.literal("SSH_PRIVATE_KEY"), ...SECRET_SHAPES.SSH_PRIVATE_KEY }).strict()
|
|
29838
30069
|
]);
|
|
29839
30070
|
var SetCredentialMfaRequestSchema = external_exports.object({
|
|
29840
30071
|
kind: external_exports.literal("TOTP"),
|
|
@@ -31186,6 +31417,159 @@ var inboxContract = c19.router({
|
|
|
31186
31417
|
}
|
|
31187
31418
|
});
|
|
31188
31419
|
|
|
31420
|
+
// ../../packages/api-contracts/src/schemas/api/v1/member.api.ts
|
|
31421
|
+
var MemberOrgParamsSchema = OrgIdParamsSchema;
|
|
31422
|
+
var MemberRoleSlugSchema = external_exports.enum(["admin", "analyst", "developer"]);
|
|
31423
|
+
var CreateMemberInvitationRequestSchema = external_exports.object({
|
|
31424
|
+
email: external_exports.email().max(320),
|
|
31425
|
+
roleSlug: MemberRoleSlugSchema.default("developer")
|
|
31426
|
+
});
|
|
31427
|
+
var CreateMemberInvitationResponseSchema = external_exports.object({
|
|
31428
|
+
invitationId: external_exports.string().min(1),
|
|
31429
|
+
email: external_exports.email(),
|
|
31430
|
+
roleSlug: MemberRoleSlugSchema
|
|
31431
|
+
});
|
|
31432
|
+
|
|
31433
|
+
// ../../packages/api-contracts/src/schemas/api/v1/invite-link.api.ts
|
|
31434
|
+
var INVITE_LINK_MIN_EXPIRES_IN_HOURS = 1;
|
|
31435
|
+
var INVITE_LINK_MAX_EXPIRES_IN_HOURS = 24 * 30;
|
|
31436
|
+
var INVITE_LINK_DEFAULT_EXPIRES_IN_HOURS = 24 * 7;
|
|
31437
|
+
var INVITE_LINK_MIN_USES = 1;
|
|
31438
|
+
var INVITE_LINK_MAX_USES = 100;
|
|
31439
|
+
var INVITE_LINK_DEFAULT_MAX_USES = 1;
|
|
31440
|
+
var InviteLinkOrgParamsSchema = OrgIdParamsSchema;
|
|
31441
|
+
var InviteLinkParamsSchema = OrgIdParamsSchema.extend({
|
|
31442
|
+
inviteLinkId: external_exports.uuid()
|
|
31443
|
+
});
|
|
31444
|
+
var InviteLinkTokenSchema = external_exports.string().min(32).max(128).regex(/^[A-Za-z0-9_-]+$/, {
|
|
31445
|
+
message: "token must contain only URL-safe base64 characters"
|
|
31446
|
+
});
|
|
31447
|
+
var InviteLinkTokenParamsSchema = external_exports.object({
|
|
31448
|
+
token: InviteLinkTokenSchema
|
|
31449
|
+
});
|
|
31450
|
+
var CreateInviteLinkRequestSchema = external_exports.object({
|
|
31451
|
+
roleSlug: MemberRoleSlugSchema.default("developer"),
|
|
31452
|
+
expiresInHours: external_exports.number().int().min(INVITE_LINK_MIN_EXPIRES_IN_HOURS).max(INVITE_LINK_MAX_EXPIRES_IN_HOURS).default(INVITE_LINK_DEFAULT_EXPIRES_IN_HOURS),
|
|
31453
|
+
maxUses: external_exports.number().int().min(INVITE_LINK_MIN_USES).max(INVITE_LINK_MAX_USES).default(INVITE_LINK_DEFAULT_MAX_USES)
|
|
31454
|
+
});
|
|
31455
|
+
var InviteLinkStatusSchema = external_exports.enum(["active", "expired", "exhausted", "revoked"]);
|
|
31456
|
+
var InviteLinkResponseSchema = external_exports.object({
|
|
31457
|
+
inviteLinkId: external_exports.uuid(),
|
|
31458
|
+
organizationId: external_exports.uuid(),
|
|
31459
|
+
roleSlug: MemberRoleSlugSchema,
|
|
31460
|
+
status: InviteLinkStatusSchema,
|
|
31461
|
+
expiresAt: external_exports.coerce.date(),
|
|
31462
|
+
maxUses: external_exports.number().int(),
|
|
31463
|
+
useCount: external_exports.number().int(),
|
|
31464
|
+
createdById: external_exports.uuid(),
|
|
31465
|
+
createdByName: external_exports.string(),
|
|
31466
|
+
createdByEmail: external_exports.string(),
|
|
31467
|
+
revokedAt: external_exports.coerce.date().nullable(),
|
|
31468
|
+
createdAt: external_exports.coerce.date()
|
|
31469
|
+
});
|
|
31470
|
+
var CreateInviteLinkResponseSchema = InviteLinkResponseSchema.extend({
|
|
31471
|
+
url: external_exports.url()
|
|
31472
|
+
});
|
|
31473
|
+
var ListInviteLinksResponseSchema = external_exports.array(InviteLinkResponseSchema);
|
|
31474
|
+
var RevokeInviteLinkResponseSchema = external_exports.object({
|
|
31475
|
+
inviteLinkId: external_exports.uuid(),
|
|
31476
|
+
revokedAt: external_exports.coerce.date()
|
|
31477
|
+
});
|
|
31478
|
+
var InviteLinkPreviewResponseSchema = external_exports.object({
|
|
31479
|
+
status: InviteLinkStatusSchema,
|
|
31480
|
+
organizationName: external_exports.string(),
|
|
31481
|
+
organizationLogoUrl: external_exports.string().nullable(),
|
|
31482
|
+
roleSlug: MemberRoleSlugSchema,
|
|
31483
|
+
expiresAt: external_exports.coerce.date()
|
|
31484
|
+
});
|
|
31485
|
+
var AcceptInviteLinkResponseSchema = external_exports.object({
|
|
31486
|
+
/** `joined` created a membership; `already_member` found an active one and consumed nothing. */
|
|
31487
|
+
outcome: external_exports.enum(["joined", "already_member"]),
|
|
31488
|
+
organizationSlug: external_exports.string(),
|
|
31489
|
+
organizationName: external_exports.string(),
|
|
31490
|
+
workosOrganizationId: external_exports.string(),
|
|
31491
|
+
roleSlug: MemberRoleSlugSchema
|
|
31492
|
+
});
|
|
31493
|
+
var AcceptInviteLinkRejectedResponseSchema = ErrorResponseSchema.extend({
|
|
31494
|
+
status: InviteLinkStatusSchema.optional()
|
|
31495
|
+
});
|
|
31496
|
+
|
|
31497
|
+
// ../../packages/api-contracts/src/contracts/v1/invite-link.ts
|
|
31498
|
+
var c20 = initContract();
|
|
31499
|
+
var inviteLinkContract = c20.router({
|
|
31500
|
+
createInviteLink: {
|
|
31501
|
+
method: "POST",
|
|
31502
|
+
path: "/organizations/:organizationId/invite-links",
|
|
31503
|
+
pathParams: InviteLinkOrgParamsSchema,
|
|
31504
|
+
body: CreateInviteLinkRequestSchema,
|
|
31505
|
+
responses: {
|
|
31506
|
+
201: CreateInviteLinkResponseSchema,
|
|
31507
|
+
400: ErrorResponseSchema,
|
|
31508
|
+
401: ErrorResponseSchema,
|
|
31509
|
+
403: ErrorResponseSchema,
|
|
31510
|
+
404: ErrorResponseSchema,
|
|
31511
|
+
500: ErrorResponseSchema
|
|
31512
|
+
}
|
|
31513
|
+
},
|
|
31514
|
+
listInviteLinks: {
|
|
31515
|
+
method: "GET",
|
|
31516
|
+
path: "/organizations/:organizationId/invite-links",
|
|
31517
|
+
pathParams: InviteLinkOrgParamsSchema,
|
|
31518
|
+
responses: {
|
|
31519
|
+
200: ListInviteLinksResponseSchema,
|
|
31520
|
+
401: ErrorResponseSchema,
|
|
31521
|
+
403: ErrorResponseSchema,
|
|
31522
|
+
404: ErrorResponseSchema,
|
|
31523
|
+
500: ErrorResponseSchema
|
|
31524
|
+
}
|
|
31525
|
+
},
|
|
31526
|
+
revokeInviteLink: {
|
|
31527
|
+
method: "DELETE",
|
|
31528
|
+
path: "/organizations/:organizationId/invite-links/:inviteLinkId",
|
|
31529
|
+
pathParams: InviteLinkParamsSchema,
|
|
31530
|
+
responses: {
|
|
31531
|
+
200: RevokeInviteLinkResponseSchema,
|
|
31532
|
+
401: ErrorResponseSchema,
|
|
31533
|
+
403: ErrorResponseSchema,
|
|
31534
|
+
404: ErrorResponseSchema,
|
|
31535
|
+
500: ErrorResponseSchema
|
|
31536
|
+
}
|
|
31537
|
+
}
|
|
31538
|
+
});
|
|
31539
|
+
var inviteLinkPublicContract = c20.router(
|
|
31540
|
+
{
|
|
31541
|
+
previewInviteLink: {
|
|
31542
|
+
method: "GET",
|
|
31543
|
+
path: "/invite-links/:token",
|
|
31544
|
+
pathParams: InviteLinkTokenParamsSchema,
|
|
31545
|
+
responses: {
|
|
31546
|
+
200: InviteLinkPreviewResponseSchema,
|
|
31547
|
+
400: ErrorResponseSchema,
|
|
31548
|
+
404: ErrorResponseSchema,
|
|
31549
|
+
500: ErrorResponseSchema
|
|
31550
|
+
}
|
|
31551
|
+
},
|
|
31552
|
+
acceptInviteLink: {
|
|
31553
|
+
method: "POST",
|
|
31554
|
+
path: "/invite-links/:token/accept",
|
|
31555
|
+
pathParams: InviteLinkTokenParamsSchema,
|
|
31556
|
+
body: c20.noBody(),
|
|
31557
|
+
responses: {
|
|
31558
|
+
200: AcceptInviteLinkResponseSchema,
|
|
31559
|
+
400: ErrorResponseSchema,
|
|
31560
|
+
401: ErrorResponseSchema,
|
|
31561
|
+
404: ErrorResponseSchema,
|
|
31562
|
+
409: AcceptInviteLinkRejectedResponseSchema,
|
|
31563
|
+
503: ErrorResponseSchema,
|
|
31564
|
+
500: ErrorResponseSchema
|
|
31565
|
+
}
|
|
31566
|
+
}
|
|
31567
|
+
},
|
|
31568
|
+
{
|
|
31569
|
+
pathPrefix: "/v1"
|
|
31570
|
+
}
|
|
31571
|
+
);
|
|
31572
|
+
|
|
31189
31573
|
// ../../packages/api-contracts/src/schemas/api/v1/knowledge-base.api.ts
|
|
31190
31574
|
var KnowledgeBaseAuthorSchema = external_exports.object({
|
|
31191
31575
|
userId: external_exports.string(),
|
|
@@ -31217,8 +31601,8 @@ var UpdateKnowledgeBaseResponseSchema = external_exports.object({
|
|
|
31217
31601
|
});
|
|
31218
31602
|
|
|
31219
31603
|
// ../../packages/api-contracts/src/contracts/v1/knowledge-base.ts
|
|
31220
|
-
var
|
|
31221
|
-
var knowledgeBaseContract =
|
|
31604
|
+
var c21 = initContract();
|
|
31605
|
+
var knowledgeBaseContract = c21.router({
|
|
31222
31606
|
getKnowledgeBase: {
|
|
31223
31607
|
method: "GET",
|
|
31224
31608
|
path: "/organizations/:organizationId/knowledge-base",
|
|
@@ -31439,8 +31823,8 @@ var UpdateRepoDocumentContentResponseSchema = external_exports.object({
|
|
|
31439
31823
|
});
|
|
31440
31824
|
|
|
31441
31825
|
// ../../packages/api-contracts/src/contracts/v1/knowledge-document.ts
|
|
31442
|
-
var
|
|
31443
|
-
var knowledgeDocumentContract =
|
|
31826
|
+
var c22 = initContract();
|
|
31827
|
+
var knowledgeDocumentContract = c22.router({
|
|
31444
31828
|
createDocument: {
|
|
31445
31829
|
method: "POST",
|
|
31446
31830
|
path: "/organizations/:organizationId/knowledge-documents",
|
|
@@ -31766,8 +32150,8 @@ var LinearMetadataResponseSchema = external_exports.object({
|
|
|
31766
32150
|
});
|
|
31767
32151
|
|
|
31768
32152
|
// ../../packages/api-contracts/src/contracts/v1/linear-integration.ts
|
|
31769
|
-
var
|
|
31770
|
-
var linearIntegrationContract =
|
|
32153
|
+
var c23 = initContract();
|
|
32154
|
+
var linearIntegrationContract = c23.router({
|
|
31771
32155
|
getLinearIntegration: {
|
|
31772
32156
|
method: "GET",
|
|
31773
32157
|
path: "/organizations/:organizationId/integrations/linear",
|
|
@@ -31785,7 +32169,7 @@ var linearIntegrationContract = c22.router({
|
|
|
31785
32169
|
method: "POST",
|
|
31786
32170
|
path: "/organizations/:organizationId/integrations/linear/connect",
|
|
31787
32171
|
pathParams: OrgIdParamsSchema,
|
|
31788
|
-
body:
|
|
32172
|
+
body: c23.noBody(),
|
|
31789
32173
|
responses: {
|
|
31790
32174
|
200: LinearConnectResponseSchema,
|
|
31791
32175
|
401: ErrorResponseSchema,
|
|
@@ -31800,7 +32184,7 @@ var linearIntegrationContract = c22.router({
|
|
|
31800
32184
|
method: "POST",
|
|
31801
32185
|
path: "/organizations/:organizationId/integrations/linear/disconnect",
|
|
31802
32186
|
pathParams: OrgIdParamsSchema,
|
|
31803
|
-
body:
|
|
32187
|
+
body: c23.noBody(),
|
|
31804
32188
|
responses: {
|
|
31805
32189
|
200: LinearIntegrationResponseSchema,
|
|
31806
32190
|
401: ErrorResponseSchema,
|
|
@@ -31862,8 +32246,8 @@ var linearIntegrationContract = c22.router({
|
|
|
31862
32246
|
});
|
|
31863
32247
|
|
|
31864
32248
|
// ../../packages/api-contracts/src/contracts/v1/linear-tickets.ts
|
|
31865
|
-
var
|
|
31866
|
-
var linearTicketContract =
|
|
32249
|
+
var c24 = initContract();
|
|
32250
|
+
var linearTicketContract = c24.router({
|
|
31867
32251
|
/**
|
|
31868
32252
|
* Push one or more pentest findings to Linear as tickets. Customer-side
|
|
31869
32253
|
* (VIEW_RESULTS + PENTEST capability); non-admins create into the org's
|
|
@@ -31967,8 +32351,8 @@ var LlmProviderKeyResponseSchema = external_exports.object({
|
|
|
31967
32351
|
var ListLlmProviderKeysResponseSchema = external_exports.array(LlmProviderKeyResponseSchema);
|
|
31968
32352
|
|
|
31969
32353
|
// ../../packages/api-contracts/src/contracts/v1/llm-provider-key.ts
|
|
31970
|
-
var
|
|
31971
|
-
var llmProviderKeyContract =
|
|
32354
|
+
var c25 = initContract();
|
|
32355
|
+
var llmProviderKeyContract = c25.router({
|
|
31972
32356
|
createLlmProviderKey: {
|
|
31973
32357
|
method: "POST",
|
|
31974
32358
|
path: "/organizations/:organizationId/llm-provider-keys",
|
|
@@ -32035,22 +32419,9 @@ var llmProviderKeyContract = c24.router({
|
|
|
32035
32419
|
}
|
|
32036
32420
|
});
|
|
32037
32421
|
|
|
32038
|
-
// ../../packages/api-contracts/src/schemas/api/v1/member.api.ts
|
|
32039
|
-
var MemberOrgParamsSchema = OrgIdParamsSchema;
|
|
32040
|
-
var MemberRoleSlugSchema = external_exports.enum(["admin", "analyst", "developer"]);
|
|
32041
|
-
var CreateMemberInvitationRequestSchema = external_exports.object({
|
|
32042
|
-
email: external_exports.email().max(320),
|
|
32043
|
-
roleSlug: MemberRoleSlugSchema.default("developer")
|
|
32044
|
-
});
|
|
32045
|
-
var CreateMemberInvitationResponseSchema = external_exports.object({
|
|
32046
|
-
invitationId: external_exports.string().min(1),
|
|
32047
|
-
email: external_exports.email(),
|
|
32048
|
-
roleSlug: MemberRoleSlugSchema
|
|
32049
|
-
});
|
|
32050
|
-
|
|
32051
32422
|
// ../../packages/api-contracts/src/contracts/v1/member.ts
|
|
32052
|
-
var
|
|
32053
|
-
var memberContract =
|
|
32423
|
+
var c26 = initContract();
|
|
32424
|
+
var memberContract = c26.router({
|
|
32054
32425
|
createInvitation: {
|
|
32055
32426
|
method: "POST",
|
|
32056
32427
|
path: "/organizations/:organizationId/members/invitations",
|
|
@@ -32350,8 +32721,8 @@ var LogoDeleteRequestSchema = external_exports.object({
|
|
|
32350
32721
|
});
|
|
32351
32722
|
|
|
32352
32723
|
// ../../packages/api-contracts/src/contracts/v1/organization.ts
|
|
32353
|
-
var
|
|
32354
|
-
var organizationContract =
|
|
32724
|
+
var c27 = initContract();
|
|
32725
|
+
var organizationContract = c27.router({
|
|
32355
32726
|
listOrganizations: {
|
|
32356
32727
|
method: "GET",
|
|
32357
32728
|
path: "/organizations",
|
|
@@ -32396,6 +32767,23 @@ var organizationContract = c26.router({
|
|
|
32396
32767
|
},
|
|
32397
32768
|
summary: "Create an organization (Trace staff only)"
|
|
32398
32769
|
},
|
|
32770
|
+
// Staff-only, cross-org: removes the tenant from Trace and WorkOS together.
|
|
32771
|
+
// 409 when members, repositories, or retained audit history still reference
|
|
32772
|
+
// the organization; those must be removed first (or cannot be, for WORM rows).
|
|
32773
|
+
deleteOrganizationAsStaff: {
|
|
32774
|
+
method: "DELETE",
|
|
32775
|
+
path: "/staff/organizations/:organizationId",
|
|
32776
|
+
pathParams: OrgIdParamsSchema,
|
|
32777
|
+
responses: {
|
|
32778
|
+
204: DeleteResponseSchema,
|
|
32779
|
+
401: ErrorResponseSchema,
|
|
32780
|
+
403: ErrorResponseSchema,
|
|
32781
|
+
404: ErrorResponseSchema,
|
|
32782
|
+
409: ErrorResponseSchema,
|
|
32783
|
+
500: ErrorResponseSchema
|
|
32784
|
+
},
|
|
32785
|
+
summary: "Delete an organization (Trace staff only)"
|
|
32786
|
+
},
|
|
32399
32787
|
getOrganization: {
|
|
32400
32788
|
method: "GET",
|
|
32401
32789
|
path: "/organizations/:organizationId",
|
|
@@ -32706,7 +33094,7 @@ var organizationContract = c26.router({
|
|
|
32706
33094
|
method: "POST",
|
|
32707
33095
|
path: "/organizations/:organizationId/logos-from-homepage",
|
|
32708
33096
|
pathParams: OrgIdParamsSchema,
|
|
32709
|
-
body:
|
|
33097
|
+
body: c27.type(),
|
|
32710
33098
|
responses: {
|
|
32711
33099
|
200: OrganizationResponseSchema,
|
|
32712
33100
|
// 400 — no homepage set on the organization.
|
|
@@ -33013,8 +33401,8 @@ var ScanReuseSuggestionsResponseSchema = external_exports.object({
|
|
|
33013
33401
|
});
|
|
33014
33402
|
|
|
33015
33403
|
// ../../packages/api-contracts/src/contracts/v1/pentest.ts
|
|
33016
|
-
var
|
|
33017
|
-
var pentestContract =
|
|
33404
|
+
var c28 = initContract();
|
|
33405
|
+
var pentestContract = c28.router({
|
|
33018
33406
|
listPentests: {
|
|
33019
33407
|
method: "GET",
|
|
33020
33408
|
path: "/organizations/:organizationId/pentests",
|
|
@@ -33324,8 +33712,8 @@ var pentestContract = c27.router({
|
|
|
33324
33712
|
});
|
|
33325
33713
|
|
|
33326
33714
|
// ../../packages/api-contracts/src/contracts/v1/pentest-attack-chain.ts
|
|
33327
|
-
var
|
|
33328
|
-
var pentestAttackChainContract =
|
|
33715
|
+
var c29 = initContract();
|
|
33716
|
+
var pentestAttackChainContract = c29.router({
|
|
33329
33717
|
listAttackChains: {
|
|
33330
33718
|
method: "GET",
|
|
33331
33719
|
path: "/organizations/:organizationId/pentests/:pentestId/attack-chains",
|
|
@@ -33424,7 +33812,7 @@ var pentestAttackChainContract = c28.router({
|
|
|
33424
33812
|
method: "DELETE",
|
|
33425
33813
|
path: "/organizations/:organizationId/pentests/:pentestId/attack-chains/:attackChainId",
|
|
33426
33814
|
pathParams: PentestAttackChainIdParamsSchema,
|
|
33427
|
-
body:
|
|
33815
|
+
body: c29.noBody(),
|
|
33428
33816
|
responses: {
|
|
33429
33817
|
200: DeleteResponseSchema,
|
|
33430
33818
|
401: ErrorResponseSchema,
|
|
@@ -33585,8 +33973,8 @@ var ReadAttestationDownloadResponseSchema = external_exports.union([
|
|
|
33585
33973
|
]);
|
|
33586
33974
|
|
|
33587
33975
|
// ../../packages/api-contracts/src/contracts/v1/pentest-attestation.ts
|
|
33588
|
-
var
|
|
33589
|
-
var pentestAttestationContract =
|
|
33976
|
+
var c30 = initContract();
|
|
33977
|
+
var pentestAttestationContract = c30.router({
|
|
33590
33978
|
getDefaults: {
|
|
33591
33979
|
method: "GET",
|
|
33592
33980
|
path: "/organizations/:organizationId/pentests/:pentestId/attestations/defaults",
|
|
@@ -33729,8 +34117,8 @@ var ListPentestAuditLogResponseSchema = external_exports.object({
|
|
|
33729
34117
|
});
|
|
33730
34118
|
|
|
33731
34119
|
// ../../packages/api-contracts/src/contracts/v1/pentest-audit-log.ts
|
|
33732
|
-
var
|
|
33733
|
-
var pentestAuditLogContract =
|
|
34120
|
+
var c31 = initContract();
|
|
34121
|
+
var pentestAuditLogContract = c31.router({
|
|
33734
34122
|
listAuditLog: {
|
|
33735
34123
|
method: "GET",
|
|
33736
34124
|
path: "/organizations/:organizationId/pentests/:pentestId/audit-log",
|
|
@@ -33777,8 +34165,8 @@ var CreatePentestAuthorizedDomainRequestSchema = external_exports.object({
|
|
|
33777
34165
|
}).strict();
|
|
33778
34166
|
|
|
33779
34167
|
// ../../packages/api-contracts/src/contracts/v1/pentest-authorized-domain.ts
|
|
33780
|
-
var
|
|
33781
|
-
var pentestAuthorizedDomainContract =
|
|
34168
|
+
var c32 = initContract();
|
|
34169
|
+
var pentestAuthorizedDomainContract = c32.router({
|
|
33782
34170
|
getPentestAuthorizedScope: {
|
|
33783
34171
|
method: "GET",
|
|
33784
34172
|
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope",
|
|
@@ -33832,8 +34220,8 @@ var PentestEgressResponseSchema = external_exports.object({
|
|
|
33832
34220
|
}).strict();
|
|
33833
34221
|
|
|
33834
34222
|
// ../../packages/api-contracts/src/contracts/v1/pentest-egress.ts
|
|
33835
|
-
var
|
|
33836
|
-
var pentestEgressContract =
|
|
34223
|
+
var c33 = initContract();
|
|
34224
|
+
var pentestEgressContract = c33.router({
|
|
33837
34225
|
getPentestEgress: {
|
|
33838
34226
|
method: "GET",
|
|
33839
34227
|
path: "/staff/pentest-egress",
|
|
@@ -33872,8 +34260,8 @@ var CreatePentestEngagementExclusionRequestSchema = external_exports.object({
|
|
|
33872
34260
|
}).strict();
|
|
33873
34261
|
|
|
33874
34262
|
// ../../packages/api-contracts/src/contracts/v1/pentest-engagement-exclusion.ts
|
|
33875
|
-
var
|
|
33876
|
-
var pentestEngagementExclusionContract =
|
|
34263
|
+
var c34 = initContract();
|
|
34264
|
+
var pentestEngagementExclusionContract = c34.router({
|
|
33877
34265
|
listPentestEngagementExclusions: {
|
|
33878
34266
|
method: "GET",
|
|
33879
34267
|
path: "/organizations/:organizationId/pentests/:pentestId/engagement-exclusions",
|
|
@@ -33937,8 +34325,8 @@ var CreatePentestEnvironmentRequestSchema = external_exports.object({
|
|
|
33937
34325
|
}).strict();
|
|
33938
34326
|
|
|
33939
34327
|
// ../../packages/api-contracts/src/contracts/v1/pentest-environment.ts
|
|
33940
|
-
var
|
|
33941
|
-
var pentestEnvironmentContract =
|
|
34328
|
+
var c35 = initContract();
|
|
34329
|
+
var pentestEnvironmentContract = c35.router({
|
|
33942
34330
|
listPentestEnvironments: {
|
|
33943
34331
|
method: "GET",
|
|
33944
34332
|
path: "/organizations/:organizationId/pentests/:pentestId/environments",
|
|
@@ -33987,8 +34375,8 @@ var pentestEnvironmentContract = c34.router({
|
|
|
33987
34375
|
});
|
|
33988
34376
|
|
|
33989
34377
|
// ../../packages/api-contracts/src/contracts/v1/pentest-finding.ts
|
|
33990
|
-
var
|
|
33991
|
-
var pentestFindingContract =
|
|
34378
|
+
var c36 = initContract();
|
|
34379
|
+
var pentestFindingContract = c36.router({
|
|
33992
34380
|
// ─── Findings ───
|
|
33993
34381
|
listFindings: {
|
|
33994
34382
|
method: "GET",
|
|
@@ -34092,6 +34480,24 @@ var pentestFindingContract = c35.router({
|
|
|
34092
34480
|
500: ErrorResponseSchema
|
|
34093
34481
|
}
|
|
34094
34482
|
},
|
|
34483
|
+
// Same visibility as getCustomerFinding: published findings only, customer DTO,
|
|
34484
|
+
// so the document never carries staff identity or a draft.
|
|
34485
|
+
exportCustomerFindingPdf: {
|
|
34486
|
+
method: "GET",
|
|
34487
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/findings/:pentestFindingId/pdf",
|
|
34488
|
+
pathParams: CustomerPentestFindingIdParamsSchema,
|
|
34489
|
+
summary: "Render one pentest finding as a Trace-branded PDF",
|
|
34490
|
+
description: "Renders the published finding on demand, stores the PDF, and returns a short-lived presigned download URL. An identical export from the same day is reused without a render. The document names the finding, its classification, and its affected repositories only: no people and no organization name appear on it. Rendering shares one browser per API task, so exports are admission-controlled per organization; a 429 means retry after the interval in `details.retryAfterSeconds`.",
|
|
34491
|
+
responses: {
|
|
34492
|
+
200: PentestFindingPdfExportResponseSchema,
|
|
34493
|
+
400: ErrorResponseSchema,
|
|
34494
|
+
401: ErrorResponseSchema,
|
|
34495
|
+
403: ErrorResponseSchema,
|
|
34496
|
+
404: ErrorResponseSchema,
|
|
34497
|
+
429: ErrorResponseSchema,
|
|
34498
|
+
500: ErrorResponseSchema
|
|
34499
|
+
}
|
|
34500
|
+
},
|
|
34095
34501
|
// ─── Evidence (PR 2: surface & curate) ───
|
|
34096
34502
|
listCustomerFindingEvidence: {
|
|
34097
34503
|
method: "GET",
|
|
@@ -34414,6 +34820,25 @@ var pentestFindingContract = c35.router({
|
|
|
34414
34820
|
500: ErrorResponseSchema
|
|
34415
34821
|
}
|
|
34416
34822
|
},
|
|
34823
|
+
// Reader feedback on a published finding: a thumbs up/down, a comment, or both.
|
|
34824
|
+
// Append-only and never a status change (disputes are `contest`). Same auth as
|
|
34825
|
+
// the other customer writes: VIEW_RESULTS + user principal + customer visibility.
|
|
34826
|
+
submitFeedback: {
|
|
34827
|
+
method: "POST",
|
|
34828
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/findings/:pentestFindingId/feedback",
|
|
34829
|
+
pathParams: CustomerPentestFindingIdParamsSchema,
|
|
34830
|
+
body: CreatePentestFindingFeedbackRequestSchema,
|
|
34831
|
+
summary: "Leave feedback on a pentest finding",
|
|
34832
|
+
description: "Records a thumbs up or thumbs down, an optional reason for a thumbs down, and an optional comment. Each reader counts once in the tallies: a new vote replaces the previous one in the count while the change stays in the resolution history. Returns the updated tallies.",
|
|
34833
|
+
responses: {
|
|
34834
|
+
201: PentestFindingFeedbackSummarySchema,
|
|
34835
|
+
400: ErrorResponseSchema,
|
|
34836
|
+
401: ErrorResponseSchema,
|
|
34837
|
+
403: ErrorResponseSchema,
|
|
34838
|
+
404: ErrorResponseSchema,
|
|
34839
|
+
500: ErrorResponseSchema
|
|
34840
|
+
}
|
|
34841
|
+
},
|
|
34417
34842
|
// ─── Contests ───
|
|
34418
34843
|
listContests: {
|
|
34419
34844
|
method: "GET",
|
|
@@ -34544,8 +34969,8 @@ var pentestFindingContract = c35.router({
|
|
|
34544
34969
|
});
|
|
34545
34970
|
|
|
34546
34971
|
// ../../packages/api-contracts/src/contracts/v1/pentest-hypothesis.ts
|
|
34547
|
-
var
|
|
34548
|
-
var pentestHypothesisContract =
|
|
34972
|
+
var c37 = initContract();
|
|
34973
|
+
var pentestHypothesisContract = c37.router({
|
|
34549
34974
|
listHypotheses: {
|
|
34550
34975
|
method: "GET",
|
|
34551
34976
|
path: "/organizations/:organizationId/pentests/:pentestId/hypotheses",
|
|
@@ -34647,9 +35072,148 @@ var pentestHypothesisContract = c36.router({
|
|
|
34647
35072
|
}
|
|
34648
35073
|
});
|
|
34649
35074
|
|
|
35075
|
+
// ../../packages/api-contracts/src/schemas/api/v1/pentest-intake-document.api.ts
|
|
35076
|
+
var PentestIntakeDocumentTypeValues = [
|
|
35077
|
+
"PREVIOUS_PENTEST",
|
|
35078
|
+
"ARCHITECTURE_DIAGRAM",
|
|
35079
|
+
"THREAT_MODEL",
|
|
35080
|
+
"OTHER"
|
|
35081
|
+
];
|
|
35082
|
+
var PentestIntakeDocumentTypeSchema = external_exports.enum(PentestIntakeDocumentTypeValues);
|
|
35083
|
+
var MAX_PENTEST_INTAKE_DOCUMENT_BYTES = 50 * 1024 * 1024;
|
|
35084
|
+
var PentestIntakeDocumentIdParamsSchema = CustomerPentestIdParamsSchema.extend({
|
|
35085
|
+
documentId: external_exports.uuid()
|
|
35086
|
+
});
|
|
35087
|
+
var PentestIntakeDocumentResponseSchema = external_exports.object({
|
|
35088
|
+
documentId: external_exports.uuid(),
|
|
35089
|
+
pentestId: external_exports.uuid(),
|
|
35090
|
+
documentType: PentestIntakeDocumentTypeSchema,
|
|
35091
|
+
fileName: external_exports.string(),
|
|
35092
|
+
fileType: external_exports.string(),
|
|
35093
|
+
fileSizeBytes: external_exports.number().int().nonnegative(),
|
|
35094
|
+
uploadedByName: external_exports.string().nullable(),
|
|
35095
|
+
createdAt: external_exports.coerce.date(),
|
|
35096
|
+
updatedAt: external_exports.coerce.date()
|
|
35097
|
+
});
|
|
35098
|
+
var ListPentestIntakeDocumentsResponseSchema = external_exports.object({
|
|
35099
|
+
/** Mirrors the questionnaire's `editable`: uploads and removals are refused once false. */
|
|
35100
|
+
editable: external_exports.boolean(),
|
|
35101
|
+
documents: external_exports.array(PentestIntakeDocumentResponseSchema)
|
|
35102
|
+
});
|
|
35103
|
+
var CreatePentestIntakeDocumentUploadRequestSchema = external_exports.object({
|
|
35104
|
+
fileName: external_exports.string().min(1).max(255),
|
|
35105
|
+
fileSizeBytes: external_exports.number().int().positive().max(MAX_PENTEST_INTAKE_DOCUMENT_BYTES)
|
|
35106
|
+
}).strict();
|
|
35107
|
+
var CreatePentestIntakeDocumentUploadResponseSchema = external_exports.object({
|
|
35108
|
+
/** Server-minted S3 key; hand it back unchanged on attach. */
|
|
35109
|
+
uploadKey: external_exports.string(),
|
|
35110
|
+
uploadUrl: external_exports.url(),
|
|
35111
|
+
expiresAt: external_exports.coerce.date()
|
|
35112
|
+
});
|
|
35113
|
+
var AttachPentestIntakeDocumentRequestSchema = external_exports.object({
|
|
35114
|
+
uploadKey: external_exports.string().min(1).max(1024),
|
|
35115
|
+
documentType: PentestIntakeDocumentTypeSchema,
|
|
35116
|
+
fileName: external_exports.string().min(1).max(255),
|
|
35117
|
+
fileType: external_exports.string().min(1).max(100)
|
|
35118
|
+
}).strict();
|
|
35119
|
+
var UpdatePentestIntakeDocumentRequestSchema = external_exports.object({
|
|
35120
|
+
documentType: PentestIntakeDocumentTypeSchema
|
|
35121
|
+
}).strict();
|
|
35122
|
+
var DownloadPentestIntakeDocumentResponseSchema = external_exports.object({
|
|
35123
|
+
document: PentestIntakeDocumentResponseSchema,
|
|
35124
|
+
downloadUrl: external_exports.url()
|
|
35125
|
+
});
|
|
35126
|
+
|
|
35127
|
+
// ../../packages/api-contracts/src/contracts/v1/pentest-intake-document.ts
|
|
35128
|
+
var c38 = initContract();
|
|
35129
|
+
var pentestIntakeDocumentContract = c38.router({
|
|
35130
|
+
listDocuments: {
|
|
35131
|
+
method: "GET",
|
|
35132
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents",
|
|
35133
|
+
pathParams: CustomerPentestIdParamsSchema,
|
|
35134
|
+
responses: {
|
|
35135
|
+
200: ListPentestIntakeDocumentsResponseSchema,
|
|
35136
|
+
401: ErrorResponseSchema,
|
|
35137
|
+
403: ErrorResponseSchema,
|
|
35138
|
+
404: ErrorResponseSchema,
|
|
35139
|
+
500: ErrorResponseSchema
|
|
35140
|
+
}
|
|
35141
|
+
},
|
|
35142
|
+
createUpload: {
|
|
35143
|
+
method: "POST",
|
|
35144
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents/uploads",
|
|
35145
|
+
pathParams: CustomerPentestIdParamsSchema,
|
|
35146
|
+
body: CreatePentestIntakeDocumentUploadRequestSchema,
|
|
35147
|
+
responses: {
|
|
35148
|
+
201: CreatePentestIntakeDocumentUploadResponseSchema,
|
|
35149
|
+
400: ErrorResponseSchema,
|
|
35150
|
+
401: ErrorResponseSchema,
|
|
35151
|
+
403: ErrorResponseSchema,
|
|
35152
|
+
404: ErrorResponseSchema,
|
|
35153
|
+
409: ErrorResponseSchema,
|
|
35154
|
+
500: ErrorResponseSchema
|
|
35155
|
+
}
|
|
35156
|
+
},
|
|
35157
|
+
attachDocument: {
|
|
35158
|
+
method: "POST",
|
|
35159
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents",
|
|
35160
|
+
pathParams: CustomerPentestIdParamsSchema,
|
|
35161
|
+
body: AttachPentestIntakeDocumentRequestSchema,
|
|
35162
|
+
responses: {
|
|
35163
|
+
201: PentestIntakeDocumentResponseSchema,
|
|
35164
|
+
400: ErrorResponseSchema,
|
|
35165
|
+
401: ErrorResponseSchema,
|
|
35166
|
+
403: ErrorResponseSchema,
|
|
35167
|
+
404: ErrorResponseSchema,
|
|
35168
|
+
409: ErrorResponseSchema,
|
|
35169
|
+
500: ErrorResponseSchema
|
|
35170
|
+
}
|
|
35171
|
+
},
|
|
35172
|
+
updateDocument: {
|
|
35173
|
+
method: "PATCH",
|
|
35174
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents/:documentId",
|
|
35175
|
+
pathParams: PentestIntakeDocumentIdParamsSchema,
|
|
35176
|
+
body: UpdatePentestIntakeDocumentRequestSchema,
|
|
35177
|
+
responses: {
|
|
35178
|
+
200: PentestIntakeDocumentResponseSchema,
|
|
35179
|
+
400: ErrorResponseSchema,
|
|
35180
|
+
401: ErrorResponseSchema,
|
|
35181
|
+
403: ErrorResponseSchema,
|
|
35182
|
+
404: ErrorResponseSchema,
|
|
35183
|
+
409: ErrorResponseSchema,
|
|
35184
|
+
500: ErrorResponseSchema
|
|
35185
|
+
}
|
|
35186
|
+
},
|
|
35187
|
+
downloadDocument: {
|
|
35188
|
+
method: "GET",
|
|
35189
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents/:documentId/download",
|
|
35190
|
+
pathParams: PentestIntakeDocumentIdParamsSchema,
|
|
35191
|
+
responses: {
|
|
35192
|
+
200: DownloadPentestIntakeDocumentResponseSchema,
|
|
35193
|
+
401: ErrorResponseSchema,
|
|
35194
|
+
403: ErrorResponseSchema,
|
|
35195
|
+
404: ErrorResponseSchema,
|
|
35196
|
+
500: ErrorResponseSchema
|
|
35197
|
+
}
|
|
35198
|
+
},
|
|
35199
|
+
deleteDocument: {
|
|
35200
|
+
method: "DELETE",
|
|
35201
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/documents/:documentId",
|
|
35202
|
+
pathParams: PentestIntakeDocumentIdParamsSchema,
|
|
35203
|
+
responses: {
|
|
35204
|
+
204: DeleteResponseSchema,
|
|
35205
|
+
401: ErrorResponseSchema,
|
|
35206
|
+
403: ErrorResponseSchema,
|
|
35207
|
+
404: ErrorResponseSchema,
|
|
35208
|
+
409: ErrorResponseSchema,
|
|
35209
|
+
500: ErrorResponseSchema
|
|
35210
|
+
}
|
|
35211
|
+
}
|
|
35212
|
+
});
|
|
35213
|
+
|
|
34650
35214
|
// ../../packages/api-contracts/src/contracts/v1/pentest-manual-finding.ts
|
|
34651
|
-
var
|
|
34652
|
-
var pentestManualFindingContract =
|
|
35215
|
+
var c39 = initContract();
|
|
35216
|
+
var pentestManualFindingContract = c39.router({
|
|
34653
35217
|
listManualFindings: {
|
|
34654
35218
|
method: "GET",
|
|
34655
35219
|
path: "/organizations/:organizationId/pentests/:pentestId/manual-findings",
|
|
@@ -34736,8 +35300,8 @@ var pentestManualFindingContract = c37.router({
|
|
|
34736
35300
|
});
|
|
34737
35301
|
|
|
34738
35302
|
// ../../packages/api-contracts/src/contracts/v1/pentest-report-pdf.ts
|
|
34739
|
-
var
|
|
34740
|
-
var pentestReportPdfContract =
|
|
35303
|
+
var c40 = initContract();
|
|
35304
|
+
var pentestReportPdfContract = c40.router({
|
|
34741
35305
|
getCurrent: {
|
|
34742
35306
|
method: "GET",
|
|
34743
35307
|
path: "/organizations/:organizationId/pentests/:pentestId/report-pdf",
|
|
@@ -34830,7 +35394,7 @@ var pentestReportPdfContract = c38.router({
|
|
|
34830
35394
|
// No body: the render always reads current DB state (cover derived via
|
|
34831
35395
|
// deriveReportCover(), narrative/scope from the row's columns). The legacy
|
|
34832
35396
|
// dialog payload was retired with the Generate dialog (report-session RS5).
|
|
34833
|
-
body:
|
|
35397
|
+
body: c40.noBody(),
|
|
34834
35398
|
responses: {
|
|
34835
35399
|
202: StartReportPdfGenerationTaskResponseSchema,
|
|
34836
35400
|
400: ErrorResponseSchema,
|
|
@@ -34955,7 +35519,8 @@ var pentestReportPdfContract = c38.router({
|
|
|
34955
35519
|
403: ErrorResponseSchema,
|
|
34956
35520
|
404: ErrorResponseSchema,
|
|
34957
35521
|
// REPORT_NOT_RENDERED — no PDF exists yet (spec-pr-rs1 §2c) — or
|
|
34958
|
-
// BUNDLE_NOT_RENDERED for artifact=markdown
|
|
35522
|
+
// BUNDLE_NOT_RENDERED / DOCX_NOT_RENDERED for artifact=markdown / docx
|
|
35523
|
+
// with no such object beside the current PDF.
|
|
34959
35524
|
409: ErrorResponseSchema,
|
|
34960
35525
|
500: ErrorResponseSchema
|
|
34961
35526
|
}
|
|
@@ -35012,20 +35577,23 @@ var pentestReportPdfContract = c38.router({
|
|
|
35012
35577
|
method: "GET",
|
|
35013
35578
|
path: "/organizations/:organizationId/customer-pentests/:pentestId/report-pdf/download",
|
|
35014
35579
|
pathParams: CustomerReportPdfPentestParamsSchema,
|
|
35015
|
-
query:
|
|
35580
|
+
query: CustomerReportPdfDownloadQuerySchema,
|
|
35016
35581
|
responses: {
|
|
35017
35582
|
200: CustomerReportPdfDownloadResponseSchema,
|
|
35018
35583
|
401: ErrorResponseSchema,
|
|
35019
35584
|
403: ErrorResponseSchema,
|
|
35020
35585
|
404: ErrorResponseSchema,
|
|
35586
|
+
// DOCX_NOT_RENDERED for artifact=docx when no Word document from the
|
|
35587
|
+
// served render exists.
|
|
35588
|
+
409: ErrorResponseSchema,
|
|
35021
35589
|
500: ErrorResponseSchema
|
|
35022
35590
|
}
|
|
35023
35591
|
}
|
|
35024
35592
|
});
|
|
35025
35593
|
|
|
35026
35594
|
// ../../packages/api-contracts/src/contracts/v1/pentest-validation.ts
|
|
35027
|
-
var
|
|
35028
|
-
var pentestValidationContract =
|
|
35595
|
+
var c41 = initContract();
|
|
35596
|
+
var pentestValidationContract = c41.router({
|
|
35029
35597
|
listValidationRuns: {
|
|
35030
35598
|
method: "GET",
|
|
35031
35599
|
path: "/organizations/:organizationId/pentests/:pentestId/validation-runs",
|
|
@@ -35133,8 +35701,8 @@ var pentestValidationContract = c39.router({
|
|
|
35133
35701
|
});
|
|
35134
35702
|
|
|
35135
35703
|
// ../../packages/api-contracts/src/contracts/v1/repository.ts
|
|
35136
|
-
var
|
|
35137
|
-
var repositoryContract =
|
|
35704
|
+
var c42 = initContract();
|
|
35705
|
+
var repositoryContract = c42.router({
|
|
35138
35706
|
createRepository: {
|
|
35139
35707
|
method: "POST",
|
|
35140
35708
|
path: "/organizations/:organizationId/repositories",
|
|
@@ -35320,7 +35888,7 @@ var repositoryContract = c40.router({
|
|
|
35320
35888
|
method: "POST",
|
|
35321
35889
|
path: "/organizations/:organizationId/repositories/scanning-branch/confirm-defaults",
|
|
35322
35890
|
pathParams: OrgIdParamsSchema,
|
|
35323
|
-
body:
|
|
35891
|
+
body: c42.noBody(),
|
|
35324
35892
|
responses: {
|
|
35325
35893
|
200: ConfirmScanningBranchDefaultsResponseSchema,
|
|
35326
35894
|
401: ErrorResponseSchema,
|
|
@@ -35454,8 +36022,8 @@ var ListScanLogsResponseSchema = external_exports.object({
|
|
|
35454
36022
|
});
|
|
35455
36023
|
|
|
35456
36024
|
// ../../packages/api-contracts/src/contracts/v1/scan.ts
|
|
35457
|
-
var
|
|
35458
|
-
var scanContract =
|
|
36025
|
+
var c43 = initContract();
|
|
36026
|
+
var scanContract = c43.router({
|
|
35459
36027
|
createScan: {
|
|
35460
36028
|
method: "POST",
|
|
35461
36029
|
path: "/organizations/:organizationId/scans",
|
|
@@ -35576,8 +36144,8 @@ var StaffPentestStatsResponseSchema = external_exports.object({
|
|
|
35576
36144
|
}).strict();
|
|
35577
36145
|
|
|
35578
36146
|
// ../../packages/api-contracts/src/contracts/v1/staff-pentest-stats.ts
|
|
35579
|
-
var
|
|
35580
|
-
var staffPentestStatsContract =
|
|
36147
|
+
var c44 = initContract();
|
|
36148
|
+
var staffPentestStatsContract = c44.router({
|
|
35581
36149
|
getStaffPentestStats: {
|
|
35582
36150
|
method: "GET",
|
|
35583
36151
|
path: "/staff/pentest-stats",
|
|
@@ -35591,6 +36159,59 @@ var staffPentestStatsContract = c42.router({
|
|
|
35591
36159
|
}
|
|
35592
36160
|
});
|
|
35593
36161
|
|
|
36162
|
+
// ../../packages/api-contracts/src/schemas/api/v1/staff-pentests.api.ts
|
|
36163
|
+
var StaffOrganizationPentestParamsSchema = OrgIdParamsSchema.extend({
|
|
36164
|
+
pentestId: external_exports.uuid()
|
|
36165
|
+
});
|
|
36166
|
+
var StaffOrganizationPentestSummarySchema = external_exports.object({
|
|
36167
|
+
pentestId: external_exports.uuid(),
|
|
36168
|
+
displayId: external_exports.int().positive(),
|
|
36169
|
+
title: external_exports.string(),
|
|
36170
|
+
status: PentestStatus,
|
|
36171
|
+
currentStage: PentestStage,
|
|
36172
|
+
testType: PentestTestType,
|
|
36173
|
+
/** Bound application names, ordinal-ascending. Empty for an unbound draft. */
|
|
36174
|
+
applicationNames: external_exports.array(external_exports.string()),
|
|
36175
|
+
findingCount: external_exports.int().nonnegative(),
|
|
36176
|
+
startedAt: external_exports.iso.datetime().nullable(),
|
|
36177
|
+
endedAt: external_exports.iso.datetime().nullable(),
|
|
36178
|
+
createdAt: external_exports.iso.datetime()
|
|
36179
|
+
}).strict();
|
|
36180
|
+
var ListStaffOrganizationPentestsResponseSchema = external_exports.array(
|
|
36181
|
+
StaffOrganizationPentestSummarySchema
|
|
36182
|
+
);
|
|
36183
|
+
|
|
36184
|
+
// ../../packages/api-contracts/src/contracts/v1/staff-pentests.ts
|
|
36185
|
+
var c45 = initContract();
|
|
36186
|
+
var staffPentestsContract = c45.router({
|
|
36187
|
+
listStaffOrganizationPentests: {
|
|
36188
|
+
method: "GET",
|
|
36189
|
+
path: "/organizations/:organizationId/staff/pentests",
|
|
36190
|
+
pathParams: OrgIdParamsSchema,
|
|
36191
|
+
responses: {
|
|
36192
|
+
200: ListStaffOrganizationPentestsResponseSchema,
|
|
36193
|
+
401: ErrorResponseSchema,
|
|
36194
|
+
403: ErrorResponseSchema,
|
|
36195
|
+
404: ErrorResponseSchema,
|
|
36196
|
+
500: ErrorResponseSchema
|
|
36197
|
+
},
|
|
36198
|
+
summary: "List an organization\u2019s pentests (Trace staff only)"
|
|
36199
|
+
},
|
|
36200
|
+
deleteStaffOrganizationPentest: {
|
|
36201
|
+
method: "DELETE",
|
|
36202
|
+
path: "/organizations/:organizationId/staff/pentests/:pentestId",
|
|
36203
|
+
pathParams: StaffOrganizationPentestParamsSchema,
|
|
36204
|
+
responses: {
|
|
36205
|
+
204: DeleteResponseSchema,
|
|
36206
|
+
401: ErrorResponseSchema,
|
|
36207
|
+
403: ErrorResponseSchema,
|
|
36208
|
+
404: ErrorResponseSchema,
|
|
36209
|
+
500: ErrorResponseSchema
|
|
36210
|
+
},
|
|
36211
|
+
summary: "Soft-delete a pentest from the admin console (Trace staff only)"
|
|
36212
|
+
}
|
|
36213
|
+
});
|
|
36214
|
+
|
|
35594
36215
|
// ../../packages/api-contracts/src/schemas/api/v1/staff-queue.api.ts
|
|
35595
36216
|
var StaffQueueItemKindValues = [
|
|
35596
36217
|
"RETEST_OWED",
|
|
@@ -35698,8 +36319,8 @@ var StaffQueueResponseSchema = external_exports.object({
|
|
|
35698
36319
|
}).strict();
|
|
35699
36320
|
|
|
35700
36321
|
// ../../packages/api-contracts/src/contracts/v1/staff-queue.ts
|
|
35701
|
-
var
|
|
35702
|
-
var staffQueueContract =
|
|
36322
|
+
var c46 = initContract();
|
|
36323
|
+
var staffQueueContract = c46.router({
|
|
35703
36324
|
getStaffQueue: {
|
|
35704
36325
|
method: "GET",
|
|
35705
36326
|
path: "/staff/queue",
|
|
@@ -35769,8 +36390,8 @@ var AttachTestIntegrationRequestSchema = external_exports.object({
|
|
|
35769
36390
|
}).strict();
|
|
35770
36391
|
|
|
35771
36392
|
// ../../packages/api-contracts/src/contracts/v1/test-integration.ts
|
|
35772
|
-
var
|
|
35773
|
-
var testIntegrationContract =
|
|
36393
|
+
var c47 = initContract();
|
|
36394
|
+
var testIntegrationContract = c47.router({
|
|
35774
36395
|
// -- Fixture CRUD (org-less, staff-only) ----------------------------------
|
|
35775
36396
|
listTestIntegrations: {
|
|
35776
36397
|
method: "GET",
|
|
@@ -35902,8 +36523,8 @@ var MyContextResponseSchema = external_exports.object({
|
|
|
35902
36523
|
});
|
|
35903
36524
|
|
|
35904
36525
|
// ../../packages/api-contracts/src/contracts/v1/user.ts
|
|
35905
|
-
var
|
|
35906
|
-
var userContract =
|
|
36526
|
+
var c48 = initContract();
|
|
36527
|
+
var userContract = c48.router({
|
|
35907
36528
|
getStaffProfile: {
|
|
35908
36529
|
method: "GET",
|
|
35909
36530
|
path: "/staff/profile",
|
|
@@ -36018,8 +36639,8 @@ var VantaIntegrationResponseSchema = external_exports.object({
|
|
|
36018
36639
|
});
|
|
36019
36640
|
|
|
36020
36641
|
// ../../packages/api-contracts/src/contracts/v1/vanta-integration.ts
|
|
36021
|
-
var
|
|
36022
|
-
var vantaIntegrationContract =
|
|
36642
|
+
var c49 = initContract();
|
|
36643
|
+
var vantaIntegrationContract = c49.router({
|
|
36023
36644
|
createVantaIntegration: {
|
|
36024
36645
|
method: "POST",
|
|
36025
36646
|
path: "/organizations/:organizationId/vanta-integration",
|
|
@@ -36151,6 +36772,13 @@ var VulnerabilityResponseSchema = external_exports.object({
|
|
|
36151
36772
|
updatedAt: external_exports.coerce.date()
|
|
36152
36773
|
});
|
|
36153
36774
|
var ListVulnerabilitiesResponseSchema = external_exports.array(VulnerabilityResponseSchema);
|
|
36775
|
+
var VulnerabilityPdfExportResponseSchema = external_exports.object({
|
|
36776
|
+
/** Download name the presigned URL carries, e.g. `TRACE-042-sql-injection.pdf`. */
|
|
36777
|
+
fileName: external_exports.string(),
|
|
36778
|
+
downloadUrl: external_exports.url(),
|
|
36779
|
+
/** False when an identical export already existed and was reused without a render. */
|
|
36780
|
+
rendered: external_exports.boolean()
|
|
36781
|
+
});
|
|
36154
36782
|
var FilterValueSchema = external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]);
|
|
36155
36783
|
var FilterConditionSchema = external_exports.object({
|
|
36156
36784
|
field: external_exports.enum(["repositoryId", "severity", "vulnerabilityType", "status", "cweId", "scanMode"]),
|
|
@@ -36351,8 +36979,8 @@ var VerifySharedVulnerabilityEmailCodeResponseSchema = external_exports.object({
|
|
|
36351
36979
|
});
|
|
36352
36980
|
|
|
36353
36981
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability.ts
|
|
36354
|
-
var
|
|
36355
|
-
var vulnerabilityContract =
|
|
36982
|
+
var c50 = initContract();
|
|
36983
|
+
var vulnerabilityContract = c50.router({
|
|
36356
36984
|
filterVulnerabilities: {
|
|
36357
36985
|
method: "POST",
|
|
36358
36986
|
path: "/organizations/:organizationId/vulnerabilities/filter",
|
|
@@ -36404,6 +37032,22 @@ var vulnerabilityContract = c47.router({
|
|
|
36404
37032
|
500: ErrorResponseSchema
|
|
36405
37033
|
}
|
|
36406
37034
|
},
|
|
37035
|
+
exportVulnerabilityPdf: {
|
|
37036
|
+
method: "GET",
|
|
37037
|
+
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/pdf",
|
|
37038
|
+
pathParams: VulnerabilityLookupIdParamsSchema,
|
|
37039
|
+
summary: "Render one vulnerability as a Trace-branded PDF",
|
|
37040
|
+
description: "Renders the vulnerability on demand, stores the PDF, and returns a short-lived presigned download URL. An identical export from the same day is reused without a render. The document names the finding and its code location only: no people and no organization name appear on it. Rendering shares one browser per API task, so exports are admission-controlled per organization; a 429 means retry after the interval in `details.retryAfterSeconds`.",
|
|
37041
|
+
responses: {
|
|
37042
|
+
200: VulnerabilityPdfExportResponseSchema,
|
|
37043
|
+
400: ErrorResponseSchema,
|
|
37044
|
+
401: ErrorResponseSchema,
|
|
37045
|
+
403: ErrorResponseSchema,
|
|
37046
|
+
404: ErrorResponseSchema,
|
|
37047
|
+
429: ErrorResponseSchema,
|
|
37048
|
+
500: ErrorResponseSchema
|
|
37049
|
+
}
|
|
37050
|
+
},
|
|
36407
37051
|
updateVulnerability: {
|
|
36408
37052
|
method: "PATCH",
|
|
36409
37053
|
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId",
|
|
@@ -36560,8 +37204,8 @@ var UpdateVulnerabilityNoteRequestSchema = external_exports.object({
|
|
|
36560
37204
|
});
|
|
36561
37205
|
|
|
36562
37206
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability-note.ts
|
|
36563
|
-
var
|
|
36564
|
-
var vulnerabilityNoteContract =
|
|
37207
|
+
var c51 = initContract();
|
|
37208
|
+
var vulnerabilityNoteContract = c51.router({
|
|
36565
37209
|
listNotes: {
|
|
36566
37210
|
method: "GET",
|
|
36567
37211
|
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/notes",
|
|
@@ -36742,8 +37386,8 @@ var ListWebhookDeliveriesResponseSchema = external_exports.object({
|
|
|
36742
37386
|
});
|
|
36743
37387
|
|
|
36744
37388
|
// ../../packages/api-contracts/src/contracts/v1/webhook-settings.ts
|
|
36745
|
-
var
|
|
36746
|
-
var webhookSettingsContract =
|
|
37389
|
+
var c52 = initContract();
|
|
37390
|
+
var webhookSettingsContract = c52.router({
|
|
36747
37391
|
listWebhookEndpoints: {
|
|
36748
37392
|
method: "GET",
|
|
36749
37393
|
path: "/organizations/:organizationId/webhook-settings/endpoints",
|
|
@@ -36881,8 +37525,8 @@ var webhookSettingsContract = c49.router({
|
|
|
36881
37525
|
});
|
|
36882
37526
|
|
|
36883
37527
|
// ../../packages/api-contracts/src/contracts/v1/index.ts
|
|
36884
|
-
var
|
|
36885
|
-
var v1Contract =
|
|
37528
|
+
var c53 = initContract();
|
|
37529
|
+
var v1Contract = c53.router(
|
|
36886
37530
|
{
|
|
36887
37531
|
admin: adminContract,
|
|
36888
37532
|
cloudIntegration: cloudIntegrationContract,
|
|
@@ -36911,6 +37555,7 @@ var v1Contract = c50.router(
|
|
|
36911
37555
|
agentTask: agentTaskContract,
|
|
36912
37556
|
verifyApplicationSetup: verifyApplicationSetupContract,
|
|
36913
37557
|
pentest: pentestContract,
|
|
37558
|
+
pentestIntakeDocument: pentestIntakeDocumentContract,
|
|
36914
37559
|
pentestAttestation: pentestAttestationContract,
|
|
36915
37560
|
pentestManualFinding: pentestManualFindingContract,
|
|
36916
37561
|
pentestAuditLog: pentestAuditLogContract,
|
|
@@ -36928,10 +37573,12 @@ var v1Contract = c50.router(
|
|
|
36928
37573
|
inbox: inboxContract,
|
|
36929
37574
|
apiKey: apiKeyContract,
|
|
36930
37575
|
member: memberContract,
|
|
37576
|
+
inviteLink: inviteLinkContract,
|
|
36931
37577
|
engagement: engagementContract,
|
|
36932
37578
|
testIntegration: testIntegrationContract,
|
|
36933
37579
|
pentestEgress: pentestEgressContract,
|
|
36934
37580
|
staffPentestStats: staffPentestStatsContract,
|
|
37581
|
+
staffPentests: staffPentestsContract,
|
|
36935
37582
|
staffQueue: staffQueueContract
|
|
36936
37583
|
},
|
|
36937
37584
|
{
|
|
@@ -36940,8 +37587,8 @@ var v1Contract = c50.router(
|
|
|
36940
37587
|
);
|
|
36941
37588
|
|
|
36942
37589
|
// ../../packages/api-contracts/src/contracts/index.ts
|
|
36943
|
-
var
|
|
36944
|
-
var contract =
|
|
37590
|
+
var c54 = initContract();
|
|
37591
|
+
var contract = c54.router({
|
|
36945
37592
|
v1: v1Contract
|
|
36946
37593
|
});
|
|
36947
37594
|
|
|
@@ -36951,8 +37598,8 @@ var GitHubWebhookResponseSchema = external_exports.object({
|
|
|
36951
37598
|
});
|
|
36952
37599
|
|
|
36953
37600
|
// ../../packages/api-contracts/src/contracts/webhooks/github.ts
|
|
36954
|
-
var
|
|
36955
|
-
var githubWebhookContract =
|
|
37601
|
+
var c55 = initContract();
|
|
37602
|
+
var githubWebhookContract = c55.router(
|
|
36956
37603
|
{
|
|
36957
37604
|
handleWebhook: {
|
|
36958
37605
|
method: "POST",
|
|
@@ -36970,7 +37617,7 @@ var githubWebhookContract = c52.router(
|
|
|
36970
37617
|
pathPrefix: "/webhooks"
|
|
36971
37618
|
}
|
|
36972
37619
|
);
|
|
36973
|
-
var githubReadonlyWebhookContract =
|
|
37620
|
+
var githubReadonlyWebhookContract = c55.router(
|
|
36974
37621
|
{
|
|
36975
37622
|
handleWebhook: {
|
|
36976
37623
|
method: "POST",
|
|
@@ -36990,9 +37637,9 @@ var githubReadonlyWebhookContract = c52.router(
|
|
|
36990
37637
|
);
|
|
36991
37638
|
|
|
36992
37639
|
// ../../packages/api-contracts/src/contracts/webhooks/linear.ts
|
|
36993
|
-
var
|
|
37640
|
+
var c56 = initContract();
|
|
36994
37641
|
var LinearWebhookResponseSchema = external_exports.object({ ok: external_exports.boolean() });
|
|
36995
|
-
var linearWebhookContract =
|
|
37642
|
+
var linearWebhookContract = c56.router(
|
|
36996
37643
|
{
|
|
36997
37644
|
handleWebhook: {
|
|
36998
37645
|
method: "POST",
|
|
@@ -37012,7 +37659,7 @@ var linearWebhookContract = c53.router(
|
|
|
37012
37659
|
);
|
|
37013
37660
|
|
|
37014
37661
|
// ../../packages/api-contracts/src/contracts/forge/bitbucket.ts
|
|
37015
|
-
var
|
|
37662
|
+
var c57 = initContract();
|
|
37016
37663
|
var InstallEventSchema = external_exports.object({
|
|
37017
37664
|
eventType: external_exports.enum(["avi:forge:installed:app", "avi:forge:upgraded:app"]),
|
|
37018
37665
|
context: external_exports.object({ cloudId: external_exports.string().min(1) }).loose(),
|
|
@@ -37041,7 +37688,7 @@ var ForgePairingCodeResponseSchema = external_exports.discriminatedUnion("state"
|
|
|
37041
37688
|
expiresInSeconds: external_exports.number().int()
|
|
37042
37689
|
})
|
|
37043
37690
|
]);
|
|
37044
|
-
var forgeBitbucketContract =
|
|
37691
|
+
var forgeBitbucketContract = c57.router(
|
|
37045
37692
|
{
|
|
37046
37693
|
lifecycle: {
|
|
37047
37694
|
method: "POST",
|
|
@@ -37088,8 +37735,8 @@ var HealthResponseSchema = external_exports.object({
|
|
|
37088
37735
|
});
|
|
37089
37736
|
|
|
37090
37737
|
// ../../packages/api-contracts/src/contracts/health.ts
|
|
37091
|
-
var
|
|
37092
|
-
var healthContract =
|
|
37738
|
+
var c58 = initContract();
|
|
37739
|
+
var healthContract = c58.router({
|
|
37093
37740
|
getHealth: {
|
|
37094
37741
|
method: "GET",
|
|
37095
37742
|
path: "/health",
|
|
@@ -37101,8 +37748,8 @@ var healthContract = c55.router({
|
|
|
37101
37748
|
});
|
|
37102
37749
|
|
|
37103
37750
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability-share.ts
|
|
37104
|
-
var
|
|
37105
|
-
var vulnerabilityShareContract =
|
|
37751
|
+
var c59 = initContract();
|
|
37752
|
+
var vulnerabilityShareContract = c59.router(
|
|
37106
37753
|
{
|
|
37107
37754
|
resolveShareLink: {
|
|
37108
37755
|
method: "GET",
|
|
@@ -37189,8 +37836,8 @@ var UpdatePrVulnerabilityRequestSchema = external_exports.object({
|
|
|
37189
37836
|
});
|
|
37190
37837
|
|
|
37191
37838
|
// ../../packages/api-contracts/src/contracts/v1/pr-vulnerability.ts
|
|
37192
|
-
var
|
|
37193
|
-
var prVulnerabilityContract =
|
|
37839
|
+
var c60 = initContract();
|
|
37840
|
+
var prVulnerabilityContract = c60.router(
|
|
37194
37841
|
{
|
|
37195
37842
|
listPrVulnerabilities: {
|
|
37196
37843
|
method: "GET",
|
|
@@ -37241,7 +37888,7 @@ async function requestDeviceAuthorization(clientId) {
|
|
|
37241
37888
|
}
|
|
37242
37889
|
return await response.json();
|
|
37243
37890
|
}
|
|
37244
|
-
var sleep = (ms) => new Promise((
|
|
37891
|
+
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
37245
37892
|
async function pollForToken(clientId, deviceCode, options = {}) {
|
|
37246
37893
|
const expiresIn = options.expiresIn ?? 300;
|
|
37247
37894
|
let interval = options.interval ?? 5;
|
|
@@ -37926,18 +38573,18 @@ var proto = Object.defineProperties(() => {
|
|
|
37926
38573
|
}
|
|
37927
38574
|
}
|
|
37928
38575
|
});
|
|
37929
|
-
var createStyler = (
|
|
38576
|
+
var createStyler = (open3, close, parent) => {
|
|
37930
38577
|
let openAll;
|
|
37931
38578
|
let closeAll;
|
|
37932
38579
|
if (parent === void 0) {
|
|
37933
|
-
openAll =
|
|
38580
|
+
openAll = open3;
|
|
37934
38581
|
closeAll = close;
|
|
37935
38582
|
} else {
|
|
37936
|
-
openAll = parent.openAll +
|
|
38583
|
+
openAll = parent.openAll + open3;
|
|
37937
38584
|
closeAll = close + parent.closeAll;
|
|
37938
38585
|
}
|
|
37939
38586
|
return {
|
|
37940
|
-
open:
|
|
38587
|
+
open: open3,
|
|
37941
38588
|
close,
|
|
37942
38589
|
openAll,
|
|
37943
38590
|
closeAll,
|
|
@@ -39899,12 +40546,12 @@ function buildApplicationsTable(apps) {
|
|
|
39899
40546
|
repos: String(a2.repositories.length),
|
|
39900
40547
|
url: a2.applicationUrl ? sanitizeDisplay(a2.applicationUrl) : "\u2014"
|
|
39901
40548
|
}));
|
|
39902
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
39903
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
39904
|
-
const typeWidth = Math.max(4, ...cells.map((
|
|
40549
|
+
const idWidth = Math.max(2, ...cells.map((c62) => c62.id.length));
|
|
40550
|
+
const nameWidth = Math.max(4, ...cells.map((c62) => c62.name.length));
|
|
40551
|
+
const typeWidth = Math.max(4, ...cells.map((c62) => c62.type.length));
|
|
39905
40552
|
const header = `${"ID".padEnd(idWidth)} ${"NAME".padEnd(nameWidth)} ${"TYPE".padEnd(typeWidth)} REPOS URL`;
|
|
39906
40553
|
const rows = cells.map(
|
|
39907
|
-
(
|
|
40554
|
+
(c62) => `${c62.id.padEnd(idWidth)} ${c62.name.padEnd(nameWidth)} ${c62.type.padEnd(typeWidth)} ${c62.repos.padStart(5)} ${c62.url}`
|
|
39908
40555
|
);
|
|
39909
40556
|
return { header, rows };
|
|
39910
40557
|
}
|
|
@@ -39924,12 +40571,12 @@ function buildApplicationRepositoriesTable(links) {
|
|
|
39924
40571
|
path: l2.repositoryPath ? sanitizeDisplay(l2.repositoryPath) : "\u2014",
|
|
39925
40572
|
status: formatStatus(l2.repositoryStatus)
|
|
39926
40573
|
}));
|
|
39927
|
-
const nameWidth = Math.max(10, ...cells.map((
|
|
39928
|
-
const roleWidth = Math.max(4, ...cells.map((
|
|
39929
|
-
const pathWidth = Math.max(4, ...cells.map((
|
|
40574
|
+
const nameWidth = Math.max(10, ...cells.map((c62) => c62.name.length));
|
|
40575
|
+
const roleWidth = Math.max(4, ...cells.map((c62) => c62.role.length));
|
|
40576
|
+
const pathWidth = Math.max(4, ...cells.map((c62) => c62.path.length));
|
|
39930
40577
|
const header = `${"REPOSITORY".padEnd(nameWidth)} SCAN ${"ROLE".padEnd(roleWidth)} ${"PATH".padEnd(pathWidth)} STATUS`;
|
|
39931
40578
|
const rows = cells.map(
|
|
39932
|
-
(
|
|
40579
|
+
(c62) => `${c62.name.padEnd(nameWidth)} ${c62.scan.padEnd(4)} ${c62.role.padEnd(roleWidth)} ${c62.path.padEnd(pathWidth)} ${c62.status}`
|
|
39933
40580
|
);
|
|
39934
40581
|
return { header, rows };
|
|
39935
40582
|
}
|
|
@@ -40714,8 +41361,8 @@ function wrapTextWithPrefix(e, r2, o2, t2 = o2, s = o2, n3) {
|
|
|
40714
41361
|
hard: true,
|
|
40715
41362
|
trim: false
|
|
40716
41363
|
}).split(`
|
|
40717
|
-
`).map((
|
|
40718
|
-
const d = n3 ? n3(
|
|
41364
|
+
`).map((c62, i2, m2) => {
|
|
41365
|
+
const d = n3 ? n3(c62, i2) : c62;
|
|
40719
41366
|
return i2 === 0 ? `${t2}${d}` : i2 === m2.length - 1 ? `${s}${d}` : `${o2}${d}`;
|
|
40720
41367
|
}).join(`
|
|
40721
41368
|
`);
|
|
@@ -41213,14 +41860,14 @@ var limitOptions = ({
|
|
|
41213
41860
|
Math.min(l2 - a2 + 3, e.length - a2),
|
|
41214
41861
|
0
|
|
41215
41862
|
));
|
|
41216
|
-
let d = a2 < e.length && f > 0,
|
|
41863
|
+
let d = a2 < e.length && f > 0, c62 = a2 < e.length && f + a2 < e.length;
|
|
41217
41864
|
const W = Math.min(
|
|
41218
41865
|
f + a2,
|
|
41219
41866
|
e.length
|
|
41220
41867
|
), s = [];
|
|
41221
41868
|
let g = 0;
|
|
41222
|
-
d && g++,
|
|
41223
|
-
const T = f + (d ? 1 : 0), y = W - (
|
|
41869
|
+
d && g++, c62 && g++;
|
|
41870
|
+
const T = f + (d ? 1 : 0), y = W - (c62 ? 1 : 0);
|
|
41224
41871
|
for (let t2 = T; t2 < y; t2++) {
|
|
41225
41872
|
const n3 = e[t2], o2 = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o2, i2, {
|
|
41226
41873
|
hard: true,
|
|
@@ -41241,14 +41888,14 @@ var limitOptions = ({
|
|
|
41241
41888
|
u4,
|
|
41242
41889
|
true
|
|
41243
41890
|
);
|
|
41244
|
-
d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u4 && (
|
|
41891
|
+
d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u4 && (c62 || (u4 -= 1), { lineCount: o2, removals: n3 } = E())) : (c62 || (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 && (c62 = true, s.splice(s.length - n3, n3));
|
|
41245
41892
|
}
|
|
41246
41893
|
const x = [];
|
|
41247
41894
|
d && x.push(M);
|
|
41248
41895
|
for (const t2 of s)
|
|
41249
41896
|
for (const n3 of t2)
|
|
41250
41897
|
x.push(n3);
|
|
41251
|
-
return
|
|
41898
|
+
return c62 && x.push(M), x;
|
|
41252
41899
|
};
|
|
41253
41900
|
var confirm = (i2) => {
|
|
41254
41901
|
const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
|
|
@@ -41267,15 +41914,15 @@ var confirm = (i2) => {
|
|
|
41267
41914
|
u4
|
|
41268
41915
|
), o2 = `${e ? `${styleText2("gray", S_BAR)}
|
|
41269
41916
|
` : ""}${f}
|
|
41270
|
-
`,
|
|
41917
|
+
`, c62 = this.value ? a2 : s;
|
|
41271
41918
|
switch (this.state) {
|
|
41272
41919
|
case "submit": {
|
|
41273
41920
|
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
41274
|
-
return `${o2}${r2}${styleText2("dim",
|
|
41921
|
+
return `${o2}${r2}${styleText2("dim", c62)}`;
|
|
41275
41922
|
}
|
|
41276
41923
|
case "cancel": {
|
|
41277
41924
|
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
41278
|
-
return `${o2}${r2}${styleText2(["strikethrough", "dim"],
|
|
41925
|
+
return `${o2}${r2}${styleText2(["strikethrough", "dim"], c62)}${e ? `
|
|
41279
41926
|
${styleText2("gray", S_BAR)}` : ""}`;
|
|
41280
41927
|
}
|
|
41281
41928
|
default: {
|
|
@@ -41423,13 +42070,13 @@ var multiline = (e) => new h({
|
|
|
41423
42070
|
`, m2 = e.placeholder && e.placeholder.length > 0 ? (
|
|
41424
42071
|
// biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
|
|
41425
42072
|
styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1))
|
|
41426
|
-
) : styleText2(["inverse", "hidden"], "_"), a2 = this.userInput ? this.userInputWithCursor : m2, l2 = this.value ?? "",
|
|
42073
|
+
) : styleText2(["inverse", "hidden"], "_"), a2 = this.userInput ? this.userInputWithCursor : m2, l2 = this.value ?? "", c62 = e.showSubmit ? `
|
|
41427
42074
|
${styleText2(this.focused === "submit" ? "cyan" : "dim", "[ submit ]")}` : "";
|
|
41428
42075
|
switch (this.state) {
|
|
41429
42076
|
case "error": {
|
|
41430
42077
|
const n3 = `${styleText2("yellow", S_BAR)} `, r2 = i2 ? wrapTextWithPrefix(e.output, a2, n3, void 0) : a2, u4 = styleText2("yellow", S_BAR_END);
|
|
41431
42078
|
return `${o2}${r2}
|
|
41432
|
-
${u4} ${styleText2("yellow", this.error)}${
|
|
42079
|
+
${u4} ${styleText2("yellow", this.error)}${c62}
|
|
41433
42080
|
`;
|
|
41434
42081
|
}
|
|
41435
42082
|
case "submit": {
|
|
@@ -41457,7 +42104,7 @@ ${u4} ${styleText2("yellow", this.error)}${c59}
|
|
|
41457
42104
|
default: {
|
|
41458
42105
|
const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "", u4 = i2 ? wrapTextWithPrefix(e.output, a2, n3) : a2;
|
|
41459
42106
|
return `${o2}${u4}
|
|
41460
|
-
${r2}${
|
|
42107
|
+
${r2}${c62}
|
|
41461
42108
|
`;
|
|
41462
42109
|
}
|
|
41463
42110
|
}
|
|
@@ -41472,7 +42119,7 @@ var password = (r2) => new u$1({
|
|
|
41472
42119
|
render() {
|
|
41473
42120
|
const e = r2.withGuide ?? settings.withGuide, o2 = `${e ? `${styleText2("gray", S_BAR)}
|
|
41474
42121
|
` : ""}${symbol2(this.state)} ${r2.message}
|
|
41475
|
-
`,
|
|
42122
|
+
`, c62 = this.userInputWithCursor, i2 = this.masked;
|
|
41476
42123
|
switch (this.state) {
|
|
41477
42124
|
case "error": {
|
|
41478
42125
|
const s = e ? `${styleText2("yellow", S_BAR)} ` : "", n3 = e ? `${styleText2("yellow", S_BAR_END)} ` : "", l2 = i2 ?? "";
|
|
@@ -41492,7 +42139,7 @@ ${styleText2("gray", S_BAR)}` : ""}`;
|
|
|
41492
42139
|
}
|
|
41493
42140
|
default: {
|
|
41494
42141
|
const s = e ? `${styleText2("cyan", S_BAR)} ` : "", n3 = e ? styleText2("cyan", S_BAR_END) : "";
|
|
41495
|
-
return `${o2}${s}${
|
|
42142
|
+
return `${o2}${s}${c62}
|
|
41496
42143
|
${n3}
|
|
41497
42144
|
`;
|
|
41498
42145
|
}
|
|
@@ -41508,7 +42155,7 @@ var SELECT_INSTRUCTIONS = [
|
|
|
41508
42155
|
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
41509
42156
|
`${styleText2("dim", "Enter:")} confirm`
|
|
41510
42157
|
];
|
|
41511
|
-
var
|
|
42158
|
+
var c61 = (t2, o2) => t2.includes(`
|
|
41512
42159
|
`) ? t2.split(`
|
|
41513
42160
|
`).map((d) => o2(d)).join(`
|
|
41514
42161
|
`) : o2(t2);
|
|
@@ -41519,15 +42166,15 @@ var select = (t2) => {
|
|
|
41519
42166
|
const s = n3.label ?? String(n3.value);
|
|
41520
42167
|
switch (m2) {
|
|
41521
42168
|
case "disabled":
|
|
41522
|
-
return `${styleText2("gray", S_RADIO_INACTIVE)} ${
|
|
42169
|
+
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c61(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
|
|
41523
42170
|
case "selected":
|
|
41524
|
-
return `${
|
|
42171
|
+
return `${c61(s, (i2) => styleText2("dim", i2))}`;
|
|
41525
42172
|
case "active":
|
|
41526
42173
|
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
|
|
41527
42174
|
case "cancelled":
|
|
41528
|
-
return `${
|
|
42175
|
+
return `${c61(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
|
|
41529
42176
|
default:
|
|
41530
|
-
return `${styleText2("dim", S_RADIO_INACTIVE)} ${
|
|
42177
|
+
return `${styleText2("dim", S_RADIO_INACTIVE)} ${c61(s, (i2) => styleText2("dim", i2))}`;
|
|
41531
42178
|
}
|
|
41532
42179
|
}, d = t2.showInstructions ?? true;
|
|
41533
42180
|
return new n$1({
|
|
@@ -42907,7 +43554,7 @@ function extractCommandTree(cmd) {
|
|
|
42907
43554
|
description: o2.description,
|
|
42908
43555
|
takesValue: o2.required || o2.optional
|
|
42909
43556
|
}));
|
|
42910
|
-
const subcommands = cmd.commands.filter((
|
|
43557
|
+
const subcommands = cmd.commands.filter((c62) => !c62._hidden).map((c62) => extractCommandTree(c62));
|
|
42911
43558
|
return {
|
|
42912
43559
|
name: cmd.name(),
|
|
42913
43560
|
description: cmd.description(),
|
|
@@ -42973,7 +43620,7 @@ function generateBashCompletion(tree, binName) {
|
|
|
42973
43620
|
}
|
|
42974
43621
|
function collectBashCases(tree, prefix) {
|
|
42975
43622
|
const cases = /* @__PURE__ */ new Map();
|
|
42976
|
-
const subcommandNames = tree.subcommands.map((
|
|
43623
|
+
const subcommandNames = tree.subcommands.map((c62) => c62.name);
|
|
42977
43624
|
const optionNames = tree.options.flatMap((o2) => o2.short ? [o2.long, o2.short] : [o2.long]);
|
|
42978
43625
|
const extraOptions = prefix === "" ? ["--help", "--version"] : ["--help"];
|
|
42979
43626
|
const allOptions = [.../* @__PURE__ */ new Set([...optionNames, ...extraOptions])];
|
|
@@ -43388,9 +44035,9 @@ function buildInboxesTable(inboxes) {
|
|
|
43388
44035
|
address: sanitizeDisplay(inbox.address),
|
|
43389
44036
|
label: sanitizeDisplay(inbox.label)
|
|
43390
44037
|
}));
|
|
43391
|
-
const addressWidth = Math.max(7, ...cells.map((
|
|
44038
|
+
const addressWidth = Math.max(7, ...cells.map((c62) => c62.address.length));
|
|
43392
44039
|
const header = `${"ADDRESS".padEnd(addressWidth)} LABEL`;
|
|
43393
|
-
const rows = cells.map((
|
|
44040
|
+
const rows = cells.map((c62) => `${c62.address.padEnd(addressWidth)} ${c62.label}`);
|
|
43394
44041
|
return { header, rows };
|
|
43395
44042
|
}
|
|
43396
44043
|
function formatInboxQuota(quota) {
|
|
@@ -43414,14 +44061,14 @@ function buildInboxEmailsTable(messages) {
|
|
|
43414
44061
|
subject: sanitizeDisplay(message.subject ?? ""),
|
|
43415
44062
|
unread: message.unread ? "yes" : "no"
|
|
43416
44063
|
}));
|
|
43417
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
43418
|
-
const receivedWidth = Math.max(8, ...cells.map((
|
|
43419
|
-
const fromWidth = Math.max(4, ...cells.map((
|
|
43420
|
-
const toWidth = Math.max(2, ...cells.map((
|
|
43421
|
-
const subjectWidth = Math.max(7, ...cells.map((
|
|
44064
|
+
const idWidth = Math.max(2, ...cells.map((c62) => c62.id.length));
|
|
44065
|
+
const receivedWidth = Math.max(8, ...cells.map((c62) => c62.received.length));
|
|
44066
|
+
const fromWidth = Math.max(4, ...cells.map((c62) => c62.from.length));
|
|
44067
|
+
const toWidth = Math.max(2, ...cells.map((c62) => c62.to.length));
|
|
44068
|
+
const subjectWidth = Math.max(7, ...cells.map((c62) => c62.subject.length));
|
|
43422
44069
|
const header = `${"ID".padEnd(idWidth)} ${"RECEIVED".padEnd(receivedWidth)} ${"FROM".padEnd(fromWidth)} ${"TO".padEnd(toWidth)} ${"SUBJECT".padEnd(subjectWidth)} UNREAD`;
|
|
43423
44070
|
const rows = cells.map(
|
|
43424
|
-
(
|
|
44071
|
+
(c62) => `${c62.id.padEnd(idWidth)} ${c62.received.padEnd(receivedWidth)} ${c62.from.padEnd(fromWidth)} ${c62.to.padEnd(toWidth)} ${c62.subject.padEnd(subjectWidth)} ${c62.unread}`
|
|
43425
44072
|
);
|
|
43426
44073
|
return { header, rows };
|
|
43427
44074
|
}
|
|
@@ -43827,7 +44474,9 @@ var CREDENTIAL_TYPE_BY_INPUT = {
|
|
|
43827
44474
|
"magic-auth": "MAGIC_AUTH",
|
|
43828
44475
|
magic_auth: "MAGIC_AUTH",
|
|
43829
44476
|
"session-state": "SESSION_STATE",
|
|
43830
|
-
session_state: "SESSION_STATE"
|
|
44477
|
+
session_state: "SESSION_STATE",
|
|
44478
|
+
"ssh-private-key": "SSH_PRIVATE_KEY",
|
|
44479
|
+
ssh_private_key: "SSH_PRIVATE_KEY"
|
|
43831
44480
|
};
|
|
43832
44481
|
function normalizeCredentialType(input) {
|
|
43833
44482
|
return CREDENTIAL_TYPE_BY_INPUT[input.trim().toLowerCase()] ?? null;
|
|
@@ -43849,7 +44498,11 @@ var AUTH_FLAG_KEBAB = {
|
|
|
43849
44498
|
passwordField: "password-field",
|
|
43850
44499
|
sessionCookieName: "session-cookie-name",
|
|
43851
44500
|
csrfTokenSelector: "csrf-token-selector",
|
|
43852
|
-
csrfFieldName: "csrf-field-name"
|
|
44501
|
+
csrfFieldName: "csrf-field-name",
|
|
44502
|
+
sshHost: "ssh-host",
|
|
44503
|
+
sshPort: "ssh-port",
|
|
44504
|
+
sshUsername: "ssh-username",
|
|
44505
|
+
sshHostKeyFingerprint: "ssh-host-key-fingerprint"
|
|
43853
44506
|
};
|
|
43854
44507
|
var ALL_AUTH_KEYS = Object.keys(AUTH_FLAG_KEBAB);
|
|
43855
44508
|
var ALLOWED_AUTH_KEYS = {
|
|
@@ -43869,7 +44522,8 @@ var ALLOWED_AUTH_KEYS = {
|
|
|
43869
44522
|
COOKIE: ["cookieName", "cookieDomain", "cookiePath"],
|
|
43870
44523
|
MAGIC_AUTH: [],
|
|
43871
44524
|
// SESSION_STATE takes no authConfig flags — origin is server-derived from the blob.
|
|
43872
|
-
SESSION_STATE: []
|
|
44525
|
+
SESSION_STATE: [],
|
|
44526
|
+
SSH_PRIVATE_KEY: ["sshHost", "sshPort", "sshUsername", "sshHostKeyFingerprint"]
|
|
43873
44527
|
};
|
|
43874
44528
|
function rejectForeignAuthFlags(type, opts) {
|
|
43875
44529
|
const allowed = new Set(ALLOWED_AUTH_KEYS[type]);
|
|
@@ -43913,6 +44567,13 @@ function authConfigToOptions(authConfig) {
|
|
|
43913
44567
|
return {};
|
|
43914
44568
|
case "SESSION_STATE":
|
|
43915
44569
|
return {};
|
|
44570
|
+
case "SSH_PRIVATE_KEY":
|
|
44571
|
+
return {
|
|
44572
|
+
sshHost: authConfig.host,
|
|
44573
|
+
sshPort: String(authConfig.port),
|
|
44574
|
+
sshUsername: authConfig.username,
|
|
44575
|
+
...authConfig.hostKeyFingerprint !== void 0 ? { sshHostKeyFingerprint: authConfig.hostKeyFingerprint } : {}
|
|
44576
|
+
};
|
|
43916
44577
|
case "USERNAME_PASSWORD":
|
|
43917
44578
|
return {
|
|
43918
44579
|
method: authConfig.method,
|
|
@@ -44006,6 +44667,34 @@ function buildUsernamePasswordAuthConfig(opts) {
|
|
|
44006
44667
|
}
|
|
44007
44668
|
};
|
|
44008
44669
|
}
|
|
44670
|
+
function buildSshPrivateKeyAuthConfig(opts) {
|
|
44671
|
+
const hasAny = opts.sshHost !== void 0 || opts.sshPort !== void 0 || opts.sshUsername !== void 0 || opts.sshHostKeyFingerprint !== void 0;
|
|
44672
|
+
if (!hasAny) {
|
|
44673
|
+
return { value: void 0 };
|
|
44674
|
+
}
|
|
44675
|
+
if (opts.sshHost === void 0 || opts.sshUsername === void 0) {
|
|
44676
|
+
return { error: "--ssh-host and --ssh-username are required for ssh-private-key." };
|
|
44677
|
+
}
|
|
44678
|
+
let port = SSH_DEFAULT_PORT;
|
|
44679
|
+
if (opts.sshPort !== void 0) {
|
|
44680
|
+
if (!/^\d{1,5}$/.test(opts.sshPort.trim())) {
|
|
44681
|
+
return { error: "--ssh-port must be a whole number from 1 to 65535." };
|
|
44682
|
+
}
|
|
44683
|
+
port = Number(opts.sshPort.trim());
|
|
44684
|
+
if (port < 1 || port > 65535) {
|
|
44685
|
+
return { error: "--ssh-port must be a whole number from 1 to 65535." };
|
|
44686
|
+
}
|
|
44687
|
+
}
|
|
44688
|
+
return {
|
|
44689
|
+
value: {
|
|
44690
|
+
type: "SSH_PRIVATE_KEY",
|
|
44691
|
+
host: opts.sshHost,
|
|
44692
|
+
port,
|
|
44693
|
+
username: opts.sshUsername,
|
|
44694
|
+
...opts.sshHostKeyFingerprint !== void 0 ? { hostKeyFingerprint: opts.sshHostKeyFingerprint } : {}
|
|
44695
|
+
}
|
|
44696
|
+
};
|
|
44697
|
+
}
|
|
44009
44698
|
function buildAuthConfig(type, opts) {
|
|
44010
44699
|
switch (type) {
|
|
44011
44700
|
case "BEARER_TOKEN":
|
|
@@ -44020,6 +44709,8 @@ function buildAuthConfig(type, opts) {
|
|
|
44020
44709
|
return buildMagicAuthAuthConfig(opts);
|
|
44021
44710
|
case "USERNAME_PASSWORD":
|
|
44022
44711
|
return buildUsernamePasswordAuthConfig(opts);
|
|
44712
|
+
case "SSH_PRIVATE_KEY":
|
|
44713
|
+
return buildSshPrivateKeyAuthConfig(opts);
|
|
44023
44714
|
case "PASSPHRASE":
|
|
44024
44715
|
case "SESSION_STATE":
|
|
44025
44716
|
return { value: void 0 };
|
|
@@ -44028,6 +44719,9 @@ function buildAuthConfig(type, opts) {
|
|
|
44028
44719
|
function anySecretFlag(opts) {
|
|
44029
44720
|
return opts.secretStdin === true || opts.secretFile !== void 0 || opts.secretEnv !== void 0 || opts.usernameStdin === true || opts.usernameFile !== void 0 || opts.usernameEnv !== void 0 || opts.passwordStdin === true || opts.passwordFile !== void 0 || opts.passwordEnv !== void 0;
|
|
44030
44721
|
}
|
|
44722
|
+
function anyPasswordFlag(opts) {
|
|
44723
|
+
return opts.passwordStdin === true || opts.passwordFile !== void 0 || opts.passwordEnv !== void 0;
|
|
44724
|
+
}
|
|
44031
44725
|
function secretOpts(opts) {
|
|
44032
44726
|
return { stdin: opts.secretStdin, file: opts.secretFile, env: opts.secretEnv };
|
|
44033
44727
|
}
|
|
@@ -44149,16 +44843,16 @@ function printCredentialsTsv(creds) {
|
|
|
44149
44843
|
}
|
|
44150
44844
|
}
|
|
44151
44845
|
function buildCredentialsTable(creds) {
|
|
44152
|
-
const cells = creds.map((
|
|
44153
|
-
id:
|
|
44154
|
-
label: sanitizeDisplay(
|
|
44155
|
-
type:
|
|
44846
|
+
const cells = creds.map((c62) => ({
|
|
44847
|
+
id: c62.credentialId,
|
|
44848
|
+
label: sanitizeDisplay(c62.label),
|
|
44849
|
+
type: c62.credentialType
|
|
44156
44850
|
}));
|
|
44157
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
44158
|
-
const labelWidth = Math.max(5, ...cells.map((
|
|
44851
|
+
const idWidth = Math.max(2, ...cells.map((c62) => c62.id.length));
|
|
44852
|
+
const labelWidth = Math.max(5, ...cells.map((c62) => c62.label.length));
|
|
44159
44853
|
const header = `${"ID".padEnd(idWidth)} ${"LABEL".padEnd(labelWidth)} TYPE`;
|
|
44160
44854
|
const rows = cells.map(
|
|
44161
|
-
(
|
|
44855
|
+
(c62) => `${c62.id.padEnd(idWidth)} ${c62.label.padEnd(labelWidth)} ${c62.type}`
|
|
44162
44856
|
);
|
|
44163
44857
|
return { header, rows };
|
|
44164
44858
|
}
|
|
@@ -44189,6 +44883,14 @@ function failAuthBuild(result) {
|
|
|
44189
44883
|
console.error(colorError(result.error));
|
|
44190
44884
|
process.exit(1);
|
|
44191
44885
|
}
|
|
44886
|
+
function requireSshAuthConfig(options) {
|
|
44887
|
+
const ac = buildSshPrivateKeyAuthConfig(options);
|
|
44888
|
+
if ("error" in ac) failAuthBuild(ac);
|
|
44889
|
+
if (ac.value === void 0) {
|
|
44890
|
+
failAuthBuild({ error: "--ssh-host and --ssh-username are required for ssh-private-key." });
|
|
44891
|
+
}
|
|
44892
|
+
return ac.value;
|
|
44893
|
+
}
|
|
44192
44894
|
async function runCreate3(options) {
|
|
44193
44895
|
const output = parseOutput(options.output);
|
|
44194
44896
|
requireEnvId(options.env);
|
|
@@ -44212,6 +44914,17 @@ async function runCreate3(options) {
|
|
|
44212
44914
|
);
|
|
44213
44915
|
process.exit(1);
|
|
44214
44916
|
}
|
|
44917
|
+
if (type === "SSH_PRIVATE_KEY") {
|
|
44918
|
+
requireSshAuthConfig(options);
|
|
44919
|
+
if (usesStdin(secretOpts(options)) && usesStdin(passwordOpts(options))) {
|
|
44920
|
+
console.error(
|
|
44921
|
+
colorError(
|
|
44922
|
+
"Only one secret can come from stdin. Use --password-file/-env for the passphrase."
|
|
44923
|
+
)
|
|
44924
|
+
);
|
|
44925
|
+
process.exit(1);
|
|
44926
|
+
}
|
|
44927
|
+
}
|
|
44215
44928
|
const organizationId = await resolveOrganizationId();
|
|
44216
44929
|
const params = { organizationId, environmentId: options.env };
|
|
44217
44930
|
const label = options.label?.trim() ? options.label.trim() : void 0;
|
|
@@ -44284,6 +44997,18 @@ async function buildCreateBody(type, label, options) {
|
|
|
44284
44997
|
);
|
|
44285
44998
|
return { credentialType: "SESSION_STATE", ...labelFields, secretValue };
|
|
44286
44999
|
}
|
|
45000
|
+
case "SSH_PRIVATE_KEY": {
|
|
45001
|
+
const authConfig = requireSshAuthConfig(options);
|
|
45002
|
+
const privateKeyPem = await resolveSecret("private key PEM", "secret", secretOpts(options));
|
|
45003
|
+
const passphrase = anyPasswordFlag(options) ? await resolveSecret("key passphrase", "password", passwordOpts(options)) : void 0;
|
|
45004
|
+
return {
|
|
45005
|
+
credentialType: "SSH_PRIVATE_KEY",
|
|
45006
|
+
...labelFields,
|
|
45007
|
+
privateKeyPem,
|
|
45008
|
+
...passphrase !== void 0 ? { passphrase } : {},
|
|
45009
|
+
authConfig
|
|
45010
|
+
};
|
|
45011
|
+
}
|
|
44287
45012
|
case "COOKIE": {
|
|
44288
45013
|
const ac = buildCookieAuthConfig(options);
|
|
44289
45014
|
if ("error" in ac) failAuthBuild(ac);
|
|
@@ -44566,12 +45291,15 @@ function addSecretInputOptions(command) {
|
|
|
44566
45291
|
return command.option("--secret-stdin", "Read the secret value from stdin").option("--secret-file <path>", "Read the secret value from a file").option("--secret-env <name>", "Read the secret value from an env var").option("--username-stdin", "Read the username from stdin").option("--username-file <path>", "Read the username from a file").option("--username-env <name>", "Read the username from an env var").option("--password-stdin", "Read the password from stdin").option("--password-file <path>", "Read the password from a file").option("--password-env <name>", "Read the password from an env var");
|
|
44567
45292
|
}
|
|
44568
45293
|
function addAuthConfigOptions(command) {
|
|
44569
|
-
return command.option("--header-name <name>", "authConfig: header name (bearer-token/jwt-token)").option("--token-prefix <prefix>", "authConfig: token prefix (bearer-token/jwt-token)").option("--placement <header|query>", "authConfig: API key placement (api-key)").option("--key-name <name>", "authConfig: API key name (api-key)").option("--cookie-name <name>", "authConfig: cookie name (cookie)").option("--cookie-domain <domain>", "authConfig: cookie domain (cookie)").option("--cookie-path <path>", "authConfig: cookie path (cookie)").option("--method <form|basic|json>", "authConfig: login method (username-password)").option("--login-url <url>", "authConfig: login URL (username-password)").option("--username-field <name>", "authConfig: username field (username-password)").option("--password-field <name>", "authConfig: password field (username-password)").option("--session-cookie-name <name>", "authConfig: session cookie (username-password)").option("--csrf-token-selector <sel>", "authConfig: CSRF token selector (username-password)").option("--csrf-field-name <name>", "authConfig: CSRF field name (username-password)")
|
|
45294
|
+
return command.option("--header-name <name>", "authConfig: header name (bearer-token/jwt-token)").option("--token-prefix <prefix>", "authConfig: token prefix (bearer-token/jwt-token)").option("--placement <header|query>", "authConfig: API key placement (api-key)").option("--key-name <name>", "authConfig: API key name (api-key)").option("--cookie-name <name>", "authConfig: cookie name (cookie)").option("--cookie-domain <domain>", "authConfig: cookie domain (cookie)").option("--cookie-path <path>", "authConfig: cookie path (cookie)").option("--method <form|basic|json>", "authConfig: login method (username-password)").option("--login-url <url>", "authConfig: login URL (username-password)").option("--username-field <name>", "authConfig: username field (username-password)").option("--password-field <name>", "authConfig: password field (username-password)").option("--session-cookie-name <name>", "authConfig: session cookie (username-password)").option("--csrf-token-selector <sel>", "authConfig: CSRF token selector (username-password)").option("--csrf-field-name <name>", "authConfig: CSRF field name (username-password)").option("--ssh-host <host>", "authConfig: SSH host (ssh-private-key, required)").option("--ssh-port <port>", "authConfig: SSH port, 1-65535 (ssh-private-key, default 22)").option("--ssh-username <user>", "authConfig: SSH username (ssh-private-key, required)").option(
|
|
45295
|
+
"--ssh-host-key-fingerprint <fp>",
|
|
45296
|
+
"authConfig: expected host key, SHA256:<base64> (ssh-private-key)"
|
|
45297
|
+
);
|
|
44570
45298
|
}
|
|
44571
45299
|
function createCreateCommand3() {
|
|
44572
45300
|
const command = new Command("create").description("Create a credential in an environment").requiredOption("--env <environmentId>", "Parent environment UUID").requiredOption(
|
|
44573
45301
|
"--type <type>",
|
|
44574
|
-
"bearer-token, jwt-token, api-key, passphrase, username-password, cookie, magic-auth"
|
|
45302
|
+
"bearer-token, jwt-token, api-key, passphrase, username-password, cookie, magic-auth, session-state, ssh-private-key"
|
|
44575
45303
|
).option(
|
|
44576
45304
|
"--label <label>",
|
|
44577
45305
|
"Human-readable label (optional; defaults from type / username + environment)"
|
|
@@ -44588,7 +45316,9 @@ Examples:
|
|
|
44588
45316
|
tracecli credential create --env <envId> --type api-key --label "prod key" --secret-env API_KEY --placement header --key-name X-API-Key
|
|
44589
45317
|
tracecli credential create --env <envId> --type username-password --username-env U --password-env P --method form --login-url https://acme.com/login
|
|
44590
45318
|
ADDRESS=$(tracecli inbox create portal -o json | jq -r .address)
|
|
44591
|
-
echo "$ADDRESS" | tracecli credential create --env <envId> --type magic-auth --secret-stdin
|
|
45319
|
+
echo "$ADDRESS" | tracecli credential create --env <envId> --type magic-auth --secret-stdin
|
|
45320
|
+
tracecli credential create --env <envId> --type ssh-private-key --secret-file ~/.ssh/bastion_ed25519 --ssh-host bastion.example.com --ssh-username deploy
|
|
45321
|
+
tracecli credential create --env <envId> --type ssh-private-key --secret-file ./key.pem --password-env KEY_PASSPHRASE --ssh-host 10.0.0.5 --ssh-port 2222 --ssh-username ops`
|
|
44592
45322
|
);
|
|
44593
45323
|
return command.action(async (options) => {
|
|
44594
45324
|
await runCreate3(options);
|
|
@@ -44886,14 +45616,14 @@ function buildEnvironmentTable(envs, leading) {
|
|
|
44886
45616
|
url: e.primaryUrl != null ? sanitizeDisplay(e.primaryUrl) : "\u2014"
|
|
44887
45617
|
}));
|
|
44888
45618
|
const leadingWidths = leading.map(
|
|
44889
|
-
(column, i2) => Math.max(column.header.length, ...cells.map((
|
|
45619
|
+
(column, i2) => Math.max(column.header.length, ...cells.map((c62) => c62.leading[i2]?.length ?? 0))
|
|
44890
45620
|
);
|
|
44891
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
45621
|
+
const nameWidth = Math.max(4, ...cells.map((c62) => c62.name.length));
|
|
44892
45622
|
const padLeading = (values) => values.map((v, i2) => v.padEnd(leadingWidths[i2] ?? 0)).join(" ");
|
|
44893
45623
|
return {
|
|
44894
|
-
header: `${padLeading(leading.map((
|
|
45624
|
+
header: `${padLeading(leading.map((c62) => c62.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
|
|
44895
45625
|
rows: cells.map(
|
|
44896
|
-
(
|
|
45626
|
+
(c62) => `${padLeading(c62.leading)} ${c62.name.padEnd(nameWidth)} ${c62.prod.padEnd(4)} ${c62.url}`
|
|
44897
45627
|
)
|
|
44898
45628
|
};
|
|
44899
45629
|
}
|
|
@@ -47291,6 +48021,11 @@ Examples:
|
|
|
47291
48021
|
});
|
|
47292
48022
|
}
|
|
47293
48023
|
|
|
48024
|
+
// src/upload/download.ts
|
|
48025
|
+
import { createHash as createHash2 } from "crypto";
|
|
48026
|
+
import { open as open2, rename, rm, stat } from "fs/promises";
|
|
48027
|
+
import { basename as basename4, join as join7, resolve } from "path";
|
|
48028
|
+
|
|
47294
48029
|
// src/upload/prepare.ts
|
|
47295
48030
|
import { createHash } from "crypto";
|
|
47296
48031
|
import { createReadStream, statSync as statSync4 } from "fs";
|
|
@@ -47434,6 +48169,128 @@ async function prepareUploadFile(filePath, options = {}) {
|
|
|
47434
48169
|
};
|
|
47435
48170
|
}
|
|
47436
48171
|
|
|
48172
|
+
// src/upload/download.ts
|
|
48173
|
+
var CodeUploadDownloadError = class extends Error {
|
|
48174
|
+
constructor(message) {
|
|
48175
|
+
super(message);
|
|
48176
|
+
this.name = "CodeUploadDownloadError";
|
|
48177
|
+
}
|
|
48178
|
+
};
|
|
48179
|
+
function safeDownloadFilename(upload) {
|
|
48180
|
+
const extension = requiredExtensionForKind(upload.artifactKind);
|
|
48181
|
+
const fallback = `app${extension}`;
|
|
48182
|
+
const stripped = Array.from(basename4(upload.originalFilename.replace(/\\/g, "/")), (char) => {
|
|
48183
|
+
const code = char.codePointAt(0) ?? 0;
|
|
48184
|
+
return code <= 31 || code === 127 ? "_" : char;
|
|
48185
|
+
}).join("").trim();
|
|
48186
|
+
if (stripped.length === 0 || stripped === "." || stripped === "..") return fallback;
|
|
48187
|
+
return stripped.toLowerCase().endsWith(extension) ? stripped : `${stripped}${extension}`;
|
|
48188
|
+
}
|
|
48189
|
+
async function resolveDownloadDestination(upload, outOption) {
|
|
48190
|
+
const filename = safeDownloadFilename(upload);
|
|
48191
|
+
if (outOption === void 0) return resolve(process.cwd(), filename);
|
|
48192
|
+
const target = resolve(outOption);
|
|
48193
|
+
try {
|
|
48194
|
+
const info = await stat(target);
|
|
48195
|
+
if (info.isDirectory()) return join7(target, filename);
|
|
48196
|
+
} catch {
|
|
48197
|
+
}
|
|
48198
|
+
return target;
|
|
48199
|
+
}
|
|
48200
|
+
async function pathExists(path) {
|
|
48201
|
+
try {
|
|
48202
|
+
await stat(path);
|
|
48203
|
+
return true;
|
|
48204
|
+
} catch {
|
|
48205
|
+
return false;
|
|
48206
|
+
}
|
|
48207
|
+
}
|
|
48208
|
+
async function downloadCodeUploadToFile(upload, downloadUrl, destination, options = {}) {
|
|
48209
|
+
const fetchImpl = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
|
|
48210
|
+
const partialPath = `${destination}.part`;
|
|
48211
|
+
let response;
|
|
48212
|
+
try {
|
|
48213
|
+
response = await fetchImpl(downloadUrl, { method: "GET", redirect: "manual" });
|
|
48214
|
+
} catch (error48) {
|
|
48215
|
+
const detail = error48 instanceof Error ? error48.message : "network error";
|
|
48216
|
+
throw new CodeUploadDownloadError(`Download from storage failed: ${detail}.`);
|
|
48217
|
+
}
|
|
48218
|
+
if (!response.ok || response.body === null) {
|
|
48219
|
+
if (response.body !== null) await response.body.cancel();
|
|
48220
|
+
throw new CodeUploadDownloadError(
|
|
48221
|
+
`Storage answered HTTP ${response.status} instead of the build bytes. Retry; the download link may have expired.`
|
|
48222
|
+
);
|
|
48223
|
+
}
|
|
48224
|
+
const contentLength = response.headers.get("content-length");
|
|
48225
|
+
if (contentLength !== null) {
|
|
48226
|
+
const declared = Number(contentLength);
|
|
48227
|
+
if (!Number.isSafeInteger(declared) || declared !== upload.sizeBytes) {
|
|
48228
|
+
await response.body.cancel();
|
|
48229
|
+
throw new CodeUploadDownloadError(
|
|
48230
|
+
`Storage declared ${contentLength} bytes; the upload record says ${upload.sizeBytes}.`
|
|
48231
|
+
);
|
|
48232
|
+
}
|
|
48233
|
+
}
|
|
48234
|
+
await rm(partialPath, { force: true });
|
|
48235
|
+
const file2 = await open2(partialPath, "wx");
|
|
48236
|
+
const hash2 = createHash2("sha256");
|
|
48237
|
+
const reader = response.body.getReader();
|
|
48238
|
+
let downloadedBytes = 0;
|
|
48239
|
+
options.onProgress?.(progress(0, upload.sizeBytes));
|
|
48240
|
+
try {
|
|
48241
|
+
for (; ; ) {
|
|
48242
|
+
const chunk = await reader.read();
|
|
48243
|
+
if (chunk.done) break;
|
|
48244
|
+
downloadedBytes += chunk.value.byteLength;
|
|
48245
|
+
if (downloadedBytes > upload.sizeBytes) {
|
|
48246
|
+
await reader.cancel();
|
|
48247
|
+
throw new CodeUploadDownloadError(
|
|
48248
|
+
`Storage sent more than the ${upload.sizeBytes} bytes on record.`
|
|
48249
|
+
);
|
|
48250
|
+
}
|
|
48251
|
+
hash2.update(chunk.value);
|
|
48252
|
+
await writeAll(file2, chunk.value);
|
|
48253
|
+
options.onProgress?.(progress(downloadedBytes, upload.sizeBytes));
|
|
48254
|
+
}
|
|
48255
|
+
await file2.close();
|
|
48256
|
+
if (downloadedBytes !== upload.sizeBytes) {
|
|
48257
|
+
throw new CodeUploadDownloadError(
|
|
48258
|
+
`Download ended after ${downloadedBytes} of ${upload.sizeBytes} bytes.`
|
|
48259
|
+
);
|
|
48260
|
+
}
|
|
48261
|
+
const digest = hash2.digest("hex");
|
|
48262
|
+
if (digest !== upload.archiveSha256) {
|
|
48263
|
+
throw new CodeUploadDownloadError(
|
|
48264
|
+
"Downloaded bytes do not match the SHA-256 recorded at upload time."
|
|
48265
|
+
);
|
|
48266
|
+
}
|
|
48267
|
+
await rename(partialPath, destination);
|
|
48268
|
+
} catch (error48) {
|
|
48269
|
+
await file2.close().catch(() => void 0);
|
|
48270
|
+
await rm(partialPath, { force: true });
|
|
48271
|
+
if (error48 instanceof CodeUploadDownloadError) throw error48;
|
|
48272
|
+
const detail = error48 instanceof Error ? error48.message : "unknown error";
|
|
48273
|
+
throw new CodeUploadDownloadError(`Download from storage failed: ${detail}.`);
|
|
48274
|
+
}
|
|
48275
|
+
}
|
|
48276
|
+
function progress(downloadedBytes, totalBytes) {
|
|
48277
|
+
return {
|
|
48278
|
+
downloadedBytes,
|
|
48279
|
+
totalBytes,
|
|
48280
|
+
fraction: totalBytes === 0 ? 1 : downloadedBytes / totalBytes
|
|
48281
|
+
};
|
|
48282
|
+
}
|
|
48283
|
+
async function writeAll(file2, bytes) {
|
|
48284
|
+
let offset = 0;
|
|
48285
|
+
while (offset < bytes.byteLength) {
|
|
48286
|
+
const { bytesWritten } = await file2.write(bytes, offset, bytes.byteLength - offset);
|
|
48287
|
+
if (bytesWritten === 0) {
|
|
48288
|
+
throw new CodeUploadDownloadError("Writing the build to disk stalled.");
|
|
48289
|
+
}
|
|
48290
|
+
offset += bytesWritten;
|
|
48291
|
+
}
|
|
48292
|
+
}
|
|
48293
|
+
|
|
47437
48294
|
// src/upload/multipart.ts
|
|
47438
48295
|
var MAX_CONCURRENT_UPLOADS = 3;
|
|
47439
48296
|
var MAX_PART_ATTEMPTS = 3;
|
|
@@ -47446,7 +48303,7 @@ async function uploadCodeArchiveParts(filePath, totalBytes, partSizeBytes, parts
|
|
|
47446
48303
|
if (!Number.isSafeInteger(uploadedBytes) || uploadedBytes < 0 || uploadedBytes > totalBytes) {
|
|
47447
48304
|
throw new Error("Invalid multipart progress: uploaded byte count is outside the archive.");
|
|
47448
48305
|
}
|
|
47449
|
-
options.onProgress?.(
|
|
48306
|
+
options.onProgress?.(progress2(uploadedBytes, totalBytes));
|
|
47450
48307
|
if (parts.length === 0) return;
|
|
47451
48308
|
const urls = new Map(parts.map((part) => [part.partNumber, part.uploadUrl]));
|
|
47452
48309
|
const refreshUrls = createUrlRefresher(urls, options.refreshParts);
|
|
@@ -47463,7 +48320,7 @@ async function uploadCodeArchiveParts(filePath, totalBytes, partSizeBytes, parts
|
|
|
47463
48320
|
const body = await readFileSlice(filePath, start, end);
|
|
47464
48321
|
await uploadPartWithRetry(part.partNumber, urls, body, fetchPart, wait, refreshUrls);
|
|
47465
48322
|
uploadedBytes += body.byteLength;
|
|
47466
|
-
options.onProgress?.(
|
|
48323
|
+
options.onProgress?.(progress2(uploadedBytes, totalBytes));
|
|
47467
48324
|
}
|
|
47468
48325
|
})
|
|
47469
48326
|
);
|
|
@@ -47551,7 +48408,7 @@ function assertPresignedUploadUrl(value) {
|
|
|
47551
48408
|
throw new Error("Invalid multipart upload: part URLs must use HTTPS.");
|
|
47552
48409
|
}
|
|
47553
48410
|
}
|
|
47554
|
-
function
|
|
48411
|
+
function progress2(uploadedBytes, totalBytes) {
|
|
47555
48412
|
return {
|
|
47556
48413
|
uploadedBytes,
|
|
47557
48414
|
totalBytes,
|
|
@@ -47559,13 +48416,13 @@ function progress(uploadedBytes, totalBytes) {
|
|
|
47559
48416
|
};
|
|
47560
48417
|
}
|
|
47561
48418
|
function defaultWait(milliseconds) {
|
|
47562
|
-
return new Promise((
|
|
48419
|
+
return new Promise((resolve2) => setTimeout(resolve2, milliseconds));
|
|
47563
48420
|
}
|
|
47564
48421
|
|
|
47565
48422
|
// src/upload/commands.ts
|
|
47566
48423
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["READY", "REJECTED", "FAILED", "DELETING"]);
|
|
47567
48424
|
var DEFAULT_RUNTIME = {
|
|
47568
|
-
wait: (milliseconds) => new Promise((
|
|
48425
|
+
wait: (milliseconds) => new Promise((resolve2) => setTimeout(resolve2, milliseconds)),
|
|
47569
48426
|
pollIntervalMs: 3e3,
|
|
47570
48427
|
fetch: (input, init) => globalThis.fetch(input, init)
|
|
47571
48428
|
};
|
|
@@ -47678,6 +48535,53 @@ function failReadOp5(action, status, body) {
|
|
|
47678
48535
|
);
|
|
47679
48536
|
process.exit(1);
|
|
47680
48537
|
}
|
|
48538
|
+
function failDownloadOp(codeUploadId, status, body) {
|
|
48539
|
+
const { message, errorCode } = readErrorFields(body);
|
|
48540
|
+
if (status === UNAUTHORIZED_STATUS2) {
|
|
48541
|
+
exitAuthFailed();
|
|
48542
|
+
}
|
|
48543
|
+
if (status === 403) {
|
|
48544
|
+
console.error(
|
|
48545
|
+
colorError(
|
|
48546
|
+
"Only an organization admin (or Trace staff) on a pentest-enabled organization can download builds."
|
|
48547
|
+
)
|
|
48548
|
+
);
|
|
48549
|
+
process.exit(1);
|
|
48550
|
+
}
|
|
48551
|
+
if (status === 404) {
|
|
48552
|
+
console.error(colorError(message ?? "No code upload with that id."));
|
|
48553
|
+
process.exit(1);
|
|
48554
|
+
}
|
|
48555
|
+
if (status === 409) {
|
|
48556
|
+
if (errorCode === "CODE_UPLOAD_NOT_BUILD") {
|
|
48557
|
+
console.error(
|
|
48558
|
+
colorError(
|
|
48559
|
+
message ?? "Only APK and IPA builds can be downloaded. Source archives stay on the server."
|
|
48560
|
+
)
|
|
48561
|
+
);
|
|
48562
|
+
} else if (errorCode === "CODE_UPLOAD_NOT_READY") {
|
|
48563
|
+
console.error(
|
|
48564
|
+
colorError(
|
|
48565
|
+
message ?? "The build must be ready and pass malware scanning before it can be downloaded."
|
|
48566
|
+
)
|
|
48567
|
+
);
|
|
48568
|
+
console.error(`Wait for it with: tracecli upload wait ${codeUploadId}`);
|
|
48569
|
+
} else {
|
|
48570
|
+
console.error(colorError(message ?? "Conflict (status 409)."));
|
|
48571
|
+
}
|
|
48572
|
+
process.exit(1);
|
|
48573
|
+
}
|
|
48574
|
+
if (status === 503) {
|
|
48575
|
+
console.error(
|
|
48576
|
+
colorError(message ?? "Source archive uploads are not configured on this server.")
|
|
48577
|
+
);
|
|
48578
|
+
process.exit(1);
|
|
48579
|
+
}
|
|
48580
|
+
console.error(
|
|
48581
|
+
colorError(`Failed to download build (status ${status})${message ? `: ${message}` : "."}`)
|
|
48582
|
+
);
|
|
48583
|
+
process.exit(1);
|
|
48584
|
+
}
|
|
47681
48585
|
function resumeHint(codeUploadId, filePath) {
|
|
47682
48586
|
return `Resume with: tracecli upload resume ${codeUploadId} ${filePath}`;
|
|
47683
48587
|
}
|
|
@@ -47689,13 +48593,13 @@ function buildUploadsTable(uploads) {
|
|
|
47689
48593
|
size: formatArchiveBytes(upload.sizeBytes),
|
|
47690
48594
|
id: upload.codeUploadId
|
|
47691
48595
|
}));
|
|
47692
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
47693
|
-
const kindWidth = Math.max(4, ...cells.map((
|
|
47694
|
-
const statusWidth = Math.max(6, ...cells.map((
|
|
47695
|
-
const sizeWidth = Math.max(4, ...cells.map((
|
|
48596
|
+
const nameWidth = Math.max(4, ...cells.map((c62) => c62.name.length));
|
|
48597
|
+
const kindWidth = Math.max(4, ...cells.map((c62) => c62.kind.length));
|
|
48598
|
+
const statusWidth = Math.max(6, ...cells.map((c62) => c62.status.length));
|
|
48599
|
+
const sizeWidth = Math.max(4, ...cells.map((c62) => c62.size.length));
|
|
47696
48600
|
const header = `${"NAME".padEnd(nameWidth)} ${"KIND".padEnd(kindWidth)} ${"STATUS".padEnd(statusWidth)} ${"SIZE".padEnd(sizeWidth)} ID`;
|
|
47697
48601
|
const rows = cells.map(
|
|
47698
|
-
(
|
|
48602
|
+
(c62) => `${c62.name.padEnd(nameWidth)} ${c62.kind.padEnd(kindWidth)} ${c62.status.padEnd(statusWidth)} ${c62.size.padEnd(sizeWidth)} ${c62.id}`
|
|
47699
48603
|
);
|
|
47700
48604
|
return { header, rows };
|
|
47701
48605
|
}
|
|
@@ -47767,11 +48671,18 @@ function outputUpload(upload, output) {
|
|
|
47767
48671
|
}
|
|
47768
48672
|
console.log(renderUploadDetail(upload));
|
|
47769
48673
|
}
|
|
47770
|
-
function writeProgress(
|
|
48674
|
+
function writeProgress(progress3) {
|
|
48675
|
+
if (!process.stderr.isTTY) return;
|
|
48676
|
+
const pct = Math.floor(progress3.fraction * 100);
|
|
48677
|
+
process.stderr.write(
|
|
48678
|
+
`\rUploading ${pct}% (${formatArchiveBytes(progress3.uploadedBytes)} / ${formatArchiveBytes(progress3.totalBytes)})`
|
|
48679
|
+
);
|
|
48680
|
+
}
|
|
48681
|
+
function writeDownloadProgress(progress3) {
|
|
47771
48682
|
if (!process.stderr.isTTY) return;
|
|
47772
|
-
const pct = Math.floor(
|
|
48683
|
+
const pct = Math.floor(progress3.fraction * 100);
|
|
47773
48684
|
process.stderr.write(
|
|
47774
|
-
`\
|
|
48685
|
+
`\rDownloading ${pct}% (${formatArchiveBytes(progress3.downloadedBytes)} / ${formatArchiveBytes(progress3.totalBytes)})`
|
|
47775
48686
|
);
|
|
47776
48687
|
}
|
|
47777
48688
|
function finishProgress() {
|
|
@@ -48085,6 +48996,76 @@ async function runGet4(codeUploadIdArg, options) {
|
|
|
48085
48996
|
const upload = await requireUpload(organizationId, codeUploadId);
|
|
48086
48997
|
outputUpload(upload, output);
|
|
48087
48998
|
}
|
|
48999
|
+
async function runDownload(codeUploadIdArg, options, runtime) {
|
|
49000
|
+
const output = parseOutput(options.output);
|
|
49001
|
+
const codeUploadId = requireUuid(codeUploadIdArg, "code upload id");
|
|
49002
|
+
const organizationId = await resolveOrganizationId();
|
|
49003
|
+
const result = await authenticatedRequest(
|
|
49004
|
+
(client) => client.codeUpload.downloadCodeUpload({
|
|
49005
|
+
params: { organizationId, codeUploadId }
|
|
49006
|
+
})
|
|
49007
|
+
);
|
|
49008
|
+
if (result.status !== SUCCESS_STATUS) {
|
|
49009
|
+
failDownloadOp(codeUploadId, result.status, result.body);
|
|
49010
|
+
}
|
|
49011
|
+
const { upload, downloadUrl } = result.body;
|
|
49012
|
+
const destination = await resolveDownloadDestination(upload, options.out);
|
|
49013
|
+
if (!options.force && await pathExists(destination)) {
|
|
49014
|
+
console.error(
|
|
49015
|
+
colorError(`${destination} already exists. Pass --force to overwrite it or --out <path>.`)
|
|
49016
|
+
);
|
|
49017
|
+
process.exit(1);
|
|
49018
|
+
}
|
|
49019
|
+
if (output === "table") {
|
|
49020
|
+
console.error(
|
|
49021
|
+
`Downloading ${sanitizeDisplay(upload.displayName)} (${formatArchiveBytes(upload.sizeBytes)}) to ${destination}`
|
|
49022
|
+
);
|
|
49023
|
+
}
|
|
49024
|
+
try {
|
|
49025
|
+
await downloadCodeUploadToFile(upload, downloadUrl, destination, {
|
|
49026
|
+
fetch: runtime.fetch,
|
|
49027
|
+
onProgress: writeDownloadProgress
|
|
49028
|
+
});
|
|
49029
|
+
finishProgress();
|
|
49030
|
+
} catch (error48) {
|
|
49031
|
+
finishProgress();
|
|
49032
|
+
const detail = error48 instanceof Error ? error48.message : "Download from storage failed.";
|
|
49033
|
+
console.error(colorError(detail));
|
|
49034
|
+
process.exit(1);
|
|
49035
|
+
}
|
|
49036
|
+
if (output === "json") {
|
|
49037
|
+
console.log(
|
|
49038
|
+
JSON.stringify(
|
|
49039
|
+
{
|
|
49040
|
+
upload,
|
|
49041
|
+
path: destination,
|
|
49042
|
+
sizeBytes: upload.sizeBytes,
|
|
49043
|
+
archiveSha256: upload.archiveSha256
|
|
49044
|
+
},
|
|
49045
|
+
null,
|
|
49046
|
+
2
|
|
49047
|
+
)
|
|
49048
|
+
);
|
|
49049
|
+
return;
|
|
49050
|
+
}
|
|
49051
|
+
if (output === "tsv") {
|
|
49052
|
+
console.log(["codeUploadId", "path", "sizeBytes", "archiveSha256"].join(" "));
|
|
49053
|
+
console.log(
|
|
49054
|
+
[
|
|
49055
|
+
tsvSafe(upload.codeUploadId),
|
|
49056
|
+
tsvSafe(destination),
|
|
49057
|
+
String(upload.sizeBytes),
|
|
49058
|
+
tsvSafe(upload.archiveSha256)
|
|
49059
|
+
].join(" ")
|
|
49060
|
+
);
|
|
49061
|
+
return;
|
|
49062
|
+
}
|
|
49063
|
+
console.log(
|
|
49064
|
+
colorSuccess(
|
|
49065
|
+
`Saved ${sanitizeDisplay(upload.displayName)} to ${destination} (${formatArchiveBytes(upload.sizeBytes)}, SHA-256 verified).`
|
|
49066
|
+
)
|
|
49067
|
+
);
|
|
49068
|
+
}
|
|
48088
49069
|
async function runWait(codeUploadIdArg, options, runtime) {
|
|
48089
49070
|
const output = parseOutput(options.output);
|
|
48090
49071
|
const codeUploadId = requireUuid(codeUploadIdArg, "code upload id");
|
|
@@ -48209,6 +49190,23 @@ Examples:
|
|
|
48209
49190
|
await runResume(codeUploadId, file2, options, runtime);
|
|
48210
49191
|
});
|
|
48211
49192
|
}
|
|
49193
|
+
function createDownloadCommand(runtime) {
|
|
49194
|
+
return new Command("download").description("Download an APK or IPA build that finished malware scanning").argument("<codeUploadId>", "Upload UUID of the build").option("--out <path>", "File to write, or an existing directory (default: working directory)").option("-f, --force", "Overwrite an existing file").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
|
|
49195
|
+
"after",
|
|
49196
|
+
`
|
|
49197
|
+
Only READY builds with a clean malware scan can be downloaded. Source ZIPs
|
|
49198
|
+
are not downloadable. The file is written under the name it was uploaded
|
|
49199
|
+
with and its size and SHA-256 are checked against the upload record before
|
|
49200
|
+
it is moved into place.
|
|
49201
|
+
|
|
49202
|
+
Examples:
|
|
49203
|
+
tracecli upload download <codeUploadId>
|
|
49204
|
+
tracecli upload download <codeUploadId> --out ./builds/
|
|
49205
|
+
tracecli upload download <codeUploadId> --out ./release.apk --force`
|
|
49206
|
+
).action(async (codeUploadId, options) => {
|
|
49207
|
+
await runDownload(codeUploadId, options, runtime);
|
|
49208
|
+
});
|
|
49209
|
+
}
|
|
48212
49210
|
function createWaitCommand(runtime) {
|
|
48213
49211
|
return new Command("wait").description("Wait until an upload finishes malware scanning and validation").argument("<codeUploadId>", "Upload UUID").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").action(async (codeUploadId, options) => {
|
|
48214
49212
|
await runWait(codeUploadId, options, runtime);
|
|
@@ -48234,11 +49232,12 @@ Examples:
|
|
|
48234
49232
|
}
|
|
48235
49233
|
function createUploadCommand(runtime = {}) {
|
|
48236
49234
|
const resolved = resolveRuntime(runtime);
|
|
48237
|
-
const upload = new Command("upload").alias("code-upload").description("Upload source archives
|
|
49235
|
+
const upload = new Command("upload").alias("code-upload").description("Upload source archives and mobile builds for pentest; download builds back");
|
|
48238
49236
|
upload.addCommand(createCreateCommand5(resolved));
|
|
48239
49237
|
upload.addCommand(createBuildCommand(resolved));
|
|
48240
49238
|
upload.addCommand(createListCommand7());
|
|
48241
49239
|
upload.addCommand(createGetCommand4());
|
|
49240
|
+
upload.addCommand(createDownloadCommand(resolved));
|
|
48242
49241
|
upload.addCommand(createResumeCommand(resolved));
|
|
48243
49242
|
upload.addCommand(createWaitCommand(resolved));
|
|
48244
49243
|
upload.addCommand(createDeleteCommand5());
|