securewithtrace 0.31.0 → 0.33.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 +2066 -567
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6322,29 +6322,29 @@ var ZodFunction = class _ZodFunction extends ZodType {
|
|
|
6322
6322
|
const params = { errorMap: ctx.common.contextualErrorMap };
|
|
6323
6323
|
const fn = ctx.data;
|
|
6324
6324
|
if (this._def.returns instanceof ZodPromise) {
|
|
6325
|
-
const
|
|
6325
|
+
const me2 = this;
|
|
6326
6326
|
return OK(async function(...args) {
|
|
6327
6327
|
const error48 = new ZodError([]);
|
|
6328
|
-
const parsedArgs = await
|
|
6328
|
+
const parsedArgs = await me2._def.args.parseAsync(args, params).catch((e2) => {
|
|
6329
6329
|
error48.addIssue(makeArgsIssue(args, e2));
|
|
6330
6330
|
throw error48;
|
|
6331
6331
|
});
|
|
6332
6332
|
const result = await Reflect.apply(fn, this, parsedArgs);
|
|
6333
|
-
const parsedReturns = await
|
|
6333
|
+
const parsedReturns = await me2._def.returns._def.type.parseAsync(result, params).catch((e2) => {
|
|
6334
6334
|
error48.addIssue(makeReturnsIssue(result, e2));
|
|
6335
6335
|
throw error48;
|
|
6336
6336
|
});
|
|
6337
6337
|
return parsedReturns;
|
|
6338
6338
|
});
|
|
6339
6339
|
} else {
|
|
6340
|
-
const
|
|
6340
|
+
const me2 = this;
|
|
6341
6341
|
return OK(function(...args) {
|
|
6342
|
-
const parsedArgs =
|
|
6342
|
+
const parsedArgs = me2._def.args.safeParse(args, params);
|
|
6343
6343
|
if (!parsedArgs.success) {
|
|
6344
6344
|
throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);
|
|
6345
6345
|
}
|
|
6346
6346
|
const result = Reflect.apply(fn, this, parsedArgs.data);
|
|
6347
|
-
const parsedReturns =
|
|
6347
|
+
const parsedReturns = me2._def.returns.safeParse(result, params);
|
|
6348
6348
|
if (!parsedReturns.success) {
|
|
6349
6349
|
throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);
|
|
6350
6350
|
}
|
|
@@ -10176,7 +10176,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
|
10176
10176
|
function isValidBase64URL(data) {
|
|
10177
10177
|
if (!base64url.test(data))
|
|
10178
10178
|
return false;
|
|
10179
|
-
const base643 = data.replace(/[-_]/g, (
|
|
10179
|
+
const base643 = data.replace(/[-_]/g, (c51) => c51 === "-" ? "+" : "/");
|
|
10180
10180
|
const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
|
|
10181
10181
|
return isValidBase64(padded);
|
|
10182
10182
|
}
|
|
@@ -20220,9 +20220,9 @@ var ZodDate2 = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
|
|
|
20220
20220
|
inst._zod.processJSONSchema = (ctx, json2, params) => dateProcessor(inst, ctx, json2, params);
|
|
20221
20221
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
20222
20222
|
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
20223
|
-
const
|
|
20224
|
-
inst.minDate =
|
|
20225
|
-
inst.maxDate =
|
|
20223
|
+
const c51 = inst._zod.bag;
|
|
20224
|
+
inst.minDate = c51.minimum ? new Date(c51.minimum) : null;
|
|
20225
|
+
inst.maxDate = c51.maximum ? new Date(c51.maximum) : null;
|
|
20226
20226
|
});
|
|
20227
20227
|
function date3(params) {
|
|
20228
20228
|
return _date(ZodDate2, params);
|
|
@@ -21504,7 +21504,8 @@ var PentestEditEntityValues = [
|
|
|
21504
21504
|
"PENTEST_TOOL_RUN",
|
|
21505
21505
|
"PENTEST_ATTESTATION",
|
|
21506
21506
|
"PENTEST_REPORT",
|
|
21507
|
-
"PENTEST_EXPLOIT_ARTIFACT"
|
|
21507
|
+
"PENTEST_EXPLOIT_ARTIFACT",
|
|
21508
|
+
"PENTEST_FINDING_RETEST"
|
|
21508
21509
|
];
|
|
21509
21510
|
var PentestEditEntity = external_exports.enum(PentestEditEntityValues);
|
|
21510
21511
|
var PentestEditActionValues = [
|
|
@@ -21688,10 +21689,11 @@ var AgentSessionIdParamsSchema = AgentSessionsParamsSchema.extend({
|
|
|
21688
21689
|
var AgentSessionEventIdParamsSchema = AgentSessionIdParamsSchema.extend({
|
|
21689
21690
|
eventId: external_exports.uuid()
|
|
21690
21691
|
});
|
|
21692
|
+
var MAX_AGENT_SESSION_MAX_USD = 1500;
|
|
21691
21693
|
var CreateAgentSessionCommonSchema = external_exports.object({
|
|
21692
21694
|
provider: AgentSessionProvider.optional(),
|
|
21693
21695
|
model: external_exports.string().min(1).max(200).optional(),
|
|
21694
|
-
maxUsd: external_exports.number().positive().max(
|
|
21696
|
+
maxUsd: external_exports.number().positive().max(MAX_AGENT_SESSION_MAX_USD).optional(),
|
|
21695
21697
|
maxWallClockMin: external_exports.number().int().positive().max(24 * 60).optional()
|
|
21696
21698
|
});
|
|
21697
21699
|
var CreateAgentSessionRequestSchema = external_exports.discriminatedUnion("type", [
|
|
@@ -21701,7 +21703,17 @@ var CreateAgentSessionRequestSchema = external_exports.discriminatedUnion("type"
|
|
|
21701
21703
|
}),
|
|
21702
21704
|
CreateAgentSessionCommonSchema.extend({
|
|
21703
21705
|
type: external_exports.literal("CODE_REVIEW"),
|
|
21704
|
-
focus: external_exports.string().min(1).max(2e3).optional()
|
|
21706
|
+
focus: external_exports.string().min(1).max(2e3).optional(),
|
|
21707
|
+
/**
|
|
21708
|
+
* Which bound application this review reads the codebase through (multi-application
|
|
21709
|
+
* PR 4). REQUIRED once 2+ applications are bound — omitting it there is
|
|
21710
|
+
* `APPLICATION_REQUIRED`, because the silent alternative is N reviews all scoping
|
|
21711
|
+
* their threat model to the first binding and overwriting each other. Defaults to
|
|
21712
|
+
* the sole binding at 1, and is legitimately absent for a bindingless engagement.
|
|
21713
|
+
* Only CODE_REVIEW and PRODUCT_RECON carry it: the other types are engagement-wide
|
|
21714
|
+
* by design, and the discriminated union is what keeps it off them.
|
|
21715
|
+
*/
|
|
21716
|
+
applicationId: external_exports.uuid().optional()
|
|
21705
21717
|
}),
|
|
21706
21718
|
CreateAgentSessionCommonSchema.extend({
|
|
21707
21719
|
type: external_exports.literal("VALIDATION"),
|
|
@@ -21736,7 +21748,10 @@ var CreateAgentSessionRequestSchema = external_exports.discriminatedUnion("type"
|
|
|
21736
21748
|
// / VALIDATION / RECON.
|
|
21737
21749
|
CreateAgentSessionCommonSchema.extend({
|
|
21738
21750
|
type: external_exports.literal("PRODUCT_RECON"),
|
|
21739
|
-
focus: external_exports.string().min(1).max(2e3).optional()
|
|
21751
|
+
focus: external_exports.string().min(1).max(2e3).optional(),
|
|
21752
|
+
/** Which bound application this recon learns. Same rules as CODE_REVIEW's, except
|
|
21753
|
+
* a bindingless engagement is already rejected at prep (PRODUCT_RECON_NO_APPLICATION). */
|
|
21754
|
+
applicationId: external_exports.uuid().optional()
|
|
21740
21755
|
}),
|
|
21741
21756
|
// REPORT (report-generation-session RS3): the report-authoring session. The
|
|
21742
21757
|
// objective is server-built from the engagement (no repo/creds); `focus` is
|
|
@@ -21752,8 +21767,10 @@ var SendAgentSessionMessageRequestSchema = external_exports.object({
|
|
|
21752
21767
|
var ResumeAgentSessionRequestSchema = external_exports.object({
|
|
21753
21768
|
/** Manual failover: relaunch on the other provider (cold cache accepted). */
|
|
21754
21769
|
provider: AgentSessionProvider.optional(),
|
|
21755
|
-
/** Budget raise — required to leave WAITING_ON_STAFF(BUDGET_EXHAUSTED).
|
|
21756
|
-
|
|
21770
|
+
/** Budget raise — required to leave WAITING_ON_STAFF(BUDGET_EXHAUSTED). Same
|
|
21771
|
+
* lifetime ceiling as create: a raise past it is not expressible, which is why
|
|
21772
|
+
* the create cap had to move for the engagement-wide validator. */
|
|
21773
|
+
maxUsd: external_exports.number().positive().max(MAX_AGENT_SESSION_MAX_USD).optional()
|
|
21757
21774
|
});
|
|
21758
21775
|
var ListAgentSessionEventsQuerySchema = external_exports.object({
|
|
21759
21776
|
/** Return events with seq > sinceSeq (poll cursor). */
|
|
@@ -21765,6 +21782,12 @@ var AgentSessionSummarySchema = external_exports.object({
|
|
|
21765
21782
|
organizationId: external_exports.uuid(),
|
|
21766
21783
|
pentestId: external_exports.uuid(),
|
|
21767
21784
|
type: AgentSessionType,
|
|
21785
|
+
/**
|
|
21786
|
+
* The application this session is scoped to, or null for engagement-wide (PR 4).
|
|
21787
|
+
* Id only — `toSummary` is a pure row mapper feeding six call sites, and the staff
|
|
21788
|
+
* console already holds the bound applications it needs to resolve a name.
|
|
21789
|
+
*/
|
|
21790
|
+
applicationId: external_exports.uuid().nullable(),
|
|
21768
21791
|
status: AgentSessionStatus,
|
|
21769
21792
|
waitingReason: AgentSessionWaitingReason.nullable(),
|
|
21770
21793
|
failureReason: AgentSessionFailureReason.nullable(),
|
|
@@ -21861,15 +21884,35 @@ var OperatorPentestContextSchema = external_exports.object({
|
|
|
21861
21884
|
customerPriorityCategories: external_exports.array(external_exports.string()),
|
|
21862
21885
|
status: PentestStatus,
|
|
21863
21886
|
currentStage: PentestStage,
|
|
21887
|
+
/**
|
|
21888
|
+
* The lowest-ordinal binding. RETAINED rather than replaced by `applications`:
|
|
21889
|
+
* `apps/agent-session-host` mirrors this interface by hand and raw-casts the JSON
|
|
21890
|
+
* without a schema parse (`api-client.ts:858-872`), so dropping this field would
|
|
21891
|
+
* give a parked or in-flight session `undefined` for its application block with no
|
|
21892
|
+
* parse error and no log. It retires a release after no parked session predates
|
|
21893
|
+
* `applications`.
|
|
21894
|
+
*/
|
|
21864
21895
|
primaryApplication: external_exports.object({
|
|
21865
21896
|
name: external_exports.string(),
|
|
21866
21897
|
type: external_exports.string(),
|
|
21867
21898
|
applicationUrl: external_exports.string().nullable()
|
|
21868
21899
|
}).nullable(),
|
|
21900
|
+
/**
|
|
21901
|
+
* Every bound application, ordinal-ascending. Optional for the same host
|
|
21902
|
+
* raw-cast reason: an older host image ignores what it does not know about.
|
|
21903
|
+
*/
|
|
21904
|
+
applications: external_exports.array(
|
|
21905
|
+
external_exports.object({
|
|
21906
|
+
name: external_exports.string(),
|
|
21907
|
+
type: external_exports.string(),
|
|
21908
|
+
applicationUrl: external_exports.string().nullable()
|
|
21909
|
+
})
|
|
21910
|
+
).optional(),
|
|
21869
21911
|
environments: external_exports.array(
|
|
21870
21912
|
external_exports.object({
|
|
21871
21913
|
name: external_exports.string(),
|
|
21872
|
-
|
|
21914
|
+
// Null for repo-only application types (CLI, MOBILE, DESKTOP).
|
|
21915
|
+
primaryUrl: external_exports.string().nullable(),
|
|
21873
21916
|
isProduction: external_exports.boolean()
|
|
21874
21917
|
})
|
|
21875
21918
|
),
|
|
@@ -22197,36 +22240,9 @@ function roleDisplay(role, roleLabel) {
|
|
|
22197
22240
|
return APPLICATION_REPOSITORY_ROLE_LABELS[role] ?? null;
|
|
22198
22241
|
}
|
|
22199
22242
|
|
|
22200
|
-
// ../../packages/core/src/ai-tooling/profile.ts
|
|
22201
|
-
var AI_TOOL_DETECTION = ["claude-code", "codex", "both", "neither"];
|
|
22202
|
-
var AI_TOOL_OVERRIDE = ["claude-code", "codex"];
|
|
22203
|
-
var Sha40 = external_exports.string().regex(/^[a-f0-9]{40}$/, "expected a 40-char hex git SHA");
|
|
22204
|
-
var AiToolingProfileSchema = external_exports.object({
|
|
22205
|
-
schemaVersion: external_exports.literal(1),
|
|
22206
|
-
detectedTool: external_exports.enum(AI_TOOL_DETECTION),
|
|
22207
|
-
overrideTool: external_exports.enum(AI_TOOL_OVERRIDE).nullable(),
|
|
22208
|
-
/** null = no detection has run yet (override-only seed); refresh on next scan. */
|
|
22209
|
-
detectedAt: external_exports.iso.datetime().nullable(),
|
|
22210
|
-
/** Scan commit-sha the detection ran against. null when detectedAt is null. */
|
|
22211
|
-
detectedCommitSha: Sha40.nullable(),
|
|
22212
|
-
evidence: external_exports.object({
|
|
22213
|
-
claudeMdSha: Sha40.nullable(),
|
|
22214
|
-
agentsMdSha: Sha40.nullable(),
|
|
22215
|
-
claudeMdMtime: external_exports.iso.datetime().nullable(),
|
|
22216
|
-
agentsMdMtime: external_exports.iso.datetime().nullable()
|
|
22217
|
-
}).strict()
|
|
22218
|
-
}).strict();
|
|
22219
|
-
|
|
22220
22243
|
// ../../packages/api-contracts/src/schemas/api/v1/repository.api.ts
|
|
22221
22244
|
var PlatformValues = ["GITHUB", "GITLAB", "BITBUCKET"];
|
|
22222
22245
|
var RepositoryStatusValues = ["CONNECTED", "DISCONNECTED"];
|
|
22223
|
-
var SetAiToolingProfileOverrideRequestSchema = external_exports.object({
|
|
22224
|
-
/** null clears the override and reverts to detection-driven resolution. */
|
|
22225
|
-
overrideTool: external_exports.enum(AI_TOOL_OVERRIDE).nullable()
|
|
22226
|
-
}).strict();
|
|
22227
|
-
var SetAiToolingProfileOverrideResponseSchema = external_exports.object({
|
|
22228
|
-
aiToolingProfile: AiToolingProfileSchema.nullable()
|
|
22229
|
-
}).strict();
|
|
22230
22246
|
var RepositoryIdParamsSchema = OrgIdParamsSchema.extend({
|
|
22231
22247
|
repositoryId: external_exports.uuid()
|
|
22232
22248
|
});
|
|
@@ -22251,13 +22267,6 @@ var RepositoryResponseSchema = external_exports.object({
|
|
|
22251
22267
|
githubDefaultBranch: external_exports.string(),
|
|
22252
22268
|
scanningBranch: external_exports.string().nullable(),
|
|
22253
22269
|
primaryLanguage: external_exports.string().nullable().optional(),
|
|
22254
|
-
/**
|
|
22255
|
-
* Null until the first post-scan detection writes a row, OR when the raw
|
|
22256
|
-
* JSONB fails strict-schema parsing (mapper falls back to null so the
|
|
22257
|
-
* response stays valid). PATCH override writes always preserve the live
|
|
22258
|
-
* `overrideTool` via `parseOverrideTool`.
|
|
22259
|
-
*/
|
|
22260
|
-
aiToolingProfile: AiToolingProfileSchema.nullable(),
|
|
22261
22270
|
createdAt: external_exports.date(),
|
|
22262
22271
|
updatedAt: external_exports.date()
|
|
22263
22272
|
});
|
|
@@ -22345,7 +22354,8 @@ var ConfirmScanningBranchDefaultsResponseSchema = external_exports.object({
|
|
|
22345
22354
|
});
|
|
22346
22355
|
|
|
22347
22356
|
// ../../packages/api-contracts/src/schemas/api/v1/application.api.ts
|
|
22348
|
-
var ApplicationTypeValues = ["WEB", "CLI", "MOBILE", "API_SERVICE"];
|
|
22357
|
+
var ApplicationTypeValues = ["WEB", "CLI", "MOBILE", "DESKTOP", "API_SERVICE"];
|
|
22358
|
+
var APPLICATION_NOTES_MAX_CHARS = 2e3;
|
|
22349
22359
|
var ApplicationRepositoryRoleValues = [
|
|
22350
22360
|
"FRONTEND",
|
|
22351
22361
|
"BACKEND_API",
|
|
@@ -22393,9 +22403,19 @@ var ApplicationResponseSchema = external_exports.object({
|
|
|
22393
22403
|
// reject application rows.
|
|
22394
22404
|
type: external_exports.enum(ApplicationTypeValues).default("WEB"),
|
|
22395
22405
|
applicationUrl: external_exports.string().nullable(),
|
|
22406
|
+
// Customer-authored free-text context, any type ("Advanced → Notes").
|
|
22407
|
+
notes: external_exports.string().nullable(),
|
|
22396
22408
|
helpCenterUrl: external_exports.string().nullable(),
|
|
22397
22409
|
documentationUrl: external_exports.string().nullable(),
|
|
22398
22410
|
repositories: external_exports.array(ApplicationRepositorySummarySchema),
|
|
22411
|
+
// Registrable domains RECON is authorized to discover subdomains under. The
|
|
22412
|
+
// Environments-tab panel hydrates from this payload (no client GET). Defaulted
|
|
22413
|
+
// (like `type`) so a new client reading a pre-this-release API during a rolling
|
|
22414
|
+
// deploy doesn't reject application rows that predate the field.
|
|
22415
|
+
// Signed S3 URL for the Overview screenshot. Defaulted null so a new client
|
|
22416
|
+
// reading a pre-this-release API during a rolling deploy doesn't reject rows
|
|
22417
|
+
// that omit the field. The raw S3 key is never on the wire.
|
|
22418
|
+
screenshotUrl: external_exports.url().nullable().default(null),
|
|
22399
22419
|
createdAt: external_exports.date(),
|
|
22400
22420
|
updatedAt: external_exports.date()
|
|
22401
22421
|
});
|
|
@@ -22404,6 +22424,7 @@ var CreateApplicationRequestSchema = external_exports.object({
|
|
|
22404
22424
|
name: external_exports.string().min(1).max(200),
|
|
22405
22425
|
type: external_exports.enum(ApplicationTypeValues).default("WEB"),
|
|
22406
22426
|
applicationUrl: external_exports.url().max(2048).optional(),
|
|
22427
|
+
notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).optional(),
|
|
22407
22428
|
repositoryId: external_exports.uuid().optional(),
|
|
22408
22429
|
repositoryPath: external_exports.string().max(500).optional(),
|
|
22409
22430
|
helpCenterUrl: external_exports.url().max(2048).optional(),
|
|
@@ -22431,6 +22452,7 @@ var UpdateApplicationRepositoryLinkRequestSchema = external_exports.object({
|
|
|
22431
22452
|
var UpdateApplicationRequestSchema = external_exports.object({
|
|
22432
22453
|
name: external_exports.string().min(1).max(200).optional(),
|
|
22433
22454
|
applicationUrl: external_exports.url().max(2048).optional(),
|
|
22455
|
+
notes: external_exports.string().max(APPLICATION_NOTES_MAX_CHARS).nullable().optional(),
|
|
22434
22456
|
repositoryId: external_exports.uuid().nullable().optional(),
|
|
22435
22457
|
repositoryPath: external_exports.string().max(500).nullable().optional(),
|
|
22436
22458
|
helpCenterUrl: external_exports.url().max(2048).nullable().optional(),
|
|
@@ -22794,7 +22816,7 @@ var chatSessionContract = c6.router({
|
|
|
22794
22816
|
});
|
|
22795
22817
|
|
|
22796
22818
|
// ../../packages/api-contracts/src/schemas/api/v1/cloud-integration.api.ts
|
|
22797
|
-
var CloudProviderValues = ["AWS", "GCP", "AZURE", "VERCEL"];
|
|
22819
|
+
var CloudProviderValues = ["AWS", "GCP", "AZURE", "VERCEL", "CONVEX"];
|
|
22798
22820
|
var CloudIntegrationStatusValues = [
|
|
22799
22821
|
"PENDING",
|
|
22800
22822
|
"ACTIVE",
|
|
@@ -23304,6 +23326,107 @@ var DisconnectGcpCloudIntegrationResponseSchema = external_exports.object({
|
|
|
23304
23326
|
var CancelPendingGcpCloudIntegrationResponseSchema = external_exports.object({
|
|
23305
23327
|
deleted: external_exports.literal(true)
|
|
23306
23328
|
}).strict();
|
|
23329
|
+
var ConvexAccountIdParamsSchema = CloudIntegrationIdParamsSchema.extend({
|
|
23330
|
+
cloudProviderAccountId: external_exports.uuid()
|
|
23331
|
+
});
|
|
23332
|
+
var ConvexDeploymentIdParamsSchema = CloudIntegrationIdParamsSchema.extend({
|
|
23333
|
+
convexLinkedDeploymentId: external_exports.uuid()
|
|
23334
|
+
});
|
|
23335
|
+
var CreateConvexInstallIntentRequestSchema = external_exports.object({
|
|
23336
|
+
displayName: external_exports.string().trim().min(1).max(120).optional()
|
|
23337
|
+
}).strict();
|
|
23338
|
+
var FinalizeConvexCallbackRequestSchema = external_exports.object({
|
|
23339
|
+
code: external_exports.string().trim().min(1).max(4096),
|
|
23340
|
+
state: external_exports.string().trim().min(32).max(512)
|
|
23341
|
+
}).strict();
|
|
23342
|
+
var ConvexCloudIntegrationSummarySchema = external_exports.object({
|
|
23343
|
+
cloudIntegrationId: external_exports.uuid(),
|
|
23344
|
+
organizationId: external_exports.uuid(),
|
|
23345
|
+
provider: external_exports.literal("CONVEX"),
|
|
23346
|
+
status: CloudIntegrationStatusSchema,
|
|
23347
|
+
displayName: external_exports.string(),
|
|
23348
|
+
templateVersion: external_exports.string(),
|
|
23349
|
+
verifiedAt: external_exports.date().nullable(),
|
|
23350
|
+
disconnectedAt: external_exports.date().nullable(),
|
|
23351
|
+
disconnectedById: external_exports.uuid().nullable(),
|
|
23352
|
+
lastErrorCode: external_exports.string().nullable(),
|
|
23353
|
+
lastErrorMessage: external_exports.string().nullable(),
|
|
23354
|
+
createdAt: external_exports.date(),
|
|
23355
|
+
updatedAt: external_exports.date()
|
|
23356
|
+
}).strict();
|
|
23357
|
+
var ConvexLinkedDeploymentSummarySchema = external_exports.object({
|
|
23358
|
+
convexLinkedDeploymentId: external_exports.uuid(),
|
|
23359
|
+
organizationId: external_exports.uuid(),
|
|
23360
|
+
cloudIntegrationId: external_exports.uuid(),
|
|
23361
|
+
cloudProviderAccountId: external_exports.uuid(),
|
|
23362
|
+
cloudProviderConnectionId: external_exports.uuid(),
|
|
23363
|
+
convexProjectId: external_exports.number().int(),
|
|
23364
|
+
deploymentName: external_exports.string(),
|
|
23365
|
+
deploymentType: external_exports.string(),
|
|
23366
|
+
deploymentRegion: external_exports.string().nullable(),
|
|
23367
|
+
convexCloudUrl: external_exports.string(),
|
|
23368
|
+
convexSiteUrl: external_exports.string().nullable(),
|
|
23369
|
+
deploymentExpiresAt: external_exports.date().nullable(),
|
|
23370
|
+
/**
|
|
23371
|
+
* Whether a usable credential envelope is stored. NOT a scope claim: the key is
|
|
23372
|
+
* full-access, because Convex cannot mint a scoped one for an OAuth app. Read-only
|
|
23373
|
+
* is enforced by the broker that holds the key, never by the credential.
|
|
23374
|
+
*/
|
|
23375
|
+
hasStoredKey: external_exports.boolean(),
|
|
23376
|
+
status: CloudIntegrationStatusSchema,
|
|
23377
|
+
lastVerifiedAt: external_exports.date().nullable(),
|
|
23378
|
+
lastAuthErrorCode: external_exports.string().nullable(),
|
|
23379
|
+
createdAt: external_exports.date(),
|
|
23380
|
+
updatedAt: external_exports.date()
|
|
23381
|
+
}).strict();
|
|
23382
|
+
var ConvexCloudIntegrationListItemSchema = external_exports.object({
|
|
23383
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23384
|
+
deployments: external_exports.array(ConvexLinkedDeploymentSummarySchema)
|
|
23385
|
+
}).strict();
|
|
23386
|
+
var ListConvexCloudIntegrationsResponseSchema = external_exports.object({
|
|
23387
|
+
integrations: external_exports.array(ConvexCloudIntegrationListItemSchema)
|
|
23388
|
+
}).strict();
|
|
23389
|
+
var CreateConvexInstallIntentResponseSchema = external_exports.object({
|
|
23390
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23391
|
+
installUrl: external_exports.url()
|
|
23392
|
+
}).strict();
|
|
23393
|
+
var FinalizeConvexCallbackResponseSchema = external_exports.object({
|
|
23394
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23395
|
+
deployments: external_exports.array(ConvexLinkedDeploymentSummarySchema),
|
|
23396
|
+
/** Deployments beyond the CONVEX_MAX_DEPLOYMENTS cap that were not connected. */
|
|
23397
|
+
droppedDeploymentCount: external_exports.number().int().nonnegative()
|
|
23398
|
+
}).strict();
|
|
23399
|
+
var DisconnectConvexCloudIntegrationResponseSchema = external_exports.object({
|
|
23400
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23401
|
+
deploymentCount: external_exports.number().int().nonnegative(),
|
|
23402
|
+
clearedKeyCount: external_exports.number().int().nonnegative(),
|
|
23403
|
+
/**
|
|
23404
|
+
* Trace cannot revoke a Convex deploy key: there is no deployment-plane endpoint,
|
|
23405
|
+
* the key is not returned by list_deploy_keys, and delete_deploy_key needs an id
|
|
23406
|
+
* the mint never returns. Removing the Trace OAuth app is the only lever the
|
|
23407
|
+
* customer has. A closed union, so PR 2 owns the wording.
|
|
23408
|
+
*/
|
|
23409
|
+
revocationHint: external_exports.literal("REVOKE_OAUTH_APP"),
|
|
23410
|
+
convexApplicationsUrl: external_exports.url().nullable()
|
|
23411
|
+
}).strict();
|
|
23412
|
+
var DisconnectConvexProjectResponseSchema = external_exports.object({
|
|
23413
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23414
|
+
convexProjectId: external_exports.number().int(),
|
|
23415
|
+
deploymentCount: external_exports.number().int().nonnegative(),
|
|
23416
|
+
clearedKeyCount: external_exports.number().int().nonnegative(),
|
|
23417
|
+
revocationHint: external_exports.literal("REVOKE_OAUTH_APP"),
|
|
23418
|
+
convexApplicationsUrl: external_exports.url().nullable()
|
|
23419
|
+
}).strict();
|
|
23420
|
+
var DisconnectConvexDeploymentResponseSchema = external_exports.object({
|
|
23421
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23422
|
+
deployment: ConvexLinkedDeploymentSummarySchema,
|
|
23423
|
+
revocationHint: external_exports.literal("REVOKE_OAUTH_APP"),
|
|
23424
|
+
convexApplicationsUrl: external_exports.url().nullable()
|
|
23425
|
+
}).strict();
|
|
23426
|
+
var ReverifyConvexDeploymentResponseSchema = external_exports.object({
|
|
23427
|
+
integration: ConvexCloudIntegrationSummarySchema,
|
|
23428
|
+
deployment: ConvexLinkedDeploymentSummarySchema
|
|
23429
|
+
}).strict();
|
|
23307
23430
|
|
|
23308
23431
|
// ../../packages/api-contracts/src/contracts/v1/cloud-integration.ts
|
|
23309
23432
|
var c7 = initContract();
|
|
@@ -23604,6 +23727,165 @@ var cloudIntegrationContract = c7.router({
|
|
|
23604
23727
|
503: ErrorResponseSchema,
|
|
23605
23728
|
500: ErrorResponseSchema
|
|
23606
23729
|
}
|
|
23730
|
+
},
|
|
23731
|
+
listConvexIntegrations: {
|
|
23732
|
+
method: "GET",
|
|
23733
|
+
path: "/organizations/:organizationId/cloud-integrations/convex",
|
|
23734
|
+
pathParams: OrgIdParamsSchema,
|
|
23735
|
+
responses: {
|
|
23736
|
+
200: ListConvexCloudIntegrationsResponseSchema,
|
|
23737
|
+
401: ErrorResponseSchema,
|
|
23738
|
+
403: ErrorResponseSchema,
|
|
23739
|
+
404: ErrorResponseSchema,
|
|
23740
|
+
500: ErrorResponseSchema
|
|
23741
|
+
}
|
|
23742
|
+
},
|
|
23743
|
+
createConvexInstallIntent: {
|
|
23744
|
+
method: "POST",
|
|
23745
|
+
path: "/organizations/:organizationId/cloud-integrations/convex/install-intents",
|
|
23746
|
+
pathParams: OrgIdParamsSchema,
|
|
23747
|
+
body: CreateConvexInstallIntentRequestSchema,
|
|
23748
|
+
responses: {
|
|
23749
|
+
201: CreateConvexInstallIntentResponseSchema,
|
|
23750
|
+
400: ErrorResponseSchema,
|
|
23751
|
+
401: ErrorResponseSchema,
|
|
23752
|
+
403: ErrorResponseSchema,
|
|
23753
|
+
404: ErrorResponseSchema,
|
|
23754
|
+
409: ErrorResponseSchema,
|
|
23755
|
+
500: ErrorResponseSchema
|
|
23756
|
+
}
|
|
23757
|
+
},
|
|
23758
|
+
finalizeConvexCallback: {
|
|
23759
|
+
method: "POST",
|
|
23760
|
+
path: "/organizations/:organizationId/cloud-integrations/convex/callback",
|
|
23761
|
+
pathParams: OrgIdParamsSchema,
|
|
23762
|
+
body: FinalizeConvexCallbackRequestSchema,
|
|
23763
|
+
responses: {
|
|
23764
|
+
200: FinalizeConvexCallbackResponseSchema,
|
|
23765
|
+
400: ErrorResponseSchema,
|
|
23766
|
+
401: ErrorResponseSchema,
|
|
23767
|
+
403: ErrorResponseSchema,
|
|
23768
|
+
404: ErrorResponseSchema,
|
|
23769
|
+
409: ErrorResponseSchema,
|
|
23770
|
+
503: ErrorResponseSchema,
|
|
23771
|
+
500: ErrorResponseSchema
|
|
23772
|
+
}
|
|
23773
|
+
},
|
|
23774
|
+
disconnectConvexIntegration: {
|
|
23775
|
+
method: "DELETE",
|
|
23776
|
+
path: "/organizations/:organizationId/cloud-integrations/:cloudIntegrationId/convex",
|
|
23777
|
+
pathParams: CloudIntegrationIdParamsSchema,
|
|
23778
|
+
responses: {
|
|
23779
|
+
200: DisconnectConvexCloudIntegrationResponseSchema,
|
|
23780
|
+
401: ErrorResponseSchema,
|
|
23781
|
+
403: ErrorResponseSchema,
|
|
23782
|
+
404: ErrorResponseSchema,
|
|
23783
|
+
500: ErrorResponseSchema
|
|
23784
|
+
}
|
|
23785
|
+
},
|
|
23786
|
+
disconnectConvexProject: {
|
|
23787
|
+
method: "DELETE",
|
|
23788
|
+
path: "/organizations/:organizationId/cloud-integrations/:cloudIntegrationId/convex/accounts/:cloudProviderAccountId",
|
|
23789
|
+
pathParams: ConvexAccountIdParamsSchema,
|
|
23790
|
+
responses: {
|
|
23791
|
+
200: DisconnectConvexProjectResponseSchema,
|
|
23792
|
+
400: ErrorResponseSchema,
|
|
23793
|
+
401: ErrorResponseSchema,
|
|
23794
|
+
403: ErrorResponseSchema,
|
|
23795
|
+
404: ErrorResponseSchema,
|
|
23796
|
+
500: ErrorResponseSchema
|
|
23797
|
+
}
|
|
23798
|
+
},
|
|
23799
|
+
disconnectConvexDeployment: {
|
|
23800
|
+
method: "DELETE",
|
|
23801
|
+
path: "/organizations/:organizationId/cloud-integrations/:cloudIntegrationId/convex/deployments/:convexLinkedDeploymentId",
|
|
23802
|
+
pathParams: ConvexDeploymentIdParamsSchema,
|
|
23803
|
+
responses: {
|
|
23804
|
+
200: DisconnectConvexDeploymentResponseSchema,
|
|
23805
|
+
400: ErrorResponseSchema,
|
|
23806
|
+
401: ErrorResponseSchema,
|
|
23807
|
+
403: ErrorResponseSchema,
|
|
23808
|
+
404: ErrorResponseSchema,
|
|
23809
|
+
500: ErrorResponseSchema
|
|
23810
|
+
}
|
|
23811
|
+
},
|
|
23812
|
+
reverifyConvexDeployment: {
|
|
23813
|
+
method: "POST",
|
|
23814
|
+
path: "/organizations/:organizationId/cloud-integrations/:cloudIntegrationId/convex/deployments/:convexLinkedDeploymentId/reverify",
|
|
23815
|
+
pathParams: ConvexDeploymentIdParamsSchema,
|
|
23816
|
+
body: c7.noBody(),
|
|
23817
|
+
responses: {
|
|
23818
|
+
200: ReverifyConvexDeploymentResponseSchema,
|
|
23819
|
+
400: ErrorResponseSchema,
|
|
23820
|
+
401: ErrorResponseSchema,
|
|
23821
|
+
403: ErrorResponseSchema,
|
|
23822
|
+
404: ErrorResponseSchema,
|
|
23823
|
+
409: ErrorResponseSchema,
|
|
23824
|
+
503: ErrorResponseSchema,
|
|
23825
|
+
500: ErrorResponseSchema
|
|
23826
|
+
}
|
|
23827
|
+
}
|
|
23828
|
+
});
|
|
23829
|
+
|
|
23830
|
+
// ../../packages/api-contracts/src/schemas/api/v1/code-size.api.ts
|
|
23831
|
+
var CodeSizeBucketTallySchema = external_exports.object({
|
|
23832
|
+
files: external_exports.number().int().nonnegative(),
|
|
23833
|
+
lines: external_exports.number().int().nonnegative(),
|
|
23834
|
+
code: external_exports.number().int().nonnegative()
|
|
23835
|
+
});
|
|
23836
|
+
var CodeSizeLanguageTallySchema = external_exports.object({
|
|
23837
|
+
language: external_exports.string(),
|
|
23838
|
+
files: external_exports.number().int().nonnegative(),
|
|
23839
|
+
code: external_exports.number().int().nonnegative()
|
|
23840
|
+
});
|
|
23841
|
+
var CodeSizePlatformValues = ["GITHUB", "BITBUCKET"];
|
|
23842
|
+
var CodeSizeRepositorySchema = external_exports.object({
|
|
23843
|
+
repositoryId: external_exports.uuid(),
|
|
23844
|
+
repositoryUrl: external_exports.url(),
|
|
23845
|
+
platform: external_exports.enum(CodeSizePlatformValues),
|
|
23846
|
+
/** Billable SLOC of the current resolved branch. null = not measured yet. */
|
|
23847
|
+
billableSloc: external_exports.number().int().nonnegative().nullable()
|
|
23848
|
+
});
|
|
23849
|
+
var CodeSizeBucketsSchema = external_exports.object({
|
|
23850
|
+
code: CodeSizeBucketTallySchema,
|
|
23851
|
+
tests: CodeSizeBucketTallySchema,
|
|
23852
|
+
docs: CodeSizeBucketTallySchema,
|
|
23853
|
+
config_data: CodeSizeBucketTallySchema,
|
|
23854
|
+
vendored_generated: CodeSizeBucketTallySchema
|
|
23855
|
+
});
|
|
23856
|
+
var OrganizationCodeSizeResponseSchema = external_exports.object({
|
|
23857
|
+
/** All CONNECTED GitHub/Bitbucket repos. Server-sorted: measured first by
|
|
23858
|
+
* billableSloc desc (ties repositoryUrl asc), then unmeasured by
|
|
23859
|
+
* repositoryUrl asc — clients render as-is (spec-pr-2 §3.3). */
|
|
23860
|
+
repositories: external_exports.array(CodeSizeRepositorySchema),
|
|
23861
|
+
/** Sums over measured repos only. All-zero when none are measured. */
|
|
23862
|
+
totals: external_exports.object({
|
|
23863
|
+
billableSloc: external_exports.number().int().nonnegative(),
|
|
23864
|
+
rawLines: external_exports.number().int().nonnegative(),
|
|
23865
|
+
buckets: CodeSizeBucketsSchema,
|
|
23866
|
+
/** Merged across repos, re-sorted code desc then language asc, capped
|
|
23867
|
+
* at 12 for display (stored lists are complete; spec-pr-2 §3.2). */
|
|
23868
|
+
codeByLanguage: external_exports.array(CodeSizeLanguageTallySchema),
|
|
23869
|
+
/** Distinct languages in the code bucket across measured repos — the
|
|
23870
|
+
* TRUE count, not codeByLanguage.length (which is display-capped). */
|
|
23871
|
+
languageCount: external_exports.number().int().nonnegative()
|
|
23872
|
+
})
|
|
23873
|
+
});
|
|
23874
|
+
|
|
23875
|
+
// ../../packages/api-contracts/src/contracts/v1/code-size.ts
|
|
23876
|
+
var c8 = initContract();
|
|
23877
|
+
var codeSizeContract = c8.router({
|
|
23878
|
+
getOrganizationCodeSize: {
|
|
23879
|
+
method: "GET",
|
|
23880
|
+
path: "/organizations/:organizationId/code-size",
|
|
23881
|
+
pathParams: OrgIdParamsSchema,
|
|
23882
|
+
responses: {
|
|
23883
|
+
200: OrganizationCodeSizeResponseSchema,
|
|
23884
|
+
401: ErrorResponseSchema,
|
|
23885
|
+
403: ErrorResponseSchema,
|
|
23886
|
+
404: ErrorResponseSchema,
|
|
23887
|
+
500: ErrorResponseSchema
|
|
23888
|
+
}
|
|
23607
23889
|
}
|
|
23608
23890
|
});
|
|
23609
23891
|
|
|
@@ -23714,13 +23996,13 @@ var StorageStateSchema = external_exports.object({
|
|
|
23714
23996
|
} catch {
|
|
23715
23997
|
return;
|
|
23716
23998
|
}
|
|
23717
|
-
s.cookies.forEach((
|
|
23718
|
-
const d2 =
|
|
23999
|
+
s.cookies.forEach((c51, i) => {
|
|
24000
|
+
const d2 = c51.domain.replace(/^\./, "").toLowerCase();
|
|
23719
24001
|
if (d2 !== host && !host.endsWith(`.${d2}`)) {
|
|
23720
24002
|
ctx.addIssue({
|
|
23721
24003
|
code: "custom",
|
|
23722
24004
|
path: ["cookies", i, "domain"],
|
|
23723
|
-
message: `cookie domain "${
|
|
24005
|
+
message: `cookie domain "${c51.domain}" is not the capture origin host "${host}" or a parent domain of it`
|
|
23724
24006
|
});
|
|
23725
24007
|
}
|
|
23726
24008
|
});
|
|
@@ -23751,10 +24033,42 @@ var CredentialIdParamsSchema = OrgIdParamsSchema.extend({
|
|
|
23751
24033
|
var EnvironmentCredentialsParamsSchema = OrgIdParamsSchema.extend({
|
|
23752
24034
|
environmentId: external_exports.uuid()
|
|
23753
24035
|
});
|
|
24036
|
+
var OPAQUE_SECRET_SHAPE = { secretValue: external_exports.string().min(1).max(8192) };
|
|
24037
|
+
var SessionStateSecretValueSchema = external_exports.string().min(1).refine((s) => Buffer.byteLength(s, "utf8") <= 262144, "session state must be \u2264256KB").superRefine((s, ctx) => {
|
|
24038
|
+
const parsed = StorageStateSchema.safeParse(parseJsonOrUndefined(s));
|
|
24039
|
+
if (parsed.success) return;
|
|
24040
|
+
if (parsed.error.issues.length === 0) {
|
|
24041
|
+
ctx.addIssue({
|
|
24042
|
+
code: "custom",
|
|
24043
|
+
message: "secretValue is not a valid StorageState capture"
|
|
24044
|
+
});
|
|
24045
|
+
return;
|
|
24046
|
+
}
|
|
24047
|
+
for (const issue2 of parsed.error.issues) {
|
|
24048
|
+
ctx.addIssue({ code: "custom", message: issue2.message, path: issue2.path });
|
|
24049
|
+
}
|
|
24050
|
+
});
|
|
24051
|
+
var SECRET_SHAPES = {
|
|
24052
|
+
BEARER_TOKEN: OPAQUE_SECRET_SHAPE,
|
|
24053
|
+
JWT_TOKEN: OPAQUE_SECRET_SHAPE,
|
|
24054
|
+
API_KEY: OPAQUE_SECRET_SHAPE,
|
|
24055
|
+
PASSPHRASE: OPAQUE_SECRET_SHAPE,
|
|
24056
|
+
COOKIE: { secretValue: external_exports.string().min(1).max(16384) },
|
|
24057
|
+
// secretValue IS the test-account email (login id + inbox ref). Validated as
|
|
24058
|
+
// an address so a typo is rejected at create/rotate time rather than failing
|
|
24059
|
+
// later when the agent uses it as a login/inbox. 320 = RFC 5321 max length.
|
|
24060
|
+
MAGIC_AUTH: { secretValue: external_exports.email().max(320) },
|
|
24061
|
+
USERNAME_PASSWORD: {
|
|
24062
|
+
username: external_exports.string().min(1).max(500),
|
|
24063
|
+
password: external_exports.string().min(1).max(2048)
|
|
24064
|
+
},
|
|
24065
|
+
SESSION_STATE: { secretValue: SessionStateSecretValueSchema }
|
|
24066
|
+
};
|
|
24067
|
+
var CreateLabelSchema = external_exports.string().max(200).optional();
|
|
23754
24068
|
var CreateBearerSchema = external_exports.object({
|
|
23755
24069
|
credentialType: external_exports.literal("BEARER_TOKEN"),
|
|
23756
|
-
label:
|
|
23757
|
-
|
|
24070
|
+
label: CreateLabelSchema,
|
|
24071
|
+
...SECRET_SHAPES.BEARER_TOKEN,
|
|
23758
24072
|
authConfig: external_exports.object({
|
|
23759
24073
|
type: external_exports.literal("BEARER_TOKEN"),
|
|
23760
24074
|
headerName: external_exports.string().min(1).max(200).optional(),
|
|
@@ -23763,8 +24077,8 @@ var CreateBearerSchema = external_exports.object({
|
|
|
23763
24077
|
}).strict();
|
|
23764
24078
|
var CreateJwtSchema = external_exports.object({
|
|
23765
24079
|
credentialType: external_exports.literal("JWT_TOKEN"),
|
|
23766
|
-
label:
|
|
23767
|
-
|
|
24080
|
+
label: CreateLabelSchema,
|
|
24081
|
+
...SECRET_SHAPES.JWT_TOKEN,
|
|
23768
24082
|
authConfig: external_exports.object({
|
|
23769
24083
|
type: external_exports.literal("JWT_TOKEN"),
|
|
23770
24084
|
headerName: external_exports.string().min(1).max(200).optional(),
|
|
@@ -23773,8 +24087,8 @@ var CreateJwtSchema = external_exports.object({
|
|
|
23773
24087
|
}).strict();
|
|
23774
24088
|
var CreateApiKeySchema = external_exports.object({
|
|
23775
24089
|
credentialType: external_exports.literal("API_KEY"),
|
|
23776
|
-
label:
|
|
23777
|
-
|
|
24090
|
+
label: CreateLabelSchema,
|
|
24091
|
+
...SECRET_SHAPES.API_KEY,
|
|
23778
24092
|
authConfig: external_exports.object({
|
|
23779
24093
|
type: external_exports.literal("API_KEY"),
|
|
23780
24094
|
placement: external_exports.enum(["header", "query"]),
|
|
@@ -23783,16 +24097,15 @@ var CreateApiKeySchema = external_exports.object({
|
|
|
23783
24097
|
}).strict();
|
|
23784
24098
|
var CreatePassphraseSchema = external_exports.object({
|
|
23785
24099
|
credentialType: external_exports.literal("PASSPHRASE"),
|
|
23786
|
-
label:
|
|
23787
|
-
|
|
24100
|
+
label: CreateLabelSchema,
|
|
24101
|
+
...SECRET_SHAPES.PASSPHRASE,
|
|
23788
24102
|
// Passphrases are non-HTTP context — authConfig is empty by design.
|
|
23789
24103
|
authConfig: external_exports.object({ type: external_exports.literal("PASSPHRASE") }).strict().optional()
|
|
23790
24104
|
}).strict();
|
|
23791
24105
|
var CreateUsernamePasswordSchema = external_exports.object({
|
|
23792
24106
|
credentialType: external_exports.literal("USERNAME_PASSWORD"),
|
|
23793
|
-
label:
|
|
23794
|
-
|
|
23795
|
-
password: external_exports.string().min(1).max(2048),
|
|
24107
|
+
label: CreateLabelSchema,
|
|
24108
|
+
...SECRET_SHAPES.USERNAME_PASSWORD,
|
|
23796
24109
|
authConfig: external_exports.object({
|
|
23797
24110
|
type: external_exports.literal("USERNAME_PASSWORD"),
|
|
23798
24111
|
method: external_exports.enum(["form", "basic", "json"]),
|
|
@@ -23806,8 +24119,8 @@ var CreateUsernamePasswordSchema = external_exports.object({
|
|
|
23806
24119
|
}).strict();
|
|
23807
24120
|
var CreateCookieSchema = external_exports.object({
|
|
23808
24121
|
credentialType: external_exports.literal("COOKIE"),
|
|
23809
|
-
label:
|
|
23810
|
-
|
|
24122
|
+
label: CreateLabelSchema,
|
|
24123
|
+
...SECRET_SHAPES.COOKIE,
|
|
23811
24124
|
authConfig: external_exports.object({
|
|
23812
24125
|
type: external_exports.literal("COOKIE"),
|
|
23813
24126
|
cookieName: external_exports.string().min(1).max(200),
|
|
@@ -23817,11 +24130,8 @@ var CreateCookieSchema = external_exports.object({
|
|
|
23817
24130
|
}).strict();
|
|
23818
24131
|
var CreateMagicAuthSchema = external_exports.object({
|
|
23819
24132
|
credentialType: external_exports.literal("MAGIC_AUTH"),
|
|
23820
|
-
label:
|
|
23821
|
-
|
|
23822
|
-
// an address so a typo is rejected at create time rather than failing later
|
|
23823
|
-
// when the agent uses it as a login/inbox. 320 = RFC 5321 max length.
|
|
23824
|
-
secretValue: external_exports.email().max(320),
|
|
24133
|
+
label: CreateLabelSchema,
|
|
24134
|
+
...SECRET_SHAPES.MAGIC_AUTH,
|
|
23825
24135
|
authConfig: external_exports.object({
|
|
23826
24136
|
type: external_exports.literal("MAGIC_AUTH"),
|
|
23827
24137
|
/** @deprecated inert — retained for back-compat only. */
|
|
@@ -23830,21 +24140,8 @@ var CreateMagicAuthSchema = external_exports.object({
|
|
|
23830
24140
|
}).strict();
|
|
23831
24141
|
var CreateSessionStateSchema = external_exports.object({
|
|
23832
24142
|
credentialType: external_exports.literal("SESSION_STATE"),
|
|
23833
|
-
label:
|
|
23834
|
-
|
|
23835
|
-
const parsed = StorageStateSchema.safeParse(parseJsonOrUndefined(s));
|
|
23836
|
-
if (parsed.success) return;
|
|
23837
|
-
if (parsed.error.issues.length === 0) {
|
|
23838
|
-
ctx.addIssue({
|
|
23839
|
-
code: "custom",
|
|
23840
|
-
message: "secretValue is not a valid StorageState capture"
|
|
23841
|
-
});
|
|
23842
|
-
return;
|
|
23843
|
-
}
|
|
23844
|
-
for (const issue2 of parsed.error.issues) {
|
|
23845
|
-
ctx.addIssue({ code: "custom", message: issue2.message, path: issue2.path });
|
|
23846
|
-
}
|
|
23847
|
-
})
|
|
24143
|
+
label: CreateLabelSchema,
|
|
24144
|
+
...SECRET_SHAPES.SESSION_STATE
|
|
23848
24145
|
}).strict();
|
|
23849
24146
|
var CreateCredentialRequestSchema = external_exports.discriminatedUnion("credentialType", [
|
|
23850
24147
|
CreateBearerSchema,
|
|
@@ -23864,7 +24161,15 @@ var CredentialResponseSchema = external_exports.object({
|
|
|
23864
24161
|
credentialType: CredentialType,
|
|
23865
24162
|
authConfig: CredentialAuthConfigSchema.nullable(),
|
|
23866
24163
|
createdAt: external_exports.date(),
|
|
23867
|
-
updatedAt: external_exports.date()
|
|
24164
|
+
updatedAt: external_exports.date(),
|
|
24165
|
+
/**
|
|
24166
|
+
* When the encrypted secret was last REPLACED. Null for a credential never
|
|
24167
|
+
* rotated (including every one created before rotation existed). Distinct
|
|
24168
|
+
* from `updatedAt`, which also moves on label / environment / authConfig
|
|
24169
|
+
* edits — so only this field can evidence a secret change. Not secret
|
|
24170
|
+
* material: a timestamp, safe on the read path.
|
|
24171
|
+
*/
|
|
24172
|
+
secretRotatedAt: external_exports.date().nullable()
|
|
23868
24173
|
}).strict();
|
|
23869
24174
|
var ListCredentialsResponseSchema = external_exports.array(CredentialResponseSchema);
|
|
23870
24175
|
var UpdateCredentialRequestSchema = external_exports.object({
|
|
@@ -23872,10 +24177,41 @@ var UpdateCredentialRequestSchema = external_exports.object({
|
|
|
23872
24177
|
environmentId: external_exports.uuid().optional(),
|
|
23873
24178
|
authConfig: CredentialAuthConfigSchema.nullable().optional()
|
|
23874
24179
|
}).strict();
|
|
24180
|
+
var RotateCredentialSecretRequestSchema = external_exports.discriminatedUnion("credentialType", [
|
|
24181
|
+
external_exports.object({ credentialType: external_exports.literal("BEARER_TOKEN"), ...SECRET_SHAPES.BEARER_TOKEN }).strict(),
|
|
24182
|
+
external_exports.object({ credentialType: external_exports.literal("JWT_TOKEN"), ...SECRET_SHAPES.JWT_TOKEN }).strict(),
|
|
24183
|
+
external_exports.object({ credentialType: external_exports.literal("API_KEY"), ...SECRET_SHAPES.API_KEY }).strict(),
|
|
24184
|
+
external_exports.object({ credentialType: external_exports.literal("PASSPHRASE"), ...SECRET_SHAPES.PASSPHRASE }).strict(),
|
|
24185
|
+
external_exports.object({ credentialType: external_exports.literal("COOKIE"), ...SECRET_SHAPES.COOKIE }).strict(),
|
|
24186
|
+
external_exports.object({ credentialType: external_exports.literal("MAGIC_AUTH"), ...SECRET_SHAPES.MAGIC_AUTH }).strict(),
|
|
24187
|
+
external_exports.object({
|
|
24188
|
+
credentialType: external_exports.literal("USERNAME_PASSWORD"),
|
|
24189
|
+
...SECRET_SHAPES.USERNAME_PASSWORD
|
|
24190
|
+
}).strict(),
|
|
24191
|
+
external_exports.object({ credentialType: external_exports.literal("SESSION_STATE"), ...SECRET_SHAPES.SESSION_STATE }).strict()
|
|
24192
|
+
]);
|
|
24193
|
+
var RevealCredentialSecretResponseSchema = external_exports.discriminatedUnion("credentialType", [
|
|
24194
|
+
external_exports.object({
|
|
24195
|
+
credentialType: external_exports.literal("USERNAME_PASSWORD"),
|
|
24196
|
+
username: external_exports.string(),
|
|
24197
|
+
password: external_exports.string()
|
|
24198
|
+
}).strict(),
|
|
24199
|
+
external_exports.object({
|
|
24200
|
+
credentialType: external_exports.enum([
|
|
24201
|
+
"BEARER_TOKEN",
|
|
24202
|
+
"JWT_TOKEN",
|
|
24203
|
+
"API_KEY",
|
|
24204
|
+
"PASSPHRASE",
|
|
24205
|
+
"COOKIE",
|
|
24206
|
+
"MAGIC_AUTH"
|
|
24207
|
+
]),
|
|
24208
|
+
secretValue: external_exports.string()
|
|
24209
|
+
}).strict()
|
|
24210
|
+
]);
|
|
23875
24211
|
|
|
23876
24212
|
// ../../packages/api-contracts/src/contracts/v1/credential.ts
|
|
23877
|
-
var
|
|
23878
|
-
var credentialContract =
|
|
24213
|
+
var c9 = initContract();
|
|
24214
|
+
var credentialContract = c9.router({
|
|
23879
24215
|
listCredentials: {
|
|
23880
24216
|
method: "GET",
|
|
23881
24217
|
path: "/organizations/:organizationId/environments/:environmentId/credentials",
|
|
@@ -23930,6 +24266,55 @@ var credentialContract = c8.router({
|
|
|
23930
24266
|
500: ErrorResponseSchema
|
|
23931
24267
|
}
|
|
23932
24268
|
},
|
|
24269
|
+
// Replace the stored secret IN PLACE — same credentialId, new KMS envelope.
|
|
24270
|
+
// Separate from PATCH so every route touching KMS or plaintext is greppable
|
|
24271
|
+
// at its own URL. PUT (not PATCH) because the body carries the COMPLETE
|
|
24272
|
+
// secret for the type, so the same request twice yields the same end state.
|
|
24273
|
+
//
|
|
24274
|
+
// Deliberately NOT subject to the CREDENTIAL_IN_USE guard that blocks delete
|
|
24275
|
+
// and env-move during a live pentest: rotation preserves credentialId, so the
|
|
24276
|
+
// engagement's credential set and its ScanCredential rows are untouched —
|
|
24277
|
+
// which is the invariant that guard protects. Mid-engagement is precisely when
|
|
24278
|
+
// a wrong password needs fixing.
|
|
24279
|
+
rotateCredentialSecret: {
|
|
24280
|
+
method: "PUT",
|
|
24281
|
+
path: "/organizations/:organizationId/environments/:environmentId/credentials/:credentialId/secret",
|
|
24282
|
+
pathParams: CredentialIdParamsSchema,
|
|
24283
|
+
body: RotateCredentialSecretRequestSchema,
|
|
24284
|
+
responses: {
|
|
24285
|
+
// Unchanged response shape — a rotate NEVER echoes the secret back.
|
|
24286
|
+
200: CredentialResponseSchema,
|
|
24287
|
+
400: ErrorResponseSchema,
|
|
24288
|
+
401: ErrorResponseSchema,
|
|
24289
|
+
403: ErrorResponseSchema,
|
|
24290
|
+
404: ErrorResponseSchema,
|
|
24291
|
+
// 422 — body's credentialType differs from the stored row's
|
|
24292
|
+
// (errorCode CREDENTIAL_ROTATE_TYPE_MISMATCH). Type changes stay
|
|
24293
|
+
// delete + recreate.
|
|
24294
|
+
422: ErrorResponseSchema,
|
|
24295
|
+
500: ErrorResponseSchema
|
|
24296
|
+
}
|
|
24297
|
+
},
|
|
24298
|
+
// Return the stored plaintext to an authorized human. POST, not GET: it must
|
|
24299
|
+
// never sit in an access log, a browser history entry, or a cacheable read.
|
|
24300
|
+
// Requires a user principal — API keys are rejected, so a leaked trace_sk_*
|
|
24301
|
+
// cannot exfiltrate customer credentials.
|
|
24302
|
+
revealCredentialSecret: {
|
|
24303
|
+
method: "POST",
|
|
24304
|
+
path: "/organizations/:organizationId/environments/:environmentId/credentials/:credentialId/reveal",
|
|
24305
|
+
pathParams: CredentialIdParamsSchema,
|
|
24306
|
+
body: c9.noBody(),
|
|
24307
|
+
responses: {
|
|
24308
|
+
200: RevealCredentialSecretResponseSchema,
|
|
24309
|
+
401: ErrorResponseSchema,
|
|
24310
|
+
403: ErrorResponseSchema,
|
|
24311
|
+
404: ErrorResponseSchema,
|
|
24312
|
+
// 422 — SESSION_STATE has no reveal variant by construction
|
|
24313
|
+
// (errorCode CREDENTIAL_REVEAL_UNSUPPORTED).
|
|
24314
|
+
422: ErrorResponseSchema,
|
|
24315
|
+
500: ErrorResponseSchema
|
|
24316
|
+
}
|
|
24317
|
+
},
|
|
23933
24318
|
deleteCredential: {
|
|
23934
24319
|
method: "DELETE",
|
|
23935
24320
|
path: "/organizations/:organizationId/environments/:environmentId/credentials/:credentialId",
|
|
@@ -24145,8 +24530,8 @@ var DependencySummaryResponseSchema = external_exports.object({
|
|
|
24145
24530
|
});
|
|
24146
24531
|
|
|
24147
24532
|
// ../../packages/api-contracts/src/contracts/v1/dependency.ts
|
|
24148
|
-
var
|
|
24149
|
-
var dependencyContract =
|
|
24533
|
+
var c10 = initContract();
|
|
24534
|
+
var dependencyContract = c10.router({
|
|
24150
24535
|
/** Cross-repo dependency search. Two-phase: pg_trgm on Package, then join repos. */
|
|
24151
24536
|
searchDependencies: {
|
|
24152
24537
|
method: "POST",
|
|
@@ -24291,8 +24676,8 @@ var DockerScoutIntegrationResponseSchema = external_exports.object({
|
|
|
24291
24676
|
});
|
|
24292
24677
|
|
|
24293
24678
|
// ../../packages/api-contracts/src/contracts/v1/docker-scout-integration.ts
|
|
24294
|
-
var
|
|
24295
|
-
var dockerScoutIntegrationContract =
|
|
24679
|
+
var c11 = initContract();
|
|
24680
|
+
var dockerScoutIntegrationContract = c11.router({
|
|
24296
24681
|
createDockerScoutIntegration: {
|
|
24297
24682
|
method: "POST",
|
|
24298
24683
|
path: "/organizations/:organizationId/docker-scout-integration",
|
|
@@ -24481,12 +24866,12 @@ var EngagementResponseSchema = external_exports.object({
|
|
|
24481
24866
|
});
|
|
24482
24867
|
|
|
24483
24868
|
// ../../packages/api-contracts/src/contracts/v1/engagement.ts
|
|
24484
|
-
var
|
|
24869
|
+
var c12 = initContract();
|
|
24485
24870
|
var RecordDashboardSessionRequest = external_exports.object({
|
|
24486
24871
|
sessionId: external_exports.string().min(1).max(100)
|
|
24487
24872
|
});
|
|
24488
24873
|
var RecordDashboardSessionResponse = external_exports.object({});
|
|
24489
|
-
var engagementContract =
|
|
24874
|
+
var engagementContract = c12.router({
|
|
24490
24875
|
recordDashboardSession: {
|
|
24491
24876
|
method: "POST",
|
|
24492
24877
|
// `pathPrefix: '/v1'` is applied at the router level (see
|
|
@@ -24535,7 +24920,7 @@ var EnvironmentResponseSchema = external_exports.object({
|
|
|
24535
24920
|
applicationId: external_exports.uuid(),
|
|
24536
24921
|
organizationId: external_exports.uuid(),
|
|
24537
24922
|
name: external_exports.string(),
|
|
24538
|
-
primaryUrl: external_exports.string(),
|
|
24923
|
+
primaryUrl: external_exports.string().nullable(),
|
|
24539
24924
|
description: external_exports.string().nullable(),
|
|
24540
24925
|
isProduction: external_exports.boolean(),
|
|
24541
24926
|
createdAt: external_exports.date(),
|
|
@@ -24544,7 +24929,7 @@ var EnvironmentResponseSchema = external_exports.object({
|
|
|
24544
24929
|
var ListEnvironmentsResponseSchema = external_exports.array(EnvironmentResponseSchema);
|
|
24545
24930
|
var CreateEnvironmentRequestSchema = external_exports.object({
|
|
24546
24931
|
name: EnvNameSchema,
|
|
24547
|
-
primaryUrl: external_exports.url().max(2048),
|
|
24932
|
+
primaryUrl: external_exports.url().max(2048).optional(),
|
|
24548
24933
|
description: external_exports.string().max(1e3).optional(),
|
|
24549
24934
|
isProduction: external_exports.boolean().optional().default(false)
|
|
24550
24935
|
}).strict();
|
|
@@ -24556,8 +24941,8 @@ var UpdateEnvironmentRequestSchema = external_exports.object({
|
|
|
24556
24941
|
}).strict();
|
|
24557
24942
|
|
|
24558
24943
|
// ../../packages/api-contracts/src/contracts/v1/environment.ts
|
|
24559
|
-
var
|
|
24560
|
-
var environmentContract =
|
|
24944
|
+
var c13 = initContract();
|
|
24945
|
+
var environmentContract = c13.router({
|
|
24561
24946
|
listEnvironments: {
|
|
24562
24947
|
method: "GET",
|
|
24563
24948
|
path: "/organizations/:organizationId/applications/:applicationId/environments",
|
|
@@ -24807,8 +25192,8 @@ var GitHubRepoSchema = external_exports.object({
|
|
|
24807
25192
|
var ListGitHubInstallationReposResponseSchema = external_exports.array(GitHubRepoSchema);
|
|
24808
25193
|
|
|
24809
25194
|
// ../../packages/api-contracts/src/contracts/v1/github.ts
|
|
24810
|
-
var
|
|
24811
|
-
var githubContract =
|
|
25195
|
+
var c14 = initContract();
|
|
25196
|
+
var githubContract = c14.router({
|
|
24812
25197
|
// Tier chooser data: which app tiers this env can connect + the org's
|
|
24813
25198
|
// entitlement default. Pure read (auth context + server config).
|
|
24814
25199
|
getConnectOptions: {
|
|
@@ -24907,7 +25292,7 @@ var githubContract = c13.router({
|
|
|
24907
25292
|
method: "POST",
|
|
24908
25293
|
path: "/organizations/:organizationId/github/install-requests/:requestId/cancel",
|
|
24909
25294
|
pathParams: GitHubInstallRequestParamsSchema,
|
|
24910
|
-
body:
|
|
25295
|
+
body: c14.type(),
|
|
24911
25296
|
responses: {
|
|
24912
25297
|
200: GitHubInstallRequestSchema,
|
|
24913
25298
|
401: ErrorResponseSchema,
|
|
@@ -24918,7 +25303,7 @@ var githubContract = c13.router({
|
|
|
24918
25303
|
}
|
|
24919
25304
|
}
|
|
24920
25305
|
});
|
|
24921
|
-
var staffGithubContract =
|
|
25306
|
+
var staffGithubContract = c14.router({
|
|
24922
25307
|
listStaffInstallations: {
|
|
24923
25308
|
method: "GET",
|
|
24924
25309
|
path: "/staff/github/installations",
|
|
@@ -24961,8 +25346,8 @@ var ManagedInboxLabelParamsSchema = OrgIdParamsSchema.extend({
|
|
|
24961
25346
|
});
|
|
24962
25347
|
|
|
24963
25348
|
// ../../packages/api-contracts/src/contracts/v1/inbox.ts
|
|
24964
|
-
var
|
|
24965
|
-
var inboxContract =
|
|
25349
|
+
var c15 = initContract();
|
|
25350
|
+
var inboxContract = c15.router({
|
|
24966
25351
|
listInboxes: {
|
|
24967
25352
|
method: "GET",
|
|
24968
25353
|
path: "/organizations/:organizationId/inboxes",
|
|
@@ -25039,8 +25424,8 @@ var UpdateKnowledgeBaseResponseSchema = external_exports.object({
|
|
|
25039
25424
|
});
|
|
25040
25425
|
|
|
25041
25426
|
// ../../packages/api-contracts/src/contracts/v1/knowledge-base.ts
|
|
25042
|
-
var
|
|
25043
|
-
var knowledgeBaseContract =
|
|
25427
|
+
var c16 = initContract();
|
|
25428
|
+
var knowledgeBaseContract = c16.router({
|
|
25044
25429
|
getKnowledgeBase: {
|
|
25045
25430
|
method: "GET",
|
|
25046
25431
|
path: "/organizations/:organizationId/knowledge-base",
|
|
@@ -25261,8 +25646,8 @@ var UpdateRepoDocumentContentResponseSchema = external_exports.object({
|
|
|
25261
25646
|
});
|
|
25262
25647
|
|
|
25263
25648
|
// ../../packages/api-contracts/src/contracts/v1/knowledge-document.ts
|
|
25264
|
-
var
|
|
25265
|
-
var knowledgeDocumentContract =
|
|
25649
|
+
var c17 = initContract();
|
|
25650
|
+
var knowledgeDocumentContract = c17.router({
|
|
25266
25651
|
createDocument: {
|
|
25267
25652
|
method: "POST",
|
|
25268
25653
|
path: "/organizations/:organizationId/knowledge-documents",
|
|
@@ -25588,8 +25973,8 @@ var LinearMetadataResponseSchema = external_exports.object({
|
|
|
25588
25973
|
});
|
|
25589
25974
|
|
|
25590
25975
|
// ../../packages/api-contracts/src/contracts/v1/linear-integration.ts
|
|
25591
|
-
var
|
|
25592
|
-
var linearIntegrationContract =
|
|
25976
|
+
var c18 = initContract();
|
|
25977
|
+
var linearIntegrationContract = c18.router({
|
|
25593
25978
|
getLinearIntegration: {
|
|
25594
25979
|
method: "GET",
|
|
25595
25980
|
path: "/organizations/:organizationId/integrations/linear",
|
|
@@ -25607,7 +25992,7 @@ var linearIntegrationContract = c17.router({
|
|
|
25607
25992
|
method: "POST",
|
|
25608
25993
|
path: "/organizations/:organizationId/integrations/linear/connect",
|
|
25609
25994
|
pathParams: OrgIdParamsSchema,
|
|
25610
|
-
body:
|
|
25995
|
+
body: c18.noBody(),
|
|
25611
25996
|
responses: {
|
|
25612
25997
|
200: LinearConnectResponseSchema,
|
|
25613
25998
|
401: ErrorResponseSchema,
|
|
@@ -25622,7 +26007,7 @@ var linearIntegrationContract = c17.router({
|
|
|
25622
26007
|
method: "POST",
|
|
25623
26008
|
path: "/organizations/:organizationId/integrations/linear/disconnect",
|
|
25624
26009
|
pathParams: OrgIdParamsSchema,
|
|
25625
|
-
body:
|
|
26010
|
+
body: c18.noBody(),
|
|
25626
26011
|
responses: {
|
|
25627
26012
|
200: LinearIntegrationResponseSchema,
|
|
25628
26013
|
401: ErrorResponseSchema,
|
|
@@ -25714,7 +26099,7 @@ var CreateLinearTicketsParamsSchema = OrgIdParamsSchema.extend({
|
|
|
25714
26099
|
});
|
|
25715
26100
|
var CreateLinearTicketsRequestSchema = external_exports.object({
|
|
25716
26101
|
/** UUID or PTF-N display id. Cap sized to the ~30s synchronous request budget. */
|
|
25717
|
-
findingIds: external_exports.array(external_exports.string().min(1).max(64)).min(1).max(
|
|
26102
|
+
findingIds: external_exports.array(external_exports.string().min(1).max(64)).min(1).max(50),
|
|
25718
26103
|
/** Single-finding requests only — a title with >1 finding is a 400. */
|
|
25719
26104
|
title: external_exports.string().min(1).max(255).optional(),
|
|
25720
26105
|
/** Destination overrides — ADMIN ONLY (MANAGE_ORGANIZATION); a non-admin sending any is a 403. */
|
|
@@ -25784,8 +26169,8 @@ var LinearTicketContextResponseSchema = external_exports.object({
|
|
|
25784
26169
|
});
|
|
25785
26170
|
|
|
25786
26171
|
// ../../packages/api-contracts/src/contracts/v1/linear-tickets.ts
|
|
25787
|
-
var
|
|
25788
|
-
var linearTicketContract =
|
|
26172
|
+
var c19 = initContract();
|
|
26173
|
+
var linearTicketContract = c19.router({
|
|
25789
26174
|
/**
|
|
25790
26175
|
* Push one or more pentest findings to Linear as tickets. Customer-side
|
|
25791
26176
|
* (VIEW_RESULTS + PENTEST capability); non-admins create into the org's
|
|
@@ -25889,8 +26274,8 @@ var LlmProviderKeyResponseSchema = external_exports.object({
|
|
|
25889
26274
|
var ListLlmProviderKeysResponseSchema = external_exports.array(LlmProviderKeyResponseSchema);
|
|
25890
26275
|
|
|
25891
26276
|
// ../../packages/api-contracts/src/contracts/v1/llm-provider-key.ts
|
|
25892
|
-
var
|
|
25893
|
-
var llmProviderKeyContract =
|
|
26277
|
+
var c20 = initContract();
|
|
26278
|
+
var llmProviderKeyContract = c20.router({
|
|
25894
26279
|
createLlmProviderKey: {
|
|
25895
26280
|
method: "POST",
|
|
25896
26281
|
path: "/organizations/:organizationId/llm-provider-keys",
|
|
@@ -25965,8 +26350,7 @@ var OrgCapabilityValues = [
|
|
|
25965
26350
|
"SCAN_SECRETS",
|
|
25966
26351
|
"SCAN_DAST",
|
|
25967
26352
|
"AUTO_PR_SCANS",
|
|
25968
|
-
"AUTO_PUSH_SCANS"
|
|
25969
|
-
"AUTO_FIX_PR"
|
|
26353
|
+
"AUTO_PUSH_SCANS"
|
|
25970
26354
|
];
|
|
25971
26355
|
var UpdateOrganizationRequestSchema = external_exports.object({
|
|
25972
26356
|
name: external_exports.string().min(1).max(255).optional(),
|
|
@@ -26053,6 +26437,14 @@ var StaffOrganizationSummarySchema = external_exports.object({
|
|
|
26053
26437
|
createdAt: external_exports.date()
|
|
26054
26438
|
});
|
|
26055
26439
|
var ListAllOrganizationsResponseSchema = external_exports.array(StaffOrganizationSummarySchema);
|
|
26440
|
+
var CreateOrganizationRequestSchema = external_exports.object({
|
|
26441
|
+
name: external_exports.string().trim().min(2, "Organization name must be at least 2 characters").max(100, "Organization name must be 100 characters or fewer")
|
|
26442
|
+
});
|
|
26443
|
+
var CreateOrganizationResponseSchema = external_exports.object({
|
|
26444
|
+
organizationId: external_exports.uuid(),
|
|
26445
|
+
slug: external_exports.string(),
|
|
26446
|
+
name: external_exports.string()
|
|
26447
|
+
});
|
|
26056
26448
|
var OnboardingItemValues = [
|
|
26057
26449
|
"CONNECT_CODE",
|
|
26058
26450
|
"CONNECT_CLOUD",
|
|
@@ -26077,8 +26469,8 @@ var LogoDeleteRequestSchema = external_exports.object({
|
|
|
26077
26469
|
});
|
|
26078
26470
|
|
|
26079
26471
|
// ../../packages/api-contracts/src/contracts/v1/organization.ts
|
|
26080
|
-
var
|
|
26081
|
-
var organizationContract =
|
|
26472
|
+
var c21 = initContract();
|
|
26473
|
+
var organizationContract = c21.router({
|
|
26082
26474
|
listOrganizations: {
|
|
26083
26475
|
method: "GET",
|
|
26084
26476
|
path: "/organizations",
|
|
@@ -26109,6 +26501,19 @@ var organizationContract = c20.router({
|
|
|
26109
26501
|
},
|
|
26110
26502
|
summary: "List every organization (Trace staff only)"
|
|
26111
26503
|
},
|
|
26504
|
+
createOrganization: {
|
|
26505
|
+
method: "POST",
|
|
26506
|
+
path: "/staff/organizations",
|
|
26507
|
+
body: CreateOrganizationRequestSchema,
|
|
26508
|
+
responses: {
|
|
26509
|
+
201: CreateOrganizationResponseSchema,
|
|
26510
|
+
400: ErrorResponseSchema,
|
|
26511
|
+
401: ErrorResponseSchema,
|
|
26512
|
+
403: ErrorResponseSchema,
|
|
26513
|
+
500: ErrorResponseSchema
|
|
26514
|
+
},
|
|
26515
|
+
summary: "Create an organization (Trace staff only)"
|
|
26516
|
+
},
|
|
26112
26517
|
getOrganization: {
|
|
26113
26518
|
method: "GET",
|
|
26114
26519
|
path: "/organizations/:organizationId",
|
|
@@ -26269,7 +26674,7 @@ var organizationContract = c20.router({
|
|
|
26269
26674
|
method: "POST",
|
|
26270
26675
|
path: "/organizations/:organizationId/logos-from-homepage",
|
|
26271
26676
|
pathParams: OrgIdParamsSchema,
|
|
26272
|
-
body:
|
|
26677
|
+
body: c21.type(),
|
|
26273
26678
|
responses: {
|
|
26274
26679
|
200: OrganizationResponseSchema,
|
|
26275
26680
|
// 400 — no homepage set on the organization.
|
|
@@ -26525,10 +26930,189 @@ var CustomerPriorityCategoryValues = [
|
|
|
26525
26930
|
];
|
|
26526
26931
|
var CustomerPriorityCategory = external_exports.enum(CustomerPriorityCategoryValues);
|
|
26527
26932
|
|
|
26933
|
+
// ../../packages/api-contracts/src/schemas/domain/pentest-customer-intake.schema.ts
|
|
26934
|
+
var IntakeSurfaceValues = [
|
|
26935
|
+
"WEB",
|
|
26936
|
+
"PUBLIC_API",
|
|
26937
|
+
"INTERNAL_API",
|
|
26938
|
+
"GRAPHQL",
|
|
26939
|
+
"WEBHOOKS",
|
|
26940
|
+
"MCP",
|
|
26941
|
+
"AI_AGENTS",
|
|
26942
|
+
"MOBILE",
|
|
26943
|
+
"DESKTOP",
|
|
26944
|
+
"CLI",
|
|
26945
|
+
"BACKGROUND_JOBS"
|
|
26946
|
+
];
|
|
26947
|
+
var IntakeSurface = external_exports.enum(IntakeSurfaceValues);
|
|
26948
|
+
var PentestCustomerIntakeAnswersShape = external_exports.object({
|
|
26949
|
+
issueClasses: external_exports.array(CustomerPriorityCategory).max(11).optional(),
|
|
26950
|
+
issueClassesNotes: external_exports.string().max(5e3).optional(),
|
|
26951
|
+
focusAreas: external_exports.string().max(5e3).optional(),
|
|
26952
|
+
rolesAndPermissions: external_exports.string().max(1e4).optional(),
|
|
26953
|
+
authenticationSetup: external_exports.string().max(5e3).optional(),
|
|
26954
|
+
tenantIsolationExpectation: external_exports.string().max(5e3).optional(),
|
|
26955
|
+
surfaces: external_exports.array(IntakeSurface).max(11).optional(),
|
|
26956
|
+
surfacesNotes: external_exports.string().max(5e3).optional(),
|
|
26957
|
+
thirdParties: external_exports.string().max(5e3).optional(),
|
|
26958
|
+
sensitiveData: external_exports.string().max(5e3).optional(),
|
|
26959
|
+
neverTouch: external_exports.string().max(5e3).optional(),
|
|
26960
|
+
knownRisks: external_exports.string().max(5e3).optional(),
|
|
26961
|
+
tribalKnowledge: external_exports.string().max(1e4).optional()
|
|
26962
|
+
});
|
|
26963
|
+
var PentestCustomerIntakeAnswersSchema = PentestCustomerIntakeAnswersShape.strict();
|
|
26964
|
+
var PentestCustomerIntakeStoredAnswersSchema = PentestCustomerIntakeAnswersShape;
|
|
26965
|
+
var PentestCustomerIntakeWriteAnswersSchema = PentestCustomerIntakeAnswersShape.extend({
|
|
26966
|
+
/** @deprecated Retired question. Accepted for in-flight clients, never stored. */
|
|
26967
|
+
testEnvironment: external_exports.string().max(100).optional(),
|
|
26968
|
+
/** @deprecated Retired question. Accepted for in-flight clients, never stored. */
|
|
26969
|
+
reposAndBranches: external_exports.string().max(5e3).optional()
|
|
26970
|
+
}).strict();
|
|
26971
|
+
var PENTEST_CUSTOMER_INTAKE_ANSWER_KEYS = [
|
|
26972
|
+
"issueClasses",
|
|
26973
|
+
"issueClassesNotes",
|
|
26974
|
+
"focusAreas",
|
|
26975
|
+
"rolesAndPermissions",
|
|
26976
|
+
"authenticationSetup",
|
|
26977
|
+
"tenantIsolationExpectation",
|
|
26978
|
+
"surfaces",
|
|
26979
|
+
"surfacesNotes",
|
|
26980
|
+
"thirdParties",
|
|
26981
|
+
"sensitiveData",
|
|
26982
|
+
"neverTouch",
|
|
26983
|
+
"knownRisks",
|
|
26984
|
+
"tribalKnowledge"
|
|
26985
|
+
];
|
|
26986
|
+
var PENTEST_CUSTOMER_INTAKE_LABELS = {
|
|
26987
|
+
issueClasses: "Issue classes to prioritize",
|
|
26988
|
+
issueClassesNotes: "Issue classes, additional notes",
|
|
26989
|
+
focusAreas: "Focus areas",
|
|
26990
|
+
rolesAndPermissions: "Roles and permissions",
|
|
26991
|
+
authenticationSetup: "Authentication setup",
|
|
26992
|
+
tenantIsolationExpectation: "Tenant isolation expectations",
|
|
26993
|
+
surfaces: "Surfaces in scope",
|
|
26994
|
+
surfacesNotes: "Surfaces, additional notes",
|
|
26995
|
+
thirdParties: "Third parties and integrations",
|
|
26996
|
+
sensitiveData: "Sensitive data",
|
|
26997
|
+
neverTouch: "Out of bounds / never touch",
|
|
26998
|
+
knownRisks: "Known risks",
|
|
26999
|
+
tribalKnowledge: "Tribal knowledge"
|
|
27000
|
+
};
|
|
27001
|
+
var PENTEST_CUSTOMER_INTAKE_QUESTIONS = [
|
|
27002
|
+
{
|
|
27003
|
+
kind: "multiSelect",
|
|
27004
|
+
key: "issueClasses",
|
|
27005
|
+
notesKey: "issueClassesNotes",
|
|
27006
|
+
question: "Which issue classes worry you most?",
|
|
27007
|
+
helper: "(authn bypass / broken access control / injection / data exposure / supply chain / infra exposure / multi-tenant isolation / crypto / business logic / SSRF / XSS)",
|
|
27008
|
+
notesQuestion: "Anything else about issue classes?"
|
|
27009
|
+
},
|
|
27010
|
+
{
|
|
27011
|
+
kind: "text",
|
|
27012
|
+
key: "focusAreas",
|
|
27013
|
+
question: "Is there any particular application or area you want us to spend extra focus on?"
|
|
27014
|
+
},
|
|
27015
|
+
{
|
|
27016
|
+
kind: "text",
|
|
27017
|
+
key: "rolesAndPermissions",
|
|
27018
|
+
question: "What roles/permissions can users take in your application?",
|
|
27019
|
+
helper: "Explain each role and what it should/shouldn't be able to do."
|
|
27020
|
+
},
|
|
27021
|
+
{
|
|
27022
|
+
kind: "text",
|
|
27023
|
+
key: "authenticationSetup",
|
|
27024
|
+
question: "Anything we should know about your authentication setup?",
|
|
27025
|
+
helper: "(e.g. mid-migration between providers, legacy login still live; otherwise we'll figure it out from the code)"
|
|
27026
|
+
},
|
|
27027
|
+
{
|
|
27028
|
+
kind: "text",
|
|
27029
|
+
key: "tenantIsolationExpectation",
|
|
27030
|
+
question: "What's your expectation for isolation between tenants/organizations?",
|
|
27031
|
+
helper: "What should never be reachable across that boundary?"
|
|
27032
|
+
},
|
|
27033
|
+
{
|
|
27034
|
+
kind: "multiSelect",
|
|
27035
|
+
key: "surfaces",
|
|
27036
|
+
notesKey: "surfacesNotes",
|
|
27037
|
+
question: "Which surfaces exist?",
|
|
27038
|
+
helper: "(web / public API / internal API / GraphQL / webhooks / MCP / AI agents / mobile / desktop / CLI / background jobs)",
|
|
27039
|
+
notesQuestion: "Anything else about your surfaces?"
|
|
27040
|
+
},
|
|
27041
|
+
{
|
|
27042
|
+
kind: "text",
|
|
27043
|
+
key: "thirdParties",
|
|
27044
|
+
question: "Which third parties do you connect to, and should we mock them or stand them up?",
|
|
27045
|
+
helper: "(e.g. CRMs, payment/bank APIs, identity providers, email/SMS, LLM providers)"
|
|
27046
|
+
},
|
|
27047
|
+
{
|
|
27048
|
+
kind: "text",
|
|
27049
|
+
key: "sensitiveData",
|
|
27050
|
+
question: "What data must no attacker ever access?",
|
|
27051
|
+
helper: "And what data do you not care about?"
|
|
27052
|
+
},
|
|
27053
|
+
{
|
|
27054
|
+
kind: "text",
|
|
27055
|
+
key: "neverTouch",
|
|
27056
|
+
question: "What must we never touch or trigger?",
|
|
27057
|
+
helper: "(destructive endpoints, real customer emails/SMS, third-party prod accounts, specific tenants)"
|
|
27058
|
+
},
|
|
27059
|
+
{
|
|
27060
|
+
kind: "text",
|
|
27061
|
+
key: "knownRisks",
|
|
27062
|
+
question: "What do you already know is broken or risky (i.e. what keeps you up at night)?"
|
|
27063
|
+
},
|
|
27064
|
+
{
|
|
27065
|
+
kind: "text",
|
|
27066
|
+
key: "tribalKnowledge",
|
|
27067
|
+
question: "What tribal knowledge would we only learn by asking?",
|
|
27068
|
+
helper: "Anything intentionally weird, counter-intuitive, or likely to trip us up; behavior that looks like a bug but isn't, dead code that's still deployed, a service that isn't what its name suggests."
|
|
27069
|
+
}
|
|
27070
|
+
];
|
|
27071
|
+
var PENTEST_CUSTOMER_INTAKE_QUESTION_COUNT = PENTEST_CUSTOMER_INTAKE_QUESTIONS.length;
|
|
27072
|
+
var INTAKE_ISSUE_CLASS_LABELS = {
|
|
27073
|
+
AUTHN_BYPASS: "Authn bypass",
|
|
27074
|
+
AUTHZ_IDOR: "Broken access control",
|
|
27075
|
+
INJECTION: "Injection",
|
|
27076
|
+
DATA_EXPOSURE: "Data exposure",
|
|
27077
|
+
SUPPLY_CHAIN: "Supply chain",
|
|
27078
|
+
INFRA_EXPOSURE: "Infra exposure",
|
|
27079
|
+
MULTI_TENANT_ISOLATION: "Multi-tenant isolation",
|
|
27080
|
+
CRYPTO_WEAKNESS: "Crypto",
|
|
27081
|
+
BUSINESS_LOGIC: "Business logic",
|
|
27082
|
+
SSRF: "SSRF",
|
|
27083
|
+
XSS: "XSS"
|
|
27084
|
+
};
|
|
27085
|
+
var INTAKE_SURFACE_LABELS = {
|
|
27086
|
+
WEB: "Web",
|
|
27087
|
+
PUBLIC_API: "Public API",
|
|
27088
|
+
INTERNAL_API: "Internal API",
|
|
27089
|
+
GRAPHQL: "GraphQL",
|
|
27090
|
+
WEBHOOKS: "Webhooks",
|
|
27091
|
+
MCP: "MCP",
|
|
27092
|
+
AI_AGENTS: "AI agents",
|
|
27093
|
+
MOBILE: "Mobile",
|
|
27094
|
+
DESKTOP: "Desktop",
|
|
27095
|
+
CLI: "CLI",
|
|
27096
|
+
BACKGROUND_JOBS: "Background jobs"
|
|
27097
|
+
};
|
|
27098
|
+
function normalizePentestCustomerIntakeAnswers(answers) {
|
|
27099
|
+
const next = { ...answers };
|
|
27100
|
+
if (next.issueClasses !== void 0) {
|
|
27101
|
+
next.issueClasses = Array.from(new Set(next.issueClasses)).sort();
|
|
27102
|
+
}
|
|
27103
|
+
if (next.surfaces !== void 0) {
|
|
27104
|
+
next.surfaces = Array.from(new Set(next.surfaces)).sort();
|
|
27105
|
+
}
|
|
27106
|
+
return next;
|
|
27107
|
+
}
|
|
27108
|
+
|
|
26528
27109
|
// ../../packages/api-contracts/src/schemas/api/v1/pentest.api.ts
|
|
26529
27110
|
var PentestIdParamsSchema = OrgIdParamsSchema.extend({
|
|
26530
27111
|
pentestId: external_exports.string().min(1)
|
|
26531
27112
|
});
|
|
27113
|
+
var PentestApplicationParamsSchema = PentestIdParamsSchema.extend({
|
|
27114
|
+
applicationId: external_exports.uuid()
|
|
27115
|
+
});
|
|
26532
27116
|
var CustomerPentestIdParamsSchema = OrgIdParamsSchema.extend({
|
|
26533
27117
|
pentestId: PentestIdOrDisplayIdSchema
|
|
26534
27118
|
});
|
|
@@ -26541,6 +27125,21 @@ var CustomerPentestStatusValues = [
|
|
|
26541
27125
|
"PAUSED"
|
|
26542
27126
|
];
|
|
26543
27127
|
var CustomerPentestStatus = external_exports.enum(CustomerPentestStatusValues);
|
|
27128
|
+
var BoundPentestApplicationSchema = external_exports.object({
|
|
27129
|
+
applicationId: external_exports.uuid(),
|
|
27130
|
+
name: external_exports.string(),
|
|
27131
|
+
type: external_exports.enum(ApplicationTypeValues),
|
|
27132
|
+
// `z.string()`, not `z.url()` — every other URL field on this surface's RESPONSE
|
|
27133
|
+
// side is a plain string. Writes already validate with `z.url()`
|
|
27134
|
+
// (`application.api.ts`), so re-validating stored data here buys nothing and would
|
|
27135
|
+
// let one legacy row 404 an entire staff page through `safeParse`.
|
|
27136
|
+
applicationUrl: external_exports.string().nullable(),
|
|
27137
|
+
/**
|
|
27138
|
+
* Bind order. Never renumbered on unbind, so gaps are normal and only the
|
|
27139
|
+
* relative order carries meaning — the lowest ordinal is the compat mirror.
|
|
27140
|
+
*/
|
|
27141
|
+
ordinal: external_exports.number().int()
|
|
27142
|
+
});
|
|
26544
27143
|
var PentestResponseSchema = external_exports.object({
|
|
26545
27144
|
pentestId: external_exports.uuid(),
|
|
26546
27145
|
organizationId: external_exports.uuid(),
|
|
@@ -26557,8 +27156,21 @@ var PentestResponseSchema = external_exports.object({
|
|
|
26557
27156
|
scope: external_exports.string().nullable(),
|
|
26558
27157
|
/** Granular stage state. Wizard surfaces this; worker transitions write it. */
|
|
26559
27158
|
currentStage: PentestStage,
|
|
26560
|
-
/**
|
|
27159
|
+
/**
|
|
27160
|
+
* The LOWEST-ORDINAL bound application — a compat mirror of the authoritative
|
|
27161
|
+
* `PentestApplication` join, not a distinct concept. Read `applications` when you
|
|
27162
|
+
* need the engagement's real scope; a multi-application engagement reports its
|
|
27163
|
+
* first binding here and would otherwise understate what it covers.
|
|
27164
|
+
*/
|
|
26561
27165
|
primaryApplicationId: external_exports.uuid().nullable(),
|
|
27166
|
+
/**
|
|
27167
|
+
* Every bound application, ordinal-ascending. `.optional()` for rolling-deploy
|
|
27168
|
+
* safety: `apps/web` (Vercel) deploys ahead of `apps/api` (ECS), so a new web
|
|
27169
|
+
* build briefly reads responses from an API that does not send this yet — the
|
|
27170
|
+
* precedent is `PentestDetailResponseSchema` below. Absent means "this API is
|
|
27171
|
+
* older", NOT "no applications bound"; fall back to `primaryApplicationId`.
|
|
27172
|
+
*/
|
|
27173
|
+
applications: external_exports.array(BoundPentestApplicationSchema).optional(),
|
|
26562
27174
|
/** Customer threat-model context — free text. Used by hypothesis-gen prompt. */
|
|
26563
27175
|
customerConcernsContext: external_exports.string().nullable(),
|
|
26564
27176
|
customerPriorityCategories: external_exports.array(CustomerPriorityCategory),
|
|
@@ -26587,7 +27199,44 @@ var PentestDetailResponseSchema = PentestResponseSchema.extend({
|
|
|
26587
27199
|
systemUnderTest: external_exports.string().optional(),
|
|
26588
27200
|
testingWindowStart: external_exports.coerce.date().nullable().optional(),
|
|
26589
27201
|
testingWindowEnd: external_exports.coerce.date().nullable().optional(),
|
|
26590
|
-
engagementMetadataOverrides: EngagementMetadataOverridesSchema.optional()
|
|
27202
|
+
engagementMetadataOverrides: EngagementMetadataOverridesSchema.optional(),
|
|
27203
|
+
/**
|
|
27204
|
+
* True once the engagement's repository scope has been snapshotted, which
|
|
27205
|
+
* PERMANENTLY refuses bind and unbind (`repositoryScopes > 0` in
|
|
27206
|
+
* `requireBindableInLock`).
|
|
27207
|
+
*
|
|
27208
|
+
* This one refusal only — that guard also refuses on `PENTEST_CLOSED` and on a
|
|
27209
|
+
* non-scoping stage, both of which the client can already read off `status` and
|
|
27210
|
+
* `currentStage` on this same response. So `false` means "not frozen by the
|
|
27211
|
+
* snapshot", NOT "a bind will succeed"; a consumer that gates a control must check
|
|
27212
|
+
* the stage and closed state too.
|
|
27213
|
+
*
|
|
27214
|
+
* Needed as its OWN field because nothing else on the wire answers it: the scope
|
|
27215
|
+
* freezes at the first scope-consuming session create, and only VALIDATION moves
|
|
27216
|
+
* the stage, so RECON / CODE_REVIEW / PRODUCT_RECON leave the engagement in
|
|
27217
|
+
* `DRAFT` with permanently frozen bindings. `getRepositoryScope` reports
|
|
27218
|
+
* `source: 'PENTEST_SCOPE'` only PAST the scoping stages, so a frozen `DRAFT`
|
|
27219
|
+
* engagement still returns live application links there.
|
|
27220
|
+
*
|
|
27221
|
+
* Scoped to BINDINGS, not to the whole target: environment add/remove is gated on
|
|
27222
|
+
* stage alone (`PentestEnvironmentService`, `NON_SCOPING_PENTEST_STAGES`), and
|
|
27223
|
+
* `DRAFT` is a scoping stage — so a consumer must not disable environment editing
|
|
27224
|
+
* on this flag. Doing so would remove the one provisioning action a frozen
|
|
27225
|
+
* multi-application engagement still legitimately needs.
|
|
27226
|
+
*
|
|
27227
|
+
* Detail-only (the list schema deliberately carries no per-pentest aggregates) and
|
|
27228
|
+
* `.optional()` for the same rolling-deploy reason as the fields above.
|
|
27229
|
+
*/
|
|
27230
|
+
applicationBindingFrozen: external_exports.boolean().optional(),
|
|
27231
|
+
/**
|
|
27232
|
+
* Optional customer intake questionnaire answers. Staff detail only.
|
|
27233
|
+
* `.optional()` for rolling-deploy safety (Vercel ahead of ECS).
|
|
27234
|
+
*
|
|
27235
|
+
* Read with the lenient schema for the same reason: an API that hasn't
|
|
27236
|
+
* deployed yet still answers with keys from a retired question, and a strict
|
|
27237
|
+
* parse here would fail the whole response instead of ignoring them.
|
|
27238
|
+
*/
|
|
27239
|
+
customerIntakeAnswers: PentestCustomerIntakeStoredAnswersSchema.nullable().optional()
|
|
26591
27240
|
});
|
|
26592
27241
|
var CustomerPentestShellResponseSchema = external_exports.object({
|
|
26593
27242
|
pentestId: external_exports.uuid(),
|
|
@@ -26596,6 +27245,24 @@ var CustomerPentestShellResponseSchema = external_exports.object({
|
|
|
26596
27245
|
title: external_exports.string(),
|
|
26597
27246
|
description: external_exports.string().nullable(),
|
|
26598
27247
|
customerStatus: CustomerPentestStatus,
|
|
27248
|
+
/** The LOWEST-ORDINAL application under test — a compat mirror of the join. Null =
|
|
27249
|
+
* engagement not bound to an application. `.optional()` for rolling-deploy
|
|
27250
|
+
* safety — apps/web (Vercel) deploys ahead of apps/api (ECS).
|
|
27251
|
+
*
|
|
27252
|
+
* Read `applicationIds` for the homepage "In scope" chips: this field names one
|
|
27253
|
+
* application, so using it there marked the other bindings of a multi-application
|
|
27254
|
+
* engagement "Not in current scope" — a false statement on a customer surface. */
|
|
27255
|
+
primaryApplicationId: external_exports.uuid().nullable().optional(),
|
|
27256
|
+
/**
|
|
27257
|
+
* EVERY application this engagement covers, in bind order. Ids only — the customer
|
|
27258
|
+
* homepage already has the org's applications and resolves names locally, and this
|
|
27259
|
+
* surface deliberately shows no more application detail than it did.
|
|
27260
|
+
*
|
|
27261
|
+
* `.optional()` for the same rolling-deploy reason: absent means "this API is
|
|
27262
|
+
* older", NOT "nothing bound", so a consumer must fall back to
|
|
27263
|
+
* `primaryApplicationId` rather than claim the engagement covers nothing.
|
|
27264
|
+
*/
|
|
27265
|
+
applicationIds: external_exports.array(external_exports.uuid()).optional(),
|
|
26599
27266
|
startedAt: external_exports.coerce.date().nullable(),
|
|
26600
27267
|
endedAt: external_exports.coerce.date().nullable(),
|
|
26601
27268
|
createdAt: external_exports.coerce.date(),
|
|
@@ -26614,8 +27281,35 @@ var ListCustomerPentestsResponseSchema = external_exports.array(CustomerPentestR
|
|
|
26614
27281
|
var CustomerPentestDetailResponseSchema = CustomerPentestResponseSchema.extend({
|
|
26615
27282
|
systemUnderTest: external_exports.string().optional(),
|
|
26616
27283
|
testingWindowStart: external_exports.coerce.date().nullable().optional(),
|
|
26617
|
-
testingWindowEnd: external_exports.coerce.date().nullable().optional()
|
|
27284
|
+
testingWindowEnd: external_exports.coerce.date().nullable().optional(),
|
|
27285
|
+
/**
|
|
27286
|
+
* Discovery flags for the questionnaire header CTA. Answer bodies live on
|
|
27287
|
+
* GET …/questionnaire. `.optional()` for rolling-deploy safety.
|
|
27288
|
+
*/
|
|
27289
|
+
questionnaireEditable: external_exports.boolean().optional(),
|
|
27290
|
+
hasQuestionnaireAnswers: external_exports.boolean().optional()
|
|
26618
27291
|
});
|
|
27292
|
+
var CustomerPentestQuestionnaireResponseSchema = external_exports.object({
|
|
27293
|
+
pentestId: external_exports.uuid(),
|
|
27294
|
+
/** True iff currentStage ∈ SCOPING_PENTEST_STAGES (DRAFT | READY_TO_START). */
|
|
27295
|
+
editable: external_exports.boolean(),
|
|
27296
|
+
/**
|
|
27297
|
+
* Lenient on unknown keys: during a rolling deploy the dashboard runs against
|
|
27298
|
+
* an API that still answers with a retired question's key, and a strict parse
|
|
27299
|
+
* would turn that into a broken page instead of an ignored field. Writes stay
|
|
27300
|
+
* strict — see the upsert request below.
|
|
27301
|
+
*/
|
|
27302
|
+
answers: PentestCustomerIntakeStoredAnswersSchema.nullable(),
|
|
27303
|
+
updatedAt: external_exports.coerce.date()
|
|
27304
|
+
});
|
|
27305
|
+
var UpsertCustomerPentestQuestionnaireRequestSchema = external_exports.object({
|
|
27306
|
+
/**
|
|
27307
|
+
* Full answers object, or null to clear. Keys of retired questions are
|
|
27308
|
+
* accepted and dropped so a tab opened before the deploy can still save;
|
|
27309
|
+
* keys that were never questions are still rejected.
|
|
27310
|
+
*/
|
|
27311
|
+
answers: PentestCustomerIntakeWriteAnswersSchema.nullable()
|
|
27312
|
+
}).strict();
|
|
26619
27313
|
var ReadPentestResponseSchema = external_exports.union([
|
|
26620
27314
|
PentestDetailResponseSchema,
|
|
26621
27315
|
CustomerPentestShellResponseSchema
|
|
@@ -26675,6 +27369,14 @@ var UpdatePentestRequestSchema = external_exports.object({
|
|
|
26675
27369
|
scope: external_exports.string().max(5e4).nullable().optional(),
|
|
26676
27370
|
startedAt: external_exports.coerce.date().nullable().optional(),
|
|
26677
27371
|
endedAt: external_exports.coerce.date().nullable().optional(),
|
|
27372
|
+
/**
|
|
27373
|
+
* SINGLE-APPLICATION COMPAT PATH ONLY: means "replace the bound set with exactly
|
|
27374
|
+
* this application", or clear it on `null`. Rejected with 409
|
|
27375
|
+
* `PENTEST_MULTI_APPLICATION_USE_BIND_ENDPOINT` when 2+ applications are already
|
|
27376
|
+
* bound — otherwise one PATCH would silently unbind N−1 of them and bypass the
|
|
27377
|
+
* per-application unbind guard. Use `bindApplication` / `unbindApplication` for
|
|
27378
|
+
* anything multi-application.
|
|
27379
|
+
*/
|
|
26678
27380
|
primaryApplicationId: external_exports.uuid().nullable().optional(),
|
|
26679
27381
|
customerConcernsContext: external_exports.string().max(2e4).nullable().optional(),
|
|
26680
27382
|
customerPriorityCategories: external_exports.array(CustomerPriorityCategory).max(20).optional(),
|
|
@@ -26688,6 +27390,9 @@ var UpdatePentestRequestSchema = external_exports.object({
|
|
|
26688
27390
|
perHypothesisBudgetCapUsd: external_exports.number().min(0).max(1e5).optional(),
|
|
26689
27391
|
lifecycleReason: external_exports.string().trim().min(1).max(2e3).optional()
|
|
26690
27392
|
});
|
|
27393
|
+
var BindPentestApplicationRequestSchema = external_exports.object({
|
|
27394
|
+
applicationId: external_exports.uuid()
|
|
27395
|
+
}).strict();
|
|
26691
27396
|
|
|
26692
27397
|
// ../../packages/api-contracts/src/schemas/api/v1/pentest-stage-transition.api.ts
|
|
26693
27398
|
var StageTransitionResponseSchema = external_exports.object({
|
|
@@ -26742,8 +27447,8 @@ var ScanReuseSuggestionsResponseSchema = external_exports.object({
|
|
|
26742
27447
|
});
|
|
26743
27448
|
|
|
26744
27449
|
// ../../packages/api-contracts/src/contracts/v1/pentest.ts
|
|
26745
|
-
var
|
|
26746
|
-
var pentestContract =
|
|
27450
|
+
var c22 = initContract();
|
|
27451
|
+
var pentestContract = c22.router({
|
|
26747
27452
|
listPentests: {
|
|
26748
27453
|
method: "GET",
|
|
26749
27454
|
path: "/organizations/:organizationId/pentests",
|
|
@@ -26793,6 +27498,33 @@ var pentestContract = c21.router({
|
|
|
26793
27498
|
500: ErrorResponseSchema
|
|
26794
27499
|
}
|
|
26795
27500
|
},
|
|
27501
|
+
getCustomerPentestQuestionnaire: {
|
|
27502
|
+
method: "GET",
|
|
27503
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire",
|
|
27504
|
+
pathParams: CustomerPentestIdParamsSchema,
|
|
27505
|
+
responses: {
|
|
27506
|
+
200: CustomerPentestQuestionnaireResponseSchema,
|
|
27507
|
+
401: ErrorResponseSchema,
|
|
27508
|
+
403: ErrorResponseSchema,
|
|
27509
|
+
404: ErrorResponseSchema,
|
|
27510
|
+
500: ErrorResponseSchema
|
|
27511
|
+
}
|
|
27512
|
+
},
|
|
27513
|
+
upsertCustomerPentestQuestionnaire: {
|
|
27514
|
+
method: "PUT",
|
|
27515
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire",
|
|
27516
|
+
pathParams: CustomerPentestIdParamsSchema,
|
|
27517
|
+
body: UpsertCustomerPentestQuestionnaireRequestSchema,
|
|
27518
|
+
responses: {
|
|
27519
|
+
200: CustomerPentestQuestionnaireResponseSchema,
|
|
27520
|
+
400: ErrorResponseSchema,
|
|
27521
|
+
401: ErrorResponseSchema,
|
|
27522
|
+
403: ErrorResponseSchema,
|
|
27523
|
+
404: ErrorResponseSchema,
|
|
27524
|
+
409: ErrorResponseSchema,
|
|
27525
|
+
500: ErrorResponseSchema
|
|
27526
|
+
}
|
|
27527
|
+
},
|
|
26796
27528
|
createPentest: {
|
|
26797
27529
|
method: "POST",
|
|
26798
27530
|
path: "/organizations/:organizationId/pentests",
|
|
@@ -26849,6 +27581,49 @@ var pentestContract = c21.router({
|
|
|
26849
27581
|
500: ErrorResponseSchema
|
|
26850
27582
|
}
|
|
26851
27583
|
},
|
|
27584
|
+
// POST/DELETE-per-row rather than a batch set on PATCH, mirroring
|
|
27585
|
+
// `pentest-environment.ts`: every rejection stays attributable to ONE
|
|
27586
|
+
// application, where a set-diff would fail an entire save on one blocked
|
|
27587
|
+
// removal with no way to say which.
|
|
27588
|
+
bindApplication: {
|
|
27589
|
+
method: "POST",
|
|
27590
|
+
path: "/organizations/:organizationId/pentests/:pentestId/applications",
|
|
27591
|
+
pathParams: PentestIdParamsSchema,
|
|
27592
|
+
body: BindPentestApplicationRequestSchema,
|
|
27593
|
+
responses: {
|
|
27594
|
+
// The resulting bound set, NOT the detail shape. The 201 body is assembled purely
|
|
27595
|
+
// inside the bind transaction, so it cannot describe a state the write did not
|
|
27596
|
+
// produce; deriving the engagement cover here would mean a fallible read AFTER the
|
|
27597
|
+
// commit. Callers that need the cover GET the pentest.
|
|
27598
|
+
201: PentestResponseSchema,
|
|
27599
|
+
400: ErrorResponseSchema,
|
|
27600
|
+
401: ErrorResponseSchema,
|
|
27601
|
+
403: ErrorResponseSchema,
|
|
27602
|
+
404: ErrorResponseSchema,
|
|
27603
|
+
// 409 — PENTEST_APPLICATION_ALREADY_BOUND (unique violation),
|
|
27604
|
+
// PENTEST_APPLICATION_FROZEN_AT_STAGE (past scoping), or
|
|
27605
|
+
// PENTEST_APPLICATION_SCOPE_FROZEN (repository scope already snapshotted,
|
|
27606
|
+
// so a new binding could never enter it).
|
|
27607
|
+
409: ErrorResponseSchema,
|
|
27608
|
+
500: ErrorResponseSchema
|
|
27609
|
+
}
|
|
27610
|
+
},
|
|
27611
|
+
unbindApplication: {
|
|
27612
|
+
method: "DELETE",
|
|
27613
|
+
path: "/organizations/:organizationId/pentests/:pentestId/applications/:applicationId",
|
|
27614
|
+
pathParams: PentestApplicationParamsSchema,
|
|
27615
|
+
responses: {
|
|
27616
|
+
204: DeleteResponseSchema,
|
|
27617
|
+
400: ErrorResponseSchema,
|
|
27618
|
+
401: ErrorResponseSchema,
|
|
27619
|
+
403: ErrorResponseSchema,
|
|
27620
|
+
404: ErrorResponseSchema,
|
|
27621
|
+
// 409 — PENTEST_APPLICATION_UNBIND_BLOCKED (this application still has
|
|
27622
|
+
// linked environments), or either frozen guard as on bind.
|
|
27623
|
+
409: ErrorResponseSchema,
|
|
27624
|
+
500: ErrorResponseSchema
|
|
27625
|
+
}
|
|
27626
|
+
},
|
|
26852
27627
|
getScanReuseSuggestions: {
|
|
26853
27628
|
method: "GET",
|
|
26854
27629
|
path: "/organizations/:organizationId/pentests/:pentestId/scan-reuse-suggestions",
|
|
@@ -27109,8 +27884,8 @@ var ReadAttestationDownloadResponseSchema = external_exports.union([
|
|
|
27109
27884
|
]);
|
|
27110
27885
|
|
|
27111
27886
|
// ../../packages/api-contracts/src/contracts/v1/pentest-attestation.ts
|
|
27112
|
-
var
|
|
27113
|
-
var pentestAttestationContract =
|
|
27887
|
+
var c23 = initContract();
|
|
27888
|
+
var pentestAttestationContract = c23.router({
|
|
27114
27889
|
getDefaults: {
|
|
27115
27890
|
method: "GET",
|
|
27116
27891
|
path: "/organizations/:organizationId/pentests/:pentestId/attestations/defaults",
|
|
@@ -27252,8 +28027,8 @@ var ListPentestAuditLogResponseSchema = external_exports.object({
|
|
|
27252
28027
|
});
|
|
27253
28028
|
|
|
27254
28029
|
// ../../packages/api-contracts/src/contracts/v1/pentest-audit-log.ts
|
|
27255
|
-
var
|
|
27256
|
-
var pentestAuditLogContract =
|
|
28030
|
+
var c24 = initContract();
|
|
28031
|
+
var pentestAuditLogContract = c24.router({
|
|
27257
28032
|
listAuditLog: {
|
|
27258
28033
|
method: "GET",
|
|
27259
28034
|
path: "/organizations/:organizationId/pentests/:pentestId/audit-log",
|
|
@@ -27269,6 +28044,86 @@ var pentestAuditLogContract = c23.router({
|
|
|
27269
28044
|
}
|
|
27270
28045
|
});
|
|
27271
28046
|
|
|
28047
|
+
// ../../packages/api-contracts/src/schemas/api/v1/pentest-authorized-domain.api.ts
|
|
28048
|
+
var PentestAuthorizedDomainIdParamsSchema = PentestIdParamsSchema.extend({
|
|
28049
|
+
pentestAuthorizedDomainId: external_exports.uuid()
|
|
28050
|
+
});
|
|
28051
|
+
var AuthorizedDomainOriginValues = ["DERIVED", "ENGAGEMENT"];
|
|
28052
|
+
var AuthorizedDomainOrigin = external_exports.enum(AuthorizedDomainOriginValues);
|
|
28053
|
+
var PentestAuthorizedDomainResponseSchema = external_exports.object({
|
|
28054
|
+
/**
|
|
28055
|
+
* NULL for a domain contributed by a bound application while the engagement is
|
|
28056
|
+
* still tracking — there is no row yet, and nothing to address by id.
|
|
28057
|
+
*/
|
|
28058
|
+
pentestAuthorizedDomainId: external_exports.uuid().nullable(),
|
|
28059
|
+
pentestId: external_exports.uuid(),
|
|
28060
|
+
organizationId: external_exports.uuid(),
|
|
28061
|
+
domain: external_exports.string(),
|
|
28062
|
+
applicationIds: external_exports.array(external_exports.uuid()),
|
|
28063
|
+
origin: AuthorizedDomainOrigin,
|
|
28064
|
+
/** NULL when the row was written by materialization rather than by a person. */
|
|
28065
|
+
addedById: external_exports.uuid().nullable(),
|
|
28066
|
+
addedAt: external_exports.date().nullable()
|
|
28067
|
+
});
|
|
28068
|
+
var PentestAuthorizedScopeResponseSchema = external_exports.object({
|
|
28069
|
+
domains: external_exports.array(PentestAuthorizedDomainResponseSchema),
|
|
28070
|
+
/** Null while the engagement still tracks its bound applications. */
|
|
28071
|
+
materializedAt: external_exports.date().nullable()
|
|
28072
|
+
});
|
|
28073
|
+
var CreatePentestAuthorizedDomainRequestSchema = external_exports.object({
|
|
28074
|
+
domain: external_exports.string().trim().min(1).max(253)
|
|
28075
|
+
}).strict();
|
|
28076
|
+
|
|
28077
|
+
// ../../packages/api-contracts/src/contracts/v1/pentest-authorized-domain.ts
|
|
28078
|
+
var c25 = initContract();
|
|
28079
|
+
var pentestAuthorizedDomainContract = c25.router({
|
|
28080
|
+
getPentestAuthorizedScope: {
|
|
28081
|
+
method: "GET",
|
|
28082
|
+
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope",
|
|
28083
|
+
pathParams: PentestIdParamsSchema,
|
|
28084
|
+
responses: {
|
|
28085
|
+
200: PentestAuthorizedScopeResponseSchema,
|
|
28086
|
+
401: ErrorResponseSchema,
|
|
28087
|
+
403: ErrorResponseSchema,
|
|
28088
|
+
404: ErrorResponseSchema,
|
|
28089
|
+
500: ErrorResponseSchema
|
|
28090
|
+
}
|
|
28091
|
+
},
|
|
28092
|
+
addPentestAuthorizedDomain: {
|
|
28093
|
+
method: "POST",
|
|
28094
|
+
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope/domains",
|
|
28095
|
+
pathParams: PentestIdParamsSchema,
|
|
28096
|
+
body: CreatePentestAuthorizedDomainRequestSchema,
|
|
28097
|
+
responses: {
|
|
28098
|
+
201: PentestAuthorizedDomainResponseSchema,
|
|
28099
|
+
// 400 = INVALID_DOMAIN (not a registrable domain / IP / bare suffix);
|
|
28100
|
+
// 409 = DOMAIN_ALREADY_AUTHORIZED or PENTEST_CLOSED.
|
|
28101
|
+
400: ErrorResponseSchema,
|
|
28102
|
+
401: ErrorResponseSchema,
|
|
28103
|
+
403: ErrorResponseSchema,
|
|
28104
|
+
404: ErrorResponseSchema,
|
|
28105
|
+
409: ErrorResponseSchema,
|
|
28106
|
+
500: ErrorResponseSchema
|
|
28107
|
+
}
|
|
28108
|
+
},
|
|
28109
|
+
removePentestAuthorizedDomain: {
|
|
28110
|
+
method: "DELETE",
|
|
28111
|
+
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope/domains/:pentestAuthorizedDomainId",
|
|
28112
|
+
pathParams: PentestAuthorizedDomainIdParamsSchema,
|
|
28113
|
+
responses: {
|
|
28114
|
+
204: DeleteResponseSchema,
|
|
28115
|
+
// 409 = DOMAIN_FROM_ENVIRONMENT (derived from a selected environment's
|
|
28116
|
+
// Target URL, so removing the row here would not remove it from scope) or
|
|
28117
|
+
// PENTEST_CLOSED.
|
|
28118
|
+
401: ErrorResponseSchema,
|
|
28119
|
+
403: ErrorResponseSchema,
|
|
28120
|
+
404: ErrorResponseSchema,
|
|
28121
|
+
409: ErrorResponseSchema,
|
|
28122
|
+
500: ErrorResponseSchema
|
|
28123
|
+
}
|
|
28124
|
+
}
|
|
28125
|
+
});
|
|
28126
|
+
|
|
27272
28127
|
// ../../packages/api-contracts/src/schemas/api/v1/pentest-engagement-exclusion.api.ts
|
|
27273
28128
|
var PentestEngagementExclusionsParamsSchema = OrgIdParamsSchema.extend({
|
|
27274
28129
|
pentestId: external_exports.string().min(1)
|
|
@@ -27294,8 +28149,8 @@ var CreatePentestEngagementExclusionRequestSchema = external_exports.object({
|
|
|
27294
28149
|
}).strict();
|
|
27295
28150
|
|
|
27296
28151
|
// ../../packages/api-contracts/src/contracts/v1/pentest-engagement-exclusion.ts
|
|
27297
|
-
var
|
|
27298
|
-
var pentestEngagementExclusionContract =
|
|
28152
|
+
var c26 = initContract();
|
|
28153
|
+
var pentestEngagementExclusionContract = c26.router({
|
|
27299
28154
|
listPentestEngagementExclusions: {
|
|
27300
28155
|
method: "GET",
|
|
27301
28156
|
path: "/organizations/:organizationId/pentests/:pentestId/engagement-exclusions",
|
|
@@ -27359,8 +28214,8 @@ var CreatePentestEnvironmentRequestSchema = external_exports.object({
|
|
|
27359
28214
|
}).strict();
|
|
27360
28215
|
|
|
27361
28216
|
// ../../packages/api-contracts/src/contracts/v1/pentest-environment.ts
|
|
27362
|
-
var
|
|
27363
|
-
var pentestEnvironmentContract =
|
|
28217
|
+
var c27 = initContract();
|
|
28218
|
+
var pentestEnvironmentContract = c27.router({
|
|
27364
28219
|
listPentestEnvironments: {
|
|
27365
28220
|
method: "GET",
|
|
27366
28221
|
path: "/organizations/:organizationId/pentests/:pentestId/environments",
|
|
@@ -27427,7 +28282,22 @@ var ScopeRowSchema = external_exports.object({
|
|
|
27427
28282
|
type: ScopeRowType,
|
|
27428
28283
|
label: external_exports.string().min(1).max(200),
|
|
27429
28284
|
description: external_exports.string().max(500),
|
|
27430
|
-
inScope: external_exports.boolean()
|
|
28285
|
+
inScope: external_exports.boolean(),
|
|
28286
|
+
/**
|
|
28287
|
+
* Which bound applications this asset belongs to — DISPLAY NAMES in bind order
|
|
28288
|
+
* (multi-application PR 7).
|
|
28289
|
+
*
|
|
28290
|
+
* A SNAPSHOT, like `PentestRepositoryScope.purposeSnapshot`, not a reference: the
|
|
28291
|
+
* report row is a frozen customer-facing document, and resolving application ids at
|
|
28292
|
+
* render time would let a regenerate after an unbind silently shrink a published
|
|
28293
|
+
* scope column. A name that no longer matches a bound application is therefore
|
|
28294
|
+
* legitimate history, not an error.
|
|
28295
|
+
*
|
|
28296
|
+
* Absent or empty means "provenance unknown" — the renderer omits the cell rather
|
|
28297
|
+
* than printing "none" (the PR 1b hand-off rule, shared with the session briefs).
|
|
28298
|
+
* Capped at the row cap so it can never be the binding constraint below it.
|
|
28299
|
+
*/
|
|
28300
|
+
applications: external_exports.array(external_exports.string().min(1).max(200)).max(100).optional()
|
|
27431
28301
|
});
|
|
27432
28302
|
var ScopeRowsJsonSchema = external_exports.object({
|
|
27433
28303
|
version: external_exports.literal(1),
|
|
@@ -27650,7 +28520,13 @@ var ReportCoverBlockSchema = external_exports.object({
|
|
|
27650
28520
|
testingWindowStart: NullableCoverFieldSchema,
|
|
27651
28521
|
testingWindowEnd: NullableCoverFieldSchema,
|
|
27652
28522
|
classification: CoverFieldSchema,
|
|
27653
|
-
documentId: CoverFieldSchema
|
|
28523
|
+
documentId: CoverFieldSchema,
|
|
28524
|
+
/** Report attribution (derive-with-override like the rest; the derived
|
|
28525
|
+
* value is a firm-default constant, so `value` is always present).
|
|
28526
|
+
* testerName renders as "<name> · <firm>" in the cover's Tested-by row;
|
|
28527
|
+
* approverName is the "Approved by" row (conventionally "Name, Title"). */
|
|
28528
|
+
testerName: CoverFieldSchema,
|
|
28529
|
+
approverName: CoverFieldSchema
|
|
27654
28530
|
});
|
|
27655
28531
|
var ReportCoverFieldNameValues = [
|
|
27656
28532
|
"customerOrgName",
|
|
@@ -27660,7 +28536,9 @@ var ReportCoverFieldNameValues = [
|
|
|
27660
28536
|
"testingWindowStart",
|
|
27661
28537
|
"testingWindowEnd",
|
|
27662
28538
|
"classification",
|
|
27663
|
-
"documentId"
|
|
28539
|
+
"documentId",
|
|
28540
|
+
"testerName",
|
|
28541
|
+
"approverName"
|
|
27664
28542
|
];
|
|
27665
28543
|
var ReportCoverFieldName = external_exports.enum(ReportCoverFieldNameValues);
|
|
27666
28544
|
var ApplyReportCoverRequestSchema = external_exports.object({
|
|
@@ -27719,6 +28597,20 @@ var ReportCanvasResponseSchema = external_exports.object({
|
|
|
27719
28597
|
/** Per-field override provenance for the cover grid (RS2). */
|
|
27720
28598
|
cover: ReportCoverBlockSchema,
|
|
27721
28599
|
scopeRows: external_exports.array(ScopeRowSchema),
|
|
28600
|
+
/**
|
|
28601
|
+
* Every bound application's name, in bind order — what the scope editor offers as
|
|
28602
|
+
* per-row application toggles (multi-application PR 7). Empty for an unbound
|
|
28603
|
+
* engagement; a single entry means the editor stays hidden, matching the report's
|
|
28604
|
+
* own rule that one application needs no attribution column.
|
|
28605
|
+
*
|
|
28606
|
+
* OPTIONAL for the wire, not because the server ever omits it: `apps/web` deploys on
|
|
28607
|
+
* merge while the API deploys after it, and the ts-rest client does not validate
|
|
28608
|
+
* response bodies (`apps/web/lib/api-client.ts` sets no `validateResponse`), so a new
|
|
28609
|
+
* bundle briefly reads an old API's response. A required field would be typed as
|
|
28610
|
+
* present while arriving `undefined` — the same reason
|
|
28611
|
+
* `AgentSessionSpawnContextSchema.applications` is optional. Consumers default it.
|
|
28612
|
+
*/
|
|
28613
|
+
boundApplications: external_exports.array(external_exports.string()).optional(),
|
|
27722
28614
|
/** null = undrafted, or stored JSON was unparseable (degraded — never 500). */
|
|
27723
28615
|
narrative: StoredNarrativeJsonSchema.nullable(),
|
|
27724
28616
|
/** Render Section 05 (Remediation Timeline) in the PDF. Lazy/no-row previews
|
|
@@ -27862,6 +28754,11 @@ var IssuedReportSnapshotSchema = external_exports.object({
|
|
|
27862
28754
|
* pre-feature `input_json` still parses (absent → undefined → standard
|
|
27863
28755
|
* branding). */
|
|
27864
28756
|
coBrandName: external_exports.string().nullable().optional(),
|
|
28757
|
+
/** Report attribution frozen at issuance. Optional so every pre-feature
|
|
28758
|
+
* `input_json` still parses (absent → legacy rendering: firm-only
|
|
28759
|
+
* Tested-by row, no Approved-by row). */
|
|
28760
|
+
testerName: external_exports.string().optional(),
|
|
28761
|
+
approverName: external_exports.string().optional(),
|
|
27865
28762
|
engagementTitle: external_exports.string(),
|
|
27866
28763
|
engagementSubtitle: external_exports.string(),
|
|
27867
28764
|
systemUnderTest: external_exports.string(),
|
|
@@ -28189,7 +29086,18 @@ var PentestFindingResponseSchema = external_exports.object({
|
|
|
28189
29086
|
pentestFindingId: external_exports.uuid(),
|
|
28190
29087
|
organizationId: external_exports.uuid(),
|
|
28191
29088
|
pentestId: external_exports.uuid(),
|
|
28192
|
-
|
|
29089
|
+
/**
|
|
29090
|
+
* Customer-facing finding number (the N in `PTF-N`). NULL until the finding is
|
|
29091
|
+
* published: a finding never shown to a customer has no customer-facing number yet.
|
|
29092
|
+
* Staff and agents identify an unpublished finding by `pentestFindingId` + `title`.
|
|
29093
|
+
*
|
|
29094
|
+
* Nullable here so it cascades to the staff and AGENT derivations below — every
|
|
29095
|
+
* agent-session type except REPORT reads findings with no visibility filter
|
|
29096
|
+
* (agent-session.service.ts operatorListFindings/operatorGetFinding), so a draft
|
|
29097
|
+
* reaches them and a non-null schema would be a Zod 500. The customer derivations
|
|
29098
|
+
* re-narrow it to non-null, because customer visibility implies published.
|
|
29099
|
+
*/
|
|
29100
|
+
displayId: external_exports.number().int().positive().nullable(),
|
|
28193
29101
|
title: external_exports.string(),
|
|
28194
29102
|
description: external_exports.string(),
|
|
28195
29103
|
severity: PentestFindingSeverity,
|
|
@@ -28263,9 +29171,11 @@ var OperatorFindingReadSchema = PentestFindingResponseSchema.omit({
|
|
|
28263
29171
|
externalTicket: true
|
|
28264
29172
|
});
|
|
28265
29173
|
var OperatorFindingRetestSchema = external_exports.object({
|
|
29174
|
+
retestId: external_exports.uuid(),
|
|
28266
29175
|
outcome: RetestOutcome,
|
|
28267
29176
|
notes: external_exports.string().nullable(),
|
|
28268
29177
|
testedAt: external_exports.coerce.date(),
|
|
29178
|
+
editedAt: external_exports.coerce.date().nullable(),
|
|
28269
29179
|
source: PentestFindingRetestSource
|
|
28270
29180
|
});
|
|
28271
29181
|
var OperatorFindingDetailSchema = OperatorFindingReadSchema.extend({
|
|
@@ -28295,10 +29205,20 @@ var CustomerPentestFindingResponseSchema = PentestFindingResponseSchema.omit({
|
|
|
28295
29205
|
reportProseAt: true,
|
|
28296
29206
|
reportProseStatus: true
|
|
28297
29207
|
}).extend({
|
|
29208
|
+
// Customer findings are published-only (customerVisiblePentestFindingWhere), and
|
|
29209
|
+
// publishing is what assigns the number, so it always exists here. Re-narrowed from
|
|
29210
|
+
// the nullable root so the customer dashboard never needs a draft affordance; the
|
|
29211
|
+
// handler mapper throws if the invariant is ever violated rather than coercing.
|
|
29212
|
+
displayId: external_exports.number().int().positive(),
|
|
28298
29213
|
// Customer-safe prose/rendering status. This preserves report/PDF heading
|
|
28299
29214
|
// semantics without exposing the staff-only provenance marker pair.
|
|
28300
29215
|
renderedStatus: PentestFindingStatus,
|
|
28301
|
-
repositories: external_exports.array(CustomerPentestFindingRepositorySchema)
|
|
29216
|
+
repositories: external_exports.array(CustomerPentestFindingRepositorySchema),
|
|
29217
|
+
// True when the customer has an unresolved dispute on this finding. Drives the
|
|
29218
|
+
// customer "dispute under review" hint + suppresses the re-dispute affordance,
|
|
29219
|
+
// even after a retest moved the finding off CONTESTED. Only this derived
|
|
29220
|
+
// boolean crosses the trust boundary — never the staff contest list.
|
|
29221
|
+
hasOpenContest: external_exports.boolean()
|
|
28302
29222
|
});
|
|
28303
29223
|
var CustomerPentestFindingListItemSchema = PentestFindingListItemSchema.omit({
|
|
28304
29224
|
organizationId: true,
|
|
@@ -28310,6 +29230,9 @@ var CustomerPentestFindingListItemSchema = PentestFindingListItemSchema.omit({
|
|
|
28310
29230
|
reportProseAt: true,
|
|
28311
29231
|
reportProseStatus: true
|
|
28312
29232
|
}).extend({
|
|
29233
|
+
// Published-only, same as the customer detail schema above — re-narrowed from the
|
|
29234
|
+
// nullable root.
|
|
29235
|
+
displayId: external_exports.number().int().positive(),
|
|
28313
29236
|
repositories: external_exports.array(CustomerPentestFindingRepositorySchema)
|
|
28314
29237
|
});
|
|
28315
29238
|
var ListCustomerPentestFindingsResponseSchema = external_exports.array(
|
|
@@ -28455,7 +29378,12 @@ var RecoveredFindingResultSchema = external_exports.object({
|
|
|
28455
29378
|
status: external_exports.enum(["recovered", "skipped"]),
|
|
28456
29379
|
reason: external_exports.string().optional(),
|
|
28457
29380
|
pentestFindingId: external_exports.uuid().optional(),
|
|
28458
|
-
|
|
29381
|
+
/**
|
|
29382
|
+
* NULL when the recovered finding has no number yet. Recovered findings land
|
|
29383
|
+
* UNPUBLISHED (see the docstring above), and publishing is what assigns the number,
|
|
29384
|
+
* so `.optional()` alone would reject the `null` the service returns.
|
|
29385
|
+
*/
|
|
29386
|
+
findingDisplayId: external_exports.int().positive().nullish(),
|
|
28459
29387
|
/** Preview-only (dryRun): the title + severity the finding WOULD get. */
|
|
28460
29388
|
findingTitle: external_exports.string().optional(),
|
|
28461
29389
|
severity: PentestFindingSeverity.nullable().optional(),
|
|
@@ -28552,8 +29480,9 @@ var PentestFindingContestResponseSchema = external_exports.object({
|
|
|
28552
29480
|
resolvedById: external_exports.uuid().nullable(),
|
|
28553
29481
|
resolvedByName: external_exports.string().nullable(),
|
|
28554
29482
|
resolvedAt: external_exports.coerce.date().nullable(),
|
|
28555
|
-
// The finding status
|
|
28556
|
-
//
|
|
29483
|
+
// The finding's ACTUAL status at resolution time (any active status for a
|
|
29484
|
+
// status-neutral reject). DISMISSED / ACCEPTED_WITH_CONTROLS ⇔ the dispute
|
|
29485
|
+
// was accepted; anything else ⇔ rejected. NULL while open.
|
|
28557
29486
|
resultStatus: PentestFindingStatus.nullable()
|
|
28558
29487
|
});
|
|
28559
29488
|
var ListPentestFindingContestsResponseSchema = external_exports.array(
|
|
@@ -28578,6 +29507,9 @@ var PentestFindingRetestResponseSchema = external_exports.object({
|
|
|
28578
29507
|
testedById: external_exports.uuid(),
|
|
28579
29508
|
testedByName: external_exports.string(),
|
|
28580
29509
|
testedAt: external_exports.coerce.date(),
|
|
29510
|
+
// Null = never corrected. Staff-only: the customer schema below is an explicit
|
|
29511
|
+
// allowlist, so this cannot reach a customer by omission.
|
|
29512
|
+
editedAt: external_exports.coerce.date().nullable(),
|
|
28581
29513
|
source: PentestFindingRetestSource,
|
|
28582
29514
|
retestRunId: external_exports.uuid().nullable(),
|
|
28583
29515
|
performedByActorType: PentestAuditActorType,
|
|
@@ -28658,8 +29590,8 @@ var GetParseTaskStatusResponseSchema = external_exports.object({
|
|
|
28658
29590
|
});
|
|
28659
29591
|
|
|
28660
29592
|
// ../../packages/api-contracts/src/contracts/v1/pentest-finding.ts
|
|
28661
|
-
var
|
|
28662
|
-
var pentestFindingContract =
|
|
29593
|
+
var c28 = initContract();
|
|
29594
|
+
var pentestFindingContract = c28.router({
|
|
28663
29595
|
// ─── Findings ───
|
|
28664
29596
|
listFindings: {
|
|
28665
29597
|
method: "GET",
|
|
@@ -29024,7 +29956,8 @@ var pentestFindingContract = c26.router({
|
|
|
29024
29956
|
401: ErrorResponseSchema,
|
|
29025
29957
|
403: ErrorResponseSchema,
|
|
29026
29958
|
404: ErrorResponseSchema,
|
|
29027
|
-
// CONTEST_ALREADY_RESOLVED,
|
|
29959
|
+
// CONTEST_ALREADY_RESOLVED, CONTEST_REJECT_NOT_ALLOWED (reject on a
|
|
29960
|
+
// dismissed/accepted finding), or PENTEST_CLOSED.
|
|
29028
29961
|
409: ErrorResponseSchema,
|
|
29029
29962
|
500: ErrorResponseSchema
|
|
29030
29963
|
}
|
|
@@ -29247,8 +30180,8 @@ var PromotePentestHypothesisRequestSchema = external_exports.object({
|
|
|
29247
30180
|
}).strict().optional();
|
|
29248
30181
|
|
|
29249
30182
|
// ../../packages/api-contracts/src/contracts/v1/pentest-hypothesis.ts
|
|
29250
|
-
var
|
|
29251
|
-
var pentestHypothesisContract =
|
|
30183
|
+
var c29 = initContract();
|
|
30184
|
+
var pentestHypothesisContract = c29.router({
|
|
29252
30185
|
listHypotheses: {
|
|
29253
30186
|
method: "GET",
|
|
29254
30187
|
path: "/organizations/:organizationId/pentests/:pentestId/hypotheses",
|
|
@@ -29351,8 +30284,8 @@ var pentestHypothesisContract = c27.router({
|
|
|
29351
30284
|
});
|
|
29352
30285
|
|
|
29353
30286
|
// ../../packages/api-contracts/src/contracts/v1/pentest-manual-finding.ts
|
|
29354
|
-
var
|
|
29355
|
-
var pentestManualFindingContract =
|
|
30287
|
+
var c30 = initContract();
|
|
30288
|
+
var pentestManualFindingContract = c30.router({
|
|
29356
30289
|
listManualFindings: {
|
|
29357
30290
|
method: "GET",
|
|
29358
30291
|
path: "/organizations/:organizationId/pentests/:pentestId/manual-findings",
|
|
@@ -29439,8 +30372,8 @@ var pentestManualFindingContract = c28.router({
|
|
|
29439
30372
|
});
|
|
29440
30373
|
|
|
29441
30374
|
// ../../packages/api-contracts/src/contracts/v1/pentest-report-pdf.ts
|
|
29442
|
-
var
|
|
29443
|
-
var pentestReportPdfContract =
|
|
30375
|
+
var c31 = initContract();
|
|
30376
|
+
var pentestReportPdfContract = c31.router({
|
|
29444
30377
|
getCurrent: {
|
|
29445
30378
|
method: "GET",
|
|
29446
30379
|
path: "/organizations/:organizationId/pentests/:pentestId/report-pdf",
|
|
@@ -29533,7 +30466,7 @@ var pentestReportPdfContract = c29.router({
|
|
|
29533
30466
|
// No body: the render always reads current DB state (cover derived via
|
|
29534
30467
|
// deriveReportCover(), narrative/scope from the row's columns). The legacy
|
|
29535
30468
|
// dialog payload was retired with the Generate dialog (report-session RS5).
|
|
29536
|
-
body:
|
|
30469
|
+
body: c31.noBody(),
|
|
29537
30470
|
responses: {
|
|
29538
30471
|
202: StartReportPdfGenerationTaskResponseSchema,
|
|
29539
30472
|
400: ErrorResponseSchema,
|
|
@@ -29724,8 +30657,8 @@ var pentestReportPdfContract = c29.router({
|
|
|
29724
30657
|
});
|
|
29725
30658
|
|
|
29726
30659
|
// ../../packages/api-contracts/src/contracts/v1/pentest-validation.ts
|
|
29727
|
-
var
|
|
29728
|
-
var pentestValidationContract =
|
|
30660
|
+
var c32 = initContract();
|
|
30661
|
+
var pentestValidationContract = c32.router({
|
|
29729
30662
|
listValidationRuns: {
|
|
29730
30663
|
method: "GET",
|
|
29731
30664
|
path: "/organizations/:organizationId/pentests/:pentestId/validation-runs",
|
|
@@ -29833,8 +30766,8 @@ var pentestValidationContract = c30.router({
|
|
|
29833
30766
|
});
|
|
29834
30767
|
|
|
29835
30768
|
// ../../packages/api-contracts/src/contracts/v1/repository.ts
|
|
29836
|
-
var
|
|
29837
|
-
var repositoryContract =
|
|
30769
|
+
var c33 = initContract();
|
|
30770
|
+
var repositoryContract = c33.router({
|
|
29838
30771
|
createRepository: {
|
|
29839
30772
|
method: "POST",
|
|
29840
30773
|
path: "/organizations/:organizationId/repositories",
|
|
@@ -29991,7 +30924,7 @@ var repositoryContract = c31.router({
|
|
|
29991
30924
|
method: "POST",
|
|
29992
30925
|
path: "/organizations/:organizationId/repositories/scanning-branch/confirm-defaults",
|
|
29993
30926
|
pathParams: OrgIdParamsSchema,
|
|
29994
|
-
body:
|
|
30927
|
+
body: c33.noBody(),
|
|
29995
30928
|
responses: {
|
|
29996
30929
|
200: ConfirmScanningBranchDefaultsResponseSchema,
|
|
29997
30930
|
401: ErrorResponseSchema,
|
|
@@ -30000,28 +30933,6 @@ var repositoryContract = c31.router({
|
|
|
30000
30933
|
409: ErrorResponseSchema,
|
|
30001
30934
|
500: ErrorResponseSchema
|
|
30002
30935
|
}
|
|
30003
|
-
},
|
|
30004
|
-
/**
|
|
30005
|
-
* Set / clear the per-repo AI coding-agent override (PR 5).
|
|
30006
|
-
* Body `{overrideTool}`: 'claude-code'|'codex' sets, `null` clears.
|
|
30007
|
-
* Response `{aiToolingProfile}` is nullable: clearing on an undetected
|
|
30008
|
-
* repo writes NULL to the column and returns `{aiToolingProfile: null}`.
|
|
30009
|
-
* 422 = `PLATFORM_VALIDATION_UNSUPPORTED` for non-GITHUB platforms.
|
|
30010
|
-
*/
|
|
30011
|
-
setAiToolingProfileOverride: {
|
|
30012
|
-
method: "PATCH",
|
|
30013
|
-
path: "/organizations/:organizationId/repositories/:repositoryId/ai-tooling-profile",
|
|
30014
|
-
pathParams: RepositoryIdParamsSchema,
|
|
30015
|
-
body: SetAiToolingProfileOverrideRequestSchema,
|
|
30016
|
-
responses: {
|
|
30017
|
-
200: SetAiToolingProfileOverrideResponseSchema,
|
|
30018
|
-
400: ErrorResponseSchema,
|
|
30019
|
-
401: ErrorResponseSchema,
|
|
30020
|
-
403: ErrorResponseSchema,
|
|
30021
|
-
404: ErrorResponseSchema,
|
|
30022
|
-
422: ErrorResponseSchema,
|
|
30023
|
-
500: ErrorResponseSchema
|
|
30024
|
-
}
|
|
30025
30936
|
}
|
|
30026
30937
|
});
|
|
30027
30938
|
|
|
@@ -30147,8 +31058,8 @@ var ListScanLogsResponseSchema = external_exports.object({
|
|
|
30147
31058
|
});
|
|
30148
31059
|
|
|
30149
31060
|
// ../../packages/api-contracts/src/contracts/v1/scan.ts
|
|
30150
|
-
var
|
|
30151
|
-
var scanContract =
|
|
31061
|
+
var c34 = initContract();
|
|
31062
|
+
var scanContract = c34.router({
|
|
30152
31063
|
createScan: {
|
|
30153
31064
|
method: "POST",
|
|
30154
31065
|
path: "/organizations/:organizationId/scans",
|
|
@@ -30310,8 +31221,8 @@ var AttachTestIntegrationRequestSchema = external_exports.object({
|
|
|
30310
31221
|
}).strict();
|
|
30311
31222
|
|
|
30312
31223
|
// ../../packages/api-contracts/src/contracts/v1/test-integration.ts
|
|
30313
|
-
var
|
|
30314
|
-
var testIntegrationContract =
|
|
31224
|
+
var c35 = initContract();
|
|
31225
|
+
var testIntegrationContract = c35.router({
|
|
30315
31226
|
// -- Fixture CRUD (org-less, staff-only) ----------------------------------
|
|
30316
31227
|
listTestIntegrations: {
|
|
30317
31228
|
method: "GET",
|
|
@@ -30438,8 +31349,8 @@ var UpdateStaffProfileRequestSchema = external_exports.object({
|
|
|
30438
31349
|
});
|
|
30439
31350
|
|
|
30440
31351
|
// ../../packages/api-contracts/src/contracts/v1/user.ts
|
|
30441
|
-
var
|
|
30442
|
-
var userContract =
|
|
31352
|
+
var c36 = initContract();
|
|
31353
|
+
var userContract = c36.router({
|
|
30443
31354
|
getStaffProfile: {
|
|
30444
31355
|
method: "GET",
|
|
30445
31356
|
path: "/staff/profile",
|
|
@@ -30536,8 +31447,8 @@ var VantaIntegrationResponseSchema = external_exports.object({
|
|
|
30536
31447
|
});
|
|
30537
31448
|
|
|
30538
31449
|
// ../../packages/api-contracts/src/contracts/v1/vanta-integration.ts
|
|
30539
|
-
var
|
|
30540
|
-
var vantaIntegrationContract =
|
|
31450
|
+
var c37 = initContract();
|
|
31451
|
+
var vantaIntegrationContract = c37.router({
|
|
30541
31452
|
createVantaIntegration: {
|
|
30542
31453
|
method: "POST",
|
|
30543
31454
|
path: "/organizations/:organizationId/vanta-integration",
|
|
@@ -30869,8 +31780,8 @@ var VerifySharedVulnerabilityEmailCodeResponseSchema = external_exports.object({
|
|
|
30869
31780
|
});
|
|
30870
31781
|
|
|
30871
31782
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability.ts
|
|
30872
|
-
var
|
|
30873
|
-
var vulnerabilityContract =
|
|
31783
|
+
var c38 = initContract();
|
|
31784
|
+
var vulnerabilityContract = c38.router({
|
|
30874
31785
|
filterVulnerabilities: {
|
|
30875
31786
|
method: "POST",
|
|
30876
31787
|
path: "/organizations/:organizationId/vulnerabilities/filter",
|
|
@@ -31051,122 +31962,6 @@ var vulnerabilityContract = c36.router({
|
|
|
31051
31962
|
}
|
|
31052
31963
|
});
|
|
31053
31964
|
|
|
31054
|
-
// ../../packages/api-contracts/src/schemas/api/v1/vulnerability-fix-run.api.ts
|
|
31055
|
-
var AGENT_FLAVORS = ["claude-code", "codex"];
|
|
31056
|
-
var VULNERABILITY_FIX_RUN_STATUSES = [
|
|
31057
|
-
"QUEUED",
|
|
31058
|
-
"RUNNING",
|
|
31059
|
-
"ARTIFACTS_READY",
|
|
31060
|
-
"NO_SAFE_FIX",
|
|
31061
|
-
"PATCH_TOO_LARGE",
|
|
31062
|
-
"TESTS_FAILED",
|
|
31063
|
-
"PR_OPENED",
|
|
31064
|
-
"INFRA_FAILED",
|
|
31065
|
-
"STALE_VULN",
|
|
31066
|
-
"TIMED_OUT",
|
|
31067
|
-
"CANCELLED"
|
|
31068
|
-
];
|
|
31069
|
-
var VulnerabilityFixRunPathParamsSchema = VulnerabilityLookupIdParamsSchema.extend({
|
|
31070
|
-
runId: external_exports.uuid()
|
|
31071
|
-
});
|
|
31072
|
-
var TriggerFixRunRequestSchema = external_exports.object({
|
|
31073
|
-
agentFlavor: external_exports.enum(AGENT_FLAVORS).optional()
|
|
31074
|
-
});
|
|
31075
|
-
var VulnerabilityFixRunResponseSchema = external_exports.object({
|
|
31076
|
-
runId: external_exports.uuid(),
|
|
31077
|
-
organizationId: external_exports.uuid(),
|
|
31078
|
-
vulnerabilityId: external_exports.uuid(),
|
|
31079
|
-
repositoryId: external_exports.uuid(),
|
|
31080
|
-
status: external_exports.enum(VULNERABILITY_FIX_RUN_STATUSES),
|
|
31081
|
-
agentFlavor: external_exports.enum(AGENT_FLAVORS),
|
|
31082
|
-
triggeredByUserId: external_exports.uuid().nullable(),
|
|
31083
|
-
triggeredByApiKeyId: external_exports.uuid().nullable(),
|
|
31084
|
-
/**
|
|
31085
|
-
* Display name + avatar of the triggering staff user, resolved
|
|
31086
|
-
* server-side (mirrors `ScanResponseSchema.initiatedByName`). Populated by
|
|
31087
|
-
* every endpoint (list, trigger, get, cancel) so the polled active row in
|
|
31088
|
-
* the runs table keeps the resolved name. `null` only when the run has no
|
|
31089
|
-
* triggering user (api-key path) or the user no longer exists.
|
|
31090
|
-
*/
|
|
31091
|
-
triggeredByName: external_exports.string().nullable(),
|
|
31092
|
-
triggeredByProfilePictureUrl: external_exports.string().nullable(),
|
|
31093
|
-
prUrl: external_exports.string().nullable(),
|
|
31094
|
-
summaryStatus: external_exports.string().nullable(),
|
|
31095
|
-
modelUsed: external_exports.string().nullable(),
|
|
31096
|
-
addedLines: external_exports.number().int().nullable(),
|
|
31097
|
-
removedLines: external_exports.number().int().nullable(),
|
|
31098
|
-
filesChanged: external_exports.number().int().nullable(),
|
|
31099
|
-
statusDetails: external_exports.string().nullable(),
|
|
31100
|
-
queuedAt: external_exports.iso.datetime(),
|
|
31101
|
-
claimedAt: external_exports.iso.datetime().nullable(),
|
|
31102
|
-
deadlineAt: external_exports.iso.datetime().nullable(),
|
|
31103
|
-
completedAt: external_exports.iso.datetime().nullable(),
|
|
31104
|
-
updatedAt: external_exports.iso.datetime()
|
|
31105
|
-
});
|
|
31106
|
-
var ListVulnerabilityFixRunsResponseSchema = external_exports.array(VulnerabilityFixRunResponseSchema);
|
|
31107
|
-
|
|
31108
|
-
// ../../packages/api-contracts/src/contracts/v1/vulnerability-fix-run.ts
|
|
31109
|
-
var c37 = initContract();
|
|
31110
|
-
var vulnerabilityFixRunContract = c37.router({
|
|
31111
|
-
triggerRun: {
|
|
31112
|
-
method: "POST",
|
|
31113
|
-
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/fix-pr-runs",
|
|
31114
|
-
pathParams: VulnerabilityLookupIdParamsSchema,
|
|
31115
|
-
body: TriggerFixRunRequestSchema,
|
|
31116
|
-
responses: {
|
|
31117
|
-
201: VulnerabilityFixRunResponseSchema,
|
|
31118
|
-
400: ErrorResponseSchema,
|
|
31119
|
-
401: ErrorResponseSchema,
|
|
31120
|
-
403: ErrorResponseSchema,
|
|
31121
|
-
404: ErrorResponseSchema,
|
|
31122
|
-
409: ErrorResponseSchema,
|
|
31123
|
-
429: ErrorResponseSchema,
|
|
31124
|
-
500: ErrorResponseSchema
|
|
31125
|
-
}
|
|
31126
|
-
},
|
|
31127
|
-
getRun: {
|
|
31128
|
-
method: "GET",
|
|
31129
|
-
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/fix-pr-runs/:runId",
|
|
31130
|
-
pathParams: VulnerabilityFixRunPathParamsSchema,
|
|
31131
|
-
responses: {
|
|
31132
|
-
200: VulnerabilityFixRunResponseSchema,
|
|
31133
|
-
400: ErrorResponseSchema,
|
|
31134
|
-
401: ErrorResponseSchema,
|
|
31135
|
-
403: ErrorResponseSchema,
|
|
31136
|
-
404: ErrorResponseSchema,
|
|
31137
|
-
500: ErrorResponseSchema
|
|
31138
|
-
}
|
|
31139
|
-
},
|
|
31140
|
-
cancelRun: {
|
|
31141
|
-
method: "POST",
|
|
31142
|
-
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/fix-pr-runs/:runId/cancel",
|
|
31143
|
-
pathParams: VulnerabilityFixRunPathParamsSchema,
|
|
31144
|
-
body: null,
|
|
31145
|
-
responses: {
|
|
31146
|
-
200: VulnerabilityFixRunResponseSchema,
|
|
31147
|
-
400: ErrorResponseSchema,
|
|
31148
|
-
401: ErrorResponseSchema,
|
|
31149
|
-
403: ErrorResponseSchema,
|
|
31150
|
-
404: ErrorResponseSchema,
|
|
31151
|
-
409: ErrorResponseSchema,
|
|
31152
|
-
500: ErrorResponseSchema
|
|
31153
|
-
}
|
|
31154
|
-
},
|
|
31155
|
-
listRuns: {
|
|
31156
|
-
method: "GET",
|
|
31157
|
-
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/fix-pr-runs",
|
|
31158
|
-
pathParams: VulnerabilityLookupIdParamsSchema,
|
|
31159
|
-
responses: {
|
|
31160
|
-
200: ListVulnerabilityFixRunsResponseSchema,
|
|
31161
|
-
400: ErrorResponseSchema,
|
|
31162
|
-
401: ErrorResponseSchema,
|
|
31163
|
-
403: ErrorResponseSchema,
|
|
31164
|
-
404: ErrorResponseSchema,
|
|
31165
|
-
500: ErrorResponseSchema
|
|
31166
|
-
}
|
|
31167
|
-
}
|
|
31168
|
-
});
|
|
31169
|
-
|
|
31170
31965
|
// ../../packages/api-contracts/src/schemas/api/v1/vulnerability-note.api.ts
|
|
31171
31966
|
var VulnerabilityLookupNoteParamsSchema = OrgIdParamsSchema.extend({
|
|
31172
31967
|
vulnerabilityId: VulnerabilityLookupIdSchema
|
|
@@ -31194,8 +31989,8 @@ var UpdateVulnerabilityNoteRequestSchema = external_exports.object({
|
|
|
31194
31989
|
});
|
|
31195
31990
|
|
|
31196
31991
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability-note.ts
|
|
31197
|
-
var
|
|
31198
|
-
var vulnerabilityNoteContract =
|
|
31992
|
+
var c39 = initContract();
|
|
31993
|
+
var vulnerabilityNoteContract = c39.router({
|
|
31199
31994
|
listNotes: {
|
|
31200
31995
|
method: "GET",
|
|
31201
31996
|
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/notes",
|
|
@@ -31376,8 +32171,8 @@ var ListWebhookDeliveriesResponseSchema = external_exports.object({
|
|
|
31376
32171
|
});
|
|
31377
32172
|
|
|
31378
32173
|
// ../../packages/api-contracts/src/contracts/v1/webhook-settings.ts
|
|
31379
|
-
var
|
|
31380
|
-
var webhookSettingsContract =
|
|
32174
|
+
var c40 = initContract();
|
|
32175
|
+
var webhookSettingsContract = c40.router({
|
|
31381
32176
|
listWebhookEndpoints: {
|
|
31382
32177
|
method: "GET",
|
|
31383
32178
|
path: "/organizations/:organizationId/webhook-settings/endpoints",
|
|
@@ -31515,11 +32310,12 @@ var webhookSettingsContract = c39.router({
|
|
|
31515
32310
|
});
|
|
31516
32311
|
|
|
31517
32312
|
// ../../packages/api-contracts/src/contracts/v1/index.ts
|
|
31518
|
-
var
|
|
31519
|
-
var v1Contract =
|
|
32313
|
+
var c41 = initContract();
|
|
32314
|
+
var v1Contract = c41.router(
|
|
31520
32315
|
{
|
|
31521
32316
|
admin: adminContract,
|
|
31522
32317
|
cloudIntegration: cloudIntegrationContract,
|
|
32318
|
+
codeSize: codeSizeContract,
|
|
31523
32319
|
scan: scanContract,
|
|
31524
32320
|
organization: organizationContract,
|
|
31525
32321
|
user: userContract,
|
|
@@ -31536,7 +32332,6 @@ var v1Contract = c40.router(
|
|
|
31536
32332
|
knowledgeDocument: knowledgeDocumentContract,
|
|
31537
32333
|
vulnerability: vulnerabilityContract,
|
|
31538
32334
|
vulnerabilityNote: vulnerabilityNoteContract,
|
|
31539
|
-
vulnerabilityFixRun: vulnerabilityFixRunContract,
|
|
31540
32335
|
webhookSettings: webhookSettingsContract,
|
|
31541
32336
|
application: applicationContract,
|
|
31542
32337
|
chatSession: chatSessionContract,
|
|
@@ -31547,6 +32342,7 @@ var v1Contract = c40.router(
|
|
|
31547
32342
|
pentestAuditLog: pentestAuditLogContract,
|
|
31548
32343
|
pentestEnvironment: pentestEnvironmentContract,
|
|
31549
32344
|
pentestEngagementExclusion: pentestEngagementExclusionContract,
|
|
32345
|
+
pentestAuthorizedDomain: pentestAuthorizedDomainContract,
|
|
31550
32346
|
pentestFinding: pentestFindingContract,
|
|
31551
32347
|
pentestHypothesis: pentestHypothesisContract,
|
|
31552
32348
|
pentestValidation: pentestValidationContract,
|
|
@@ -31565,8 +32361,8 @@ var v1Contract = c40.router(
|
|
|
31565
32361
|
);
|
|
31566
32362
|
|
|
31567
32363
|
// ../../packages/api-contracts/src/contracts/index.ts
|
|
31568
|
-
var
|
|
31569
|
-
var contract =
|
|
32364
|
+
var c42 = initContract();
|
|
32365
|
+
var contract = c42.router({
|
|
31570
32366
|
v1: v1Contract
|
|
31571
32367
|
});
|
|
31572
32368
|
|
|
@@ -31615,7 +32411,7 @@ var ComplianceRegimeValues = [
|
|
|
31615
32411
|
var ComplianceRegime = external_exports.enum(ComplianceRegimeValues);
|
|
31616
32412
|
|
|
31617
32413
|
// ../../packages/api-contracts/src/contracts/v1/agent-session-internal.ts
|
|
31618
|
-
var
|
|
32414
|
+
var c43 = initContract();
|
|
31619
32415
|
var AgentSessionInternalParamsSchema = external_exports.object({
|
|
31620
32416
|
agentSessionId: external_exports.uuid()
|
|
31621
32417
|
});
|
|
@@ -31729,8 +32525,13 @@ var RecordCandidateVulnRequestSchema = external_exports.object({
|
|
|
31729
32525
|
/** Idempotency key, stable across POST retries of one tool invocation. */
|
|
31730
32526
|
sourceKey: external_exports.string().min(1).max(256),
|
|
31731
32527
|
candidate: external_exports.object({
|
|
31732
|
-
|
|
31733
|
-
|
|
32528
|
+
// Kept in lockstep with the record_candidate_vuln tool schema in
|
|
32529
|
+
// apps/agent-session-host/src/recording.ts — a tool cap looser than this
|
|
32530
|
+
// one turns a model-visible limit into an opaque API rejection. title 250 /
|
|
32531
|
+
// description 6000 were raised from 200/5000, which observed usage had
|
|
32532
|
+
// saturated (median description 4154 of 5000).
|
|
32533
|
+
title: external_exports.string().min(1).max(250),
|
|
32534
|
+
description: external_exports.string().min(1).max(6e3),
|
|
31734
32535
|
attackChain: external_exports.string().min(1).max(5e3),
|
|
31735
32536
|
exploitTechnique: external_exports.string().min(1).max(5e3),
|
|
31736
32537
|
prerequisiteAccess: external_exports.string().min(1).max(5e3).optional(),
|
|
@@ -31773,7 +32574,7 @@ var RecordProductContextResponseSchema = external_exports.object({
|
|
|
31773
32574
|
disputed: external_exports.number().int().nonnegative(),
|
|
31774
32575
|
rejected: external_exports.number().int().nonnegative()
|
|
31775
32576
|
});
|
|
31776
|
-
var ThreatModelStatement = external_exports.string().min(1).max(
|
|
32577
|
+
var ThreatModelStatement = external_exports.string().min(1).max(2e3);
|
|
31777
32578
|
var RepoScopedThreatItem = external_exports.object({
|
|
31778
32579
|
repoAlias: external_exports.string().min(1).max(200),
|
|
31779
32580
|
statement: ThreatModelStatement
|
|
@@ -31924,17 +32725,71 @@ var RecordValidationResultRequestSchema = external_exports.object({
|
|
|
31924
32725
|
* customerFacing labels. The api stores them on the `PentestExploitArtifact` row (caption →
|
|
31925
32726
|
* `description`) and links them to the promoted finding.
|
|
31926
32727
|
*/
|
|
31927
|
-
evidence: external_exports.array(RecordValidationEvidenceItemSchema).max(32).optional()
|
|
32728
|
+
evidence: external_exports.array(RecordValidationEvidenceItemSchema).max(32).optional(),
|
|
32729
|
+
/**
|
|
32730
|
+
* PROVEN-only. The EXISTING finding this proof belongs to — the same root-cause
|
|
32731
|
+
* weakness, already reported by an earlier session. Set it INSTEAD of promoting:
|
|
32732
|
+
* the covered candidate(s) attach to that finding and no second finding is created.
|
|
32733
|
+
*
|
|
32734
|
+
* When set, `prose` is that finding's COMPLETE prose with this investigation's
|
|
32735
|
+
* addition folded in (read it with get_finding first), not a fragment — the api
|
|
32736
|
+
* writes the prose columns verbatim. Scoring fields (cvssVector / cweIds / category /
|
|
32737
|
+
* owaspCategory / severity) are REJECTED on a bind rather than silently dropped; a
|
|
32738
|
+
* second proof of a known weakness must not re-score a finding staff already
|
|
32739
|
+
* triaged. `repositories` IS applied, additively.
|
|
32740
|
+
*/
|
|
32741
|
+
bindToPentestFindingId: external_exports.uuid().optional(),
|
|
32742
|
+
/**
|
|
32743
|
+
* The bound finding's `updatedAt` as returned by get_finding. Optimistic lock: a
|
|
32744
|
+
* staff edit landing between the read and this call returns BIND_STALE_FINDING
|
|
32745
|
+
* instead of silently clobbering their text. Required whenever
|
|
32746
|
+
* `bindToPentestFindingId` is set AND `prose` is supplied.
|
|
32747
|
+
*/
|
|
32748
|
+
bindExpectedUpdatedAt: external_exports.coerce.date().optional()
|
|
31928
32749
|
}).refine((body) => (body.hypothesisIds?.length ?? 0) > 0 || body.hypothesisId !== void 0, {
|
|
31929
32750
|
message: "record_validation_result requires hypothesisIds (or the legacy hypothesisId)",
|
|
31930
32751
|
path: ["hypothesisIds"]
|
|
31931
|
-
})
|
|
32752
|
+
}).refine(
|
|
32753
|
+
(body) => body.bindToPentestFindingId === void 0 || body.prose == null || body.bindExpectedUpdatedAt !== void 0,
|
|
32754
|
+
{
|
|
32755
|
+
message: "bindExpectedUpdatedAt is required when binding with prose (pass the finding updatedAt from get_finding)",
|
|
32756
|
+
path: ["bindExpectedUpdatedAt"]
|
|
32757
|
+
}
|
|
32758
|
+
);
|
|
31932
32759
|
var RecordValidationResultResponseSchema = external_exports.object({
|
|
31933
32760
|
attemptId: external_exports.uuid(),
|
|
31934
32761
|
verdict: ValidationVerdict,
|
|
31935
32762
|
/** True when a PentestFinding was created from this PROVEN result. */
|
|
31936
32763
|
promoted: external_exports.boolean(),
|
|
31937
|
-
|
|
32764
|
+
/**
|
|
32765
|
+
* The promoted finding's customer-facing number, or NULL when it has none yet — a
|
|
32766
|
+
* freshly promoted finding is UNPUBLISHED, and publishing is what assigns the number.
|
|
32767
|
+
* `promoted: true` with `findingDisplayId: null` means "finding created, not yet
|
|
32768
|
+
* numbered".
|
|
32769
|
+
*/
|
|
32770
|
+
findingDisplayId: external_exports.number().int().positive().nullish(),
|
|
32771
|
+
/**
|
|
32772
|
+
* The promoted finding's durable id, present whenever `promoted` is true. This is the
|
|
32773
|
+
* handle the agent acts on — and once numbering moves to publish it is the ONLY handle
|
|
32774
|
+
* a freshly promoted finding has, since `findingDisplayId` is null until then.
|
|
32775
|
+
*/
|
|
32776
|
+
pentestFindingId: external_exports.uuid().optional(),
|
|
32777
|
+
/**
|
|
32778
|
+
* True when the verdict attached to an EXISTING finding (`bindToPentestFindingId`)
|
|
32779
|
+
* instead of promoting a new one. `promoted` stays false in that case, while
|
|
32780
|
+
* `pentestFindingId` carries the bound finding — so the agent still holds the handle
|
|
32781
|
+
* for the finding it just acted on.
|
|
32782
|
+
*/
|
|
32783
|
+
bound: external_exports.boolean().optional(),
|
|
32784
|
+
/**
|
|
32785
|
+
* How the bind's addition landed. REPORT_PROSE = merged into the finding's report prose
|
|
32786
|
+
* and its repository links (it was unpublished). FINDING_NOTE = filed as a staff note
|
|
32787
|
+
* instead, because the finding is PUBLISHED: nothing customer-facing on it is
|
|
32788
|
+
* agent-editable, which covers the prose AND any cited repository locations. NONE =
|
|
32789
|
+
* there was nothing to apply — no prose and no citations, or a replay, whose original
|
|
32790
|
+
* call already applied whatever it carried. Present whenever `bound`.
|
|
32791
|
+
*/
|
|
32792
|
+
deltaApplied: external_exports.enum(["REPORT_PROSE", "FINDING_NOTE", "NONE"]).optional(),
|
|
31938
32793
|
/**
|
|
31939
32794
|
* The candidate(s) the verdict was bound to (PR A) — each as {displayId, title} so the
|
|
31940
32795
|
* agent can notice a mis-tag by comparing the echoed TITLE against what it actually
|
|
@@ -31999,6 +32854,55 @@ var AgentSessionLoginCodeResponseSchema = external_exports.object({
|
|
|
31999
32854
|
value: external_exports.string().optional(),
|
|
32000
32855
|
receivedAt: external_exports.coerce.date().optional()
|
|
32001
32856
|
});
|
|
32857
|
+
var AgentSessionListInboxMessagesRequestSchema = external_exports.object({
|
|
32858
|
+
runVersion: external_exports.number().int().nonnegative(),
|
|
32859
|
+
/** Which account's inbox (by `Credential.label`); omit if exactly one is readable. */
|
|
32860
|
+
credentialLabel: external_exports.string().min(1).max(200).optional(),
|
|
32861
|
+
/** Max messages, newest first. Clamped server-side. */
|
|
32862
|
+
limit: external_exports.number().int().positive().max(50).optional()
|
|
32863
|
+
});
|
|
32864
|
+
var InboxMessageSummarySchema = external_exports.object({
|
|
32865
|
+
messageId: external_exports.string().min(1).max(500),
|
|
32866
|
+
from: external_exports.string().max(500),
|
|
32867
|
+
subject: external_exports.string().max(1e3).nullable(),
|
|
32868
|
+
/** Provider-generated short body preview. */
|
|
32869
|
+
preview: external_exports.string().max(2e3).nullable(),
|
|
32870
|
+
receivedAt: external_exports.coerce.date(),
|
|
32871
|
+
unread: external_exports.boolean()
|
|
32872
|
+
});
|
|
32873
|
+
var AgentSessionListInboxMessagesResponseSchema = external_exports.object({
|
|
32874
|
+
/** The account whose inbox was read, echoed so the agent can pass it to get_email. */
|
|
32875
|
+
credentialLabel: external_exports.string().max(200),
|
|
32876
|
+
messages: external_exports.array(InboxMessageSummarySchema)
|
|
32877
|
+
});
|
|
32878
|
+
var AgentSessionGetInboxMessageRequestSchema = external_exports.object({
|
|
32879
|
+
runVersion: external_exports.number().int().nonnegative(),
|
|
32880
|
+
/** Message id from a `list_emails` result. */
|
|
32881
|
+
messageId: external_exports.string().min(1).max(500),
|
|
32882
|
+
credentialLabel: external_exports.string().min(1).max(200).optional()
|
|
32883
|
+
});
|
|
32884
|
+
var AgentSessionGetInboxMessageResponseSchema = external_exports.object({
|
|
32885
|
+
credentialLabel: external_exports.string().max(200),
|
|
32886
|
+
message: InboxMessageSummarySchema.extend({
|
|
32887
|
+
/**
|
|
32888
|
+
* The body as plain text, prompt-injection-neutralized and length-capped
|
|
32889
|
+
* ({@link INBOX_MESSAGE_BODY_MAX_CHARS}). Deliberately NOT run through the
|
|
32890
|
+
* credential redactor — that would rewrite the `?token=…` in a magic link,
|
|
32891
|
+
* which is the artifact the agent needs.
|
|
32892
|
+
*/
|
|
32893
|
+
body: external_exports.string(),
|
|
32894
|
+
/** True when the body was truncated at the cap. */
|
|
32895
|
+
truncated: external_exports.boolean()
|
|
32896
|
+
}),
|
|
32897
|
+
/**
|
|
32898
|
+
* http(s) links extracted from the message in priority order (hrefs first,
|
|
32899
|
+
* then inline text URLs), pre-computed so the agent doesn't have to parse the
|
|
32900
|
+
* body. Same extraction and same URL-safety guards the login flow used.
|
|
32901
|
+
*/
|
|
32902
|
+
links: external_exports.array(external_exports.string()),
|
|
32903
|
+
/** Detected one-time code, if the message carried one. */
|
|
32904
|
+
otp: external_exports.string().nullable()
|
|
32905
|
+
});
|
|
32002
32906
|
var RenewCloudCredentialsRequestSchema = external_exports.object({
|
|
32003
32907
|
runVersion: external_exports.number().int().nonnegative()
|
|
32004
32908
|
});
|
|
@@ -32014,6 +32918,42 @@ var RenewCloudCredentialsResponseSchema = external_exports.object({
|
|
|
32014
32918
|
accessToken: external_exports.string().min(1)
|
|
32015
32919
|
}).nullable()
|
|
32016
32920
|
});
|
|
32921
|
+
var ConvexReconRequestSchema = external_exports.object({
|
|
32922
|
+
runVersion: external_exports.number().int().nonnegative()
|
|
32923
|
+
});
|
|
32924
|
+
var ConvexReconInventorySchema = external_exports.discriminatedUnion("status", [
|
|
32925
|
+
/**
|
|
32926
|
+
* Convex's `apiSpec` payload, forwarded verbatim: per function the identifier,
|
|
32927
|
+
* type, visibility (public/internal) and argument validators, plus httpRoutes
|
|
32928
|
+
* and cronSpecs. Deliberately `unknown` — it describes the customer's own
|
|
32929
|
+
* deployment, not a Trace domain object, so pinning its shape would break when
|
|
32930
|
+
* Convex extends it.
|
|
32931
|
+
*/
|
|
32932
|
+
external_exports.object({ status: external_exports.literal("ok"), functions: external_exports.unknown() }),
|
|
32933
|
+
/** Convex answered HTTP 200 with `status: "error"` — a function-level error. */
|
|
32934
|
+
external_exports.object({ status: external_exports.literal("error"), message: external_exports.string() }),
|
|
32935
|
+
/** Convex 401/403 — the grant is gone; the row was flipped ACCESS_DENIED. */
|
|
32936
|
+
external_exports.object({ status: external_exports.literal("access_denied") }),
|
|
32937
|
+
/** Convex 429/5xx/timeout, a decrypt failure, or the response budget spent. */
|
|
32938
|
+
external_exports.object({ status: external_exports.literal("unavailable") }),
|
|
32939
|
+
/** Over the per-deployment byte cap. NEVER truncated — a half inventory read as
|
|
32940
|
+
* complete is worse than an explicit gap. */
|
|
32941
|
+
external_exports.object({ status: external_exports.literal("too_large"), bytes: external_exports.number().int().nonnegative() })
|
|
32942
|
+
]);
|
|
32943
|
+
var ConvexReconDeploymentSchema = external_exports.object({
|
|
32944
|
+
deploymentName: external_exports.string().min(1),
|
|
32945
|
+
/** Convex's DeploymentType verbatim (dev/prod/preview/custom) — never an enum. */
|
|
32946
|
+
deploymentType: external_exports.string().min(1),
|
|
32947
|
+
/** Region-qualified, from the stored row. NEVER synthesised from deploymentName. */
|
|
32948
|
+
convexCloudUrl: external_exports.string().min(1),
|
|
32949
|
+
/** Null when get_canonical_urls failed at connect; the host is not derivable. */
|
|
32950
|
+
convexSiteUrl: external_exports.string().min(1).nullable(),
|
|
32951
|
+
inventory: ConvexReconInventorySchema
|
|
32952
|
+
});
|
|
32953
|
+
var ConvexReconResponseSchema = external_exports.object({
|
|
32954
|
+
/** Empty when the org has no connected, key-bearing Convex deployment. */
|
|
32955
|
+
deployments: external_exports.array(ConvexReconDeploymentSchema)
|
|
32956
|
+
});
|
|
32017
32957
|
var AgentSessionGetSessionStateRequestSchema = external_exports.object({
|
|
32018
32958
|
runVersion: external_exports.number().int().nonnegative(),
|
|
32019
32959
|
/** Which SESSION_STATE credential to fetch (from the non-secret env reference). */
|
|
@@ -32154,6 +33094,32 @@ var OperatorRecordFindingRetestRequestSchema = CreatePentestFindingRetestRequest
|
|
|
32154
33094
|
});
|
|
32155
33095
|
}
|
|
32156
33096
|
});
|
|
33097
|
+
var OperatorRetestAckSchema = OperatorFindingReadSchema.extend({
|
|
33098
|
+
retestId: external_exports.uuid()
|
|
33099
|
+
});
|
|
33100
|
+
var OperatorEditFindingRetestRequestSchema = external_exports.object({
|
|
33101
|
+
runVersion: operatorRunVersion,
|
|
33102
|
+
reason: operatorReason,
|
|
33103
|
+
retestId: external_exports.uuid(),
|
|
33104
|
+
outcome: RetestOutcome.optional(),
|
|
33105
|
+
notes: external_exports.string().trim().min(1).max(1e4).optional(),
|
|
33106
|
+
verification: external_exports.string().min(1).max(8e3).optional()
|
|
33107
|
+
}).superRefine((v2, ctx) => {
|
|
33108
|
+
if (v2.outcome === void 0 && v2.notes === void 0) {
|
|
33109
|
+
ctx.addIssue({
|
|
33110
|
+
code: "custom",
|
|
33111
|
+
message: "provide outcome, notes, or both \u2014 an edit must change something",
|
|
33112
|
+
path: ["notes"]
|
|
33113
|
+
});
|
|
33114
|
+
}
|
|
33115
|
+
if (v2.verification !== void 0 && v2.outcome !== "FIXED") {
|
|
33116
|
+
ctx.addIssue({
|
|
33117
|
+
code: "custom",
|
|
33118
|
+
message: "verification report prose is only allowed when outcome is FIXED",
|
|
33119
|
+
path: ["verification"]
|
|
33120
|
+
});
|
|
33121
|
+
}
|
|
33122
|
+
});
|
|
32157
33123
|
var OperatorMarkRemediationReportedRequestSchema = MarkPentestFindingRemediationReportedRequestSchema.extend({
|
|
32158
33124
|
runVersion: operatorRunVersion,
|
|
32159
33125
|
reason: operatorReason,
|
|
@@ -32300,7 +33266,7 @@ var ReportUpdateScopeRequestSchema = external_exports.object({
|
|
|
32300
33266
|
expectedUpdatedAt: reportExpectedUpdatedAt,
|
|
32301
33267
|
rows: external_exports.array(ScopeRowSchema).max(100)
|
|
32302
33268
|
});
|
|
32303
|
-
var agentSessionInternalContract =
|
|
33269
|
+
var agentSessionInternalContract = c43.router({
|
|
32304
33270
|
postEvents: {
|
|
32305
33271
|
method: "POST",
|
|
32306
33272
|
path: "/internal/v1/agent-sessions/:agentSessionId/events",
|
|
@@ -32457,6 +33423,10 @@ var agentSessionInternalContract = c42.router({
|
|
|
32457
33423
|
200: ReattributeValidationResultResponseSchema,
|
|
32458
33424
|
400: ErrorResponseSchema,
|
|
32459
33425
|
401: ErrorResponseSchema,
|
|
33426
|
+
// The attempt or the target hypothesis does not exist in this pentest — in practice a
|
|
33427
|
+
// mistyped id in the agent's call. Declared because it is the likeliest failure here and
|
|
33428
|
+
// a reader who assumes it cannot 404 mis-diagnoses the retry loop it causes.
|
|
33429
|
+
404: ErrorResponseSchema,
|
|
32460
33430
|
// runVersion/status guard, stage mismatch, R-not-approved, R-already-promoted,
|
|
32461
33431
|
// or attempt-not-in-run.
|
|
32462
33432
|
409: ErrorResponseSchema,
|
|
@@ -32478,7 +33448,53 @@ var agentSessionInternalContract = c42.router({
|
|
|
32478
33448
|
409: ErrorResponseSchema,
|
|
32479
33449
|
// No MAGIC_AUTH credential on the pentest's environments.
|
|
32480
33450
|
404: ErrorResponseSchema,
|
|
32481
|
-
500: ErrorResponseSchema
|
|
33451
|
+
500: ErrorResponseSchema,
|
|
33452
|
+
// Mail provider unavailable — RETRYABLE, and distinct from 500 so the host
|
|
33453
|
+
// can tell "we could not look" from "this will never work".
|
|
33454
|
+
503: ErrorResponseSchema
|
|
33455
|
+
}
|
|
33456
|
+
},
|
|
33457
|
+
// list_emails: newest-first metadata for the pentest's readable Trace-managed
|
|
33458
|
+
// inbox. Same resolution + ownership gate as login-code (org + pentest
|
|
33459
|
+
// environments + provider-side inbox tenancy); no bodies cross the wire here.
|
|
33460
|
+
listInboxMessages: {
|
|
33461
|
+
method: "POST",
|
|
33462
|
+
path: "/internal/v1/agent-sessions/:agentSessionId/inbox-messages",
|
|
33463
|
+
pathParams: AgentSessionInternalParamsSchema,
|
|
33464
|
+
body: AgentSessionListInboxMessagesRequestSchema,
|
|
33465
|
+
responses: {
|
|
33466
|
+
200: AgentSessionListInboxMessagesResponseSchema,
|
|
33467
|
+
// Ambiguous credentialLabel (several readable inboxes, none named).
|
|
33468
|
+
400: ErrorResponseSchema,
|
|
33469
|
+
401: ErrorResponseSchema,
|
|
33470
|
+
409: ErrorResponseSchema,
|
|
33471
|
+
// No readable Trace-managed inbox on the pentest's environments, or the
|
|
33472
|
+
// resolved address is not owned by this run's organization.
|
|
33473
|
+
404: ErrorResponseSchema,
|
|
33474
|
+
500: ErrorResponseSchema,
|
|
33475
|
+
// Mail provider unavailable — RETRYABLE, and distinct from 500 so the host
|
|
33476
|
+
// can tell "we could not look" from "this will never work".
|
|
33477
|
+
503: ErrorResponseSchema
|
|
33478
|
+
}
|
|
33479
|
+
},
|
|
33480
|
+
// get_email: one message from that inbox, body included. The body is
|
|
33481
|
+
// third-party text — the api neutralizes and length-caps it before it can
|
|
33482
|
+
// reach the agent's context.
|
|
33483
|
+
getInboxMessage: {
|
|
33484
|
+
method: "POST",
|
|
33485
|
+
path: "/internal/v1/agent-sessions/:agentSessionId/inbox-message",
|
|
33486
|
+
pathParams: AgentSessionInternalParamsSchema,
|
|
33487
|
+
body: AgentSessionGetInboxMessageRequestSchema,
|
|
33488
|
+
responses: {
|
|
33489
|
+
200: AgentSessionGetInboxMessageResponseSchema,
|
|
33490
|
+
400: ErrorResponseSchema,
|
|
33491
|
+
401: ErrorResponseSchema,
|
|
33492
|
+
409: ErrorResponseSchema,
|
|
33493
|
+
// Unknown inbox (as above) OR the message id is not in that inbox.
|
|
33494
|
+
404: ErrorResponseSchema,
|
|
33495
|
+
500: ErrorResponseSchema,
|
|
33496
|
+
// Mail provider unavailable — RETRYABLE (see listInboxMessages).
|
|
33497
|
+
503: ErrorResponseSchema
|
|
32482
33498
|
}
|
|
32483
33499
|
},
|
|
32484
33500
|
// get_session_state (SESSION_STATE, spec §2/§3): api-mediated JIT fetch — the api
|
|
@@ -32518,6 +33534,26 @@ var agentSessionInternalContract = c42.router({
|
|
|
32518
33534
|
500: ErrorResponseSchema
|
|
32519
33535
|
}
|
|
32520
33536
|
},
|
|
33537
|
+
// get_convex_deployments (Convex integration PR 3): the read-only broker. Every
|
|
33538
|
+
// connected Convex deployment for the run's OWN org, each with its function
|
|
33539
|
+
// inventory. No request identifier at all — see the schema block above. No 404:
|
|
33540
|
+
// there is no agent-supplied id to miss. No 503: a Convex outage is the
|
|
33541
|
+
// per-deployment `unavailable` status, so one bad deployment never fails the rest.
|
|
33542
|
+
convexRecon: {
|
|
33543
|
+
method: "POST",
|
|
33544
|
+
path: "/internal/v1/agent-sessions/:agentSessionId/convex/recon",
|
|
33545
|
+
pathParams: AgentSessionInternalParamsSchema,
|
|
33546
|
+
body: ConvexReconRequestSchema,
|
|
33547
|
+
responses: {
|
|
33548
|
+
200: ConvexReconResponseSchema,
|
|
33549
|
+
400: ErrorResponseSchema,
|
|
33550
|
+
401: ErrorResponseSchema,
|
|
33551
|
+
// Non-credentialed session type — this run may never reach customer clouds.
|
|
33552
|
+
403: ErrorResponseSchema,
|
|
33553
|
+
409: ErrorResponseSchema,
|
|
33554
|
+
500: ErrorResponseSchema
|
|
33555
|
+
}
|
|
33556
|
+
},
|
|
32521
33557
|
// Operator reads (operator-session PR 1 §2b). All run-token authed; org+pentest
|
|
32522
33558
|
// derived from the session row. Detail ops 404 when the id is not in this pentest.
|
|
32523
33559
|
getPentestContext: {
|
|
@@ -32714,7 +33750,21 @@ var agentSessionInternalContract = c42.router({
|
|
|
32714
33750
|
pathParams: AgentSessionInternalParamsSchema,
|
|
32715
33751
|
body: OperatorRecordFindingRetestRequestSchema,
|
|
32716
33752
|
responses: {
|
|
32717
|
-
200:
|
|
33753
|
+
200: OperatorRetestAckSchema,
|
|
33754
|
+
400: ErrorResponseSchema,
|
|
33755
|
+
401: ErrorResponseSchema,
|
|
33756
|
+
404: ErrorResponseSchema,
|
|
33757
|
+
409: ErrorResponseSchema,
|
|
33758
|
+
500: ErrorResponseSchema
|
|
33759
|
+
}
|
|
33760
|
+
},
|
|
33761
|
+
editFindingRetest: {
|
|
33762
|
+
method: "POST",
|
|
33763
|
+
path: "/internal/v1/agent-sessions/:agentSessionId/operator/findings/retest/edit",
|
|
33764
|
+
pathParams: AgentSessionInternalParamsSchema,
|
|
33765
|
+
body: OperatorEditFindingRetestRequestSchema,
|
|
33766
|
+
responses: {
|
|
33767
|
+
200: OperatorRetestAckSchema,
|
|
32718
33768
|
400: ErrorResponseSchema,
|
|
32719
33769
|
401: ErrorResponseSchema,
|
|
32720
33770
|
404: ErrorResponseSchema,
|
|
@@ -32916,8 +33966,8 @@ var GitHubWebhookResponseSchema = external_exports.object({
|
|
|
32916
33966
|
});
|
|
32917
33967
|
|
|
32918
33968
|
// ../../packages/api-contracts/src/contracts/webhooks/github.ts
|
|
32919
|
-
var
|
|
32920
|
-
var githubWebhookContract =
|
|
33969
|
+
var c44 = initContract();
|
|
33970
|
+
var githubWebhookContract = c44.router(
|
|
32921
33971
|
{
|
|
32922
33972
|
handleWebhook: {
|
|
32923
33973
|
method: "POST",
|
|
@@ -32935,7 +33985,7 @@ var githubWebhookContract = c43.router(
|
|
|
32935
33985
|
pathPrefix: "/webhooks"
|
|
32936
33986
|
}
|
|
32937
33987
|
);
|
|
32938
|
-
var githubReadonlyWebhookContract =
|
|
33988
|
+
var githubReadonlyWebhookContract = c44.router(
|
|
32939
33989
|
{
|
|
32940
33990
|
handleWebhook: {
|
|
32941
33991
|
method: "POST",
|
|
@@ -32955,9 +34005,9 @@ var githubReadonlyWebhookContract = c43.router(
|
|
|
32955
34005
|
);
|
|
32956
34006
|
|
|
32957
34007
|
// ../../packages/api-contracts/src/contracts/webhooks/linear.ts
|
|
32958
|
-
var
|
|
34008
|
+
var c45 = initContract();
|
|
32959
34009
|
var LinearWebhookResponseSchema = external_exports.object({ ok: external_exports.boolean() });
|
|
32960
|
-
var linearWebhookContract =
|
|
34010
|
+
var linearWebhookContract = c45.router(
|
|
32961
34011
|
{
|
|
32962
34012
|
handleWebhook: {
|
|
32963
34013
|
method: "POST",
|
|
@@ -32977,7 +34027,7 @@ var linearWebhookContract = c44.router(
|
|
|
32977
34027
|
);
|
|
32978
34028
|
|
|
32979
34029
|
// ../../packages/api-contracts/src/contracts/forge/bitbucket.ts
|
|
32980
|
-
var
|
|
34030
|
+
var c46 = initContract();
|
|
32981
34031
|
var InstallEventSchema = external_exports.object({
|
|
32982
34032
|
eventType: external_exports.enum(["avi:forge:installed:app", "avi:forge:upgraded:app"]),
|
|
32983
34033
|
context: external_exports.object({ cloudId: external_exports.string().min(1) }).loose(),
|
|
@@ -33006,7 +34056,7 @@ var ForgePairingCodeResponseSchema = external_exports.discriminatedUnion("state"
|
|
|
33006
34056
|
expiresInSeconds: external_exports.number().int()
|
|
33007
34057
|
})
|
|
33008
34058
|
]);
|
|
33009
|
-
var forgeBitbucketContract =
|
|
34059
|
+
var forgeBitbucketContract = c46.router(
|
|
33010
34060
|
{
|
|
33011
34061
|
lifecycle: {
|
|
33012
34062
|
method: "POST",
|
|
@@ -33053,8 +34103,8 @@ var HealthResponseSchema = external_exports.object({
|
|
|
33053
34103
|
});
|
|
33054
34104
|
|
|
33055
34105
|
// ../../packages/api-contracts/src/contracts/health.ts
|
|
33056
|
-
var
|
|
33057
|
-
var healthContract =
|
|
34106
|
+
var c47 = initContract();
|
|
34107
|
+
var healthContract = c47.router({
|
|
33058
34108
|
getHealth: {
|
|
33059
34109
|
method: "GET",
|
|
33060
34110
|
path: "/health",
|
|
@@ -33066,8 +34116,8 @@ var healthContract = c46.router({
|
|
|
33066
34116
|
});
|
|
33067
34117
|
|
|
33068
34118
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability-share.ts
|
|
33069
|
-
var
|
|
33070
|
-
var vulnerabilityShareContract =
|
|
34119
|
+
var c48 = initContract();
|
|
34120
|
+
var vulnerabilityShareContract = c48.router(
|
|
33071
34121
|
{
|
|
33072
34122
|
resolveShareLink: {
|
|
33073
34123
|
method: "GET",
|
|
@@ -33154,8 +34204,8 @@ var UpdatePrVulnerabilityRequestSchema = external_exports.object({
|
|
|
33154
34204
|
});
|
|
33155
34205
|
|
|
33156
34206
|
// ../../packages/api-contracts/src/contracts/v1/pr-vulnerability.ts
|
|
33157
|
-
var
|
|
33158
|
-
var prVulnerabilityContract =
|
|
34207
|
+
var c49 = initContract();
|
|
34208
|
+
var prVulnerabilityContract = c49.router(
|
|
33159
34209
|
{
|
|
33160
34210
|
listPrVulnerabilities: {
|
|
33161
34211
|
method: "GET",
|
|
@@ -35541,6 +36591,7 @@ var APPLICATION_TYPE_BY_INPUT = {
|
|
|
35541
36591
|
web: "WEB",
|
|
35542
36592
|
cli: "CLI",
|
|
35543
36593
|
mobile: "MOBILE",
|
|
36594
|
+
desktop: "DESKTOP",
|
|
35544
36595
|
"api-service": "API_SERVICE",
|
|
35545
36596
|
api_service: "API_SERVICE"
|
|
35546
36597
|
};
|
|
@@ -35707,12 +36758,12 @@ function buildApplicationsTable(apps) {
|
|
|
35707
36758
|
repos: String(a.repositories.length),
|
|
35708
36759
|
url: a.applicationUrl ? sanitizeDisplay(a.applicationUrl) : "\u2014"
|
|
35709
36760
|
}));
|
|
35710
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
35711
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
35712
|
-
const typeWidth = Math.max(4, ...cells.map((
|
|
36761
|
+
const idWidth = Math.max(2, ...cells.map((c51) => c51.id.length));
|
|
36762
|
+
const nameWidth = Math.max(4, ...cells.map((c51) => c51.name.length));
|
|
36763
|
+
const typeWidth = Math.max(4, ...cells.map((c51) => c51.type.length));
|
|
35713
36764
|
const header = `${"ID".padEnd(idWidth)} ${"NAME".padEnd(nameWidth)} ${"TYPE".padEnd(typeWidth)} REPOS URL`;
|
|
35714
36765
|
const rows = cells.map(
|
|
35715
|
-
(
|
|
36766
|
+
(c51) => `${c51.id.padEnd(idWidth)} ${c51.name.padEnd(nameWidth)} ${c51.type.padEnd(typeWidth)} ${c51.repos.padStart(5)} ${c51.url}`
|
|
35716
36767
|
);
|
|
35717
36768
|
return { header, rows };
|
|
35718
36769
|
}
|
|
@@ -35732,12 +36783,12 @@ function buildApplicationRepositoriesTable(links) {
|
|
|
35732
36783
|
path: l.repositoryPath ? sanitizeDisplay(l.repositoryPath) : "\u2014",
|
|
35733
36784
|
status: formatStatus(l.repositoryStatus)
|
|
35734
36785
|
}));
|
|
35735
|
-
const nameWidth = Math.max(10, ...cells.map((
|
|
35736
|
-
const roleWidth = Math.max(4, ...cells.map((
|
|
35737
|
-
const pathWidth = Math.max(4, ...cells.map((
|
|
36786
|
+
const nameWidth = Math.max(10, ...cells.map((c51) => c51.name.length));
|
|
36787
|
+
const roleWidth = Math.max(4, ...cells.map((c51) => c51.role.length));
|
|
36788
|
+
const pathWidth = Math.max(4, ...cells.map((c51) => c51.path.length));
|
|
35738
36789
|
const header = `${"REPOSITORY".padEnd(nameWidth)} SCAN ${"ROLE".padEnd(roleWidth)} ${"PATH".padEnd(pathWidth)} STATUS`;
|
|
35739
36790
|
const rows = cells.map(
|
|
35740
|
-
(
|
|
36791
|
+
(c51) => `${c51.name.padEnd(nameWidth)} ${c51.scan.padEnd(4)} ${c51.role.padEnd(roleWidth)} ${c51.path.padEnd(pathWidth)} ${c51.status}`
|
|
35741
36792
|
);
|
|
35742
36793
|
return { header, rows };
|
|
35743
36794
|
}
|
|
@@ -35999,7 +37050,7 @@ async function runDelete(applicationId, options) {
|
|
|
35999
37050
|
console.log(colorSuccess(`Deleted application ${applicationId}`));
|
|
36000
37051
|
}
|
|
36001
37052
|
function createCreateCommand() {
|
|
36002
|
-
return new Command("create").description("Create a new application").argument("<name>", "Application name").option("--type <type>", "Application type: web, cli, mobile, api-service", "web").option("--url <url>", "Application URL (required for web/api-service)").option("--repo <id-or-url>", "Link a repository at creation (UUID, URL, or owner/repo)").option("--repo-path <path>", "Path within the linked repository").option("--help-center-url <url>", "Help center URL").option("--docs-url <url>", "Documentation URL").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
|
|
37053
|
+
return new Command("create").description("Create a new application").argument("<name>", "Application name").option("--type <type>", "Application type: web, cli, mobile, desktop, api-service", "web").option("--url <url>", "Application URL (required for web/api-service)").option("--repo <id-or-url>", "Link a repository at creation (UUID, URL, or owner/repo)").option("--repo-path <path>", "Path within the linked repository").option("--help-center-url <url>", "Help center URL").option("--docs-url <url>", "Documentation URL").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
|
|
36003
37054
|
"after",
|
|
36004
37055
|
`
|
|
36005
37056
|
Examples:
|
|
@@ -36418,6 +37469,21 @@ function d(r, t, s) {
|
|
|
36418
37469
|
const e2 = r + t, i = Math.max(s.length - 1, 0), n = e2 < 0 ? i : e2 > i ? 0 : e2;
|
|
36419
37470
|
return s[n].disabled ? d(n, t < 0 ? -1 : 1, s) : n;
|
|
36420
37471
|
}
|
|
37472
|
+
function I(r, t, s, e2) {
|
|
37473
|
+
const i = e2.split(`
|
|
37474
|
+
`);
|
|
37475
|
+
let n = 0, o = r;
|
|
37476
|
+
for (const a of i) {
|
|
37477
|
+
if (o <= a.length) break;
|
|
37478
|
+
o -= a.length + 1, n++;
|
|
37479
|
+
}
|
|
37480
|
+
for (n = Math.max(0, Math.min(i.length - 1, n + s)), o = Math.min(o, i[n].length) + t; o < 0 && n > 0; ) n--, o += i[n].length + 1;
|
|
37481
|
+
for (; o > i[n].length && n < i.length - 1; ) o -= i[n].length + 1, n++;
|
|
37482
|
+
o = Math.max(0, Math.min(i[n].length, o));
|
|
37483
|
+
let u = 0;
|
|
37484
|
+
for (let a = 0; a < n; a++) u += i[a].length + 1;
|
|
37485
|
+
return u + o;
|
|
37486
|
+
}
|
|
36421
37487
|
var G = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
36422
37488
|
var K = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
36423
37489
|
var h = { actions: new Set(G), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true, date: { monthNames: [...K], messages: { required: "Please enter a valid date", invalidMonth: "There are only 12 months in a year", invalidDay: (r, t) => `There are only ${r} days in ${t}`, afterMin: (r) => `Date must be on or after ${r.toISOString().slice(0, 10)}`, beforeMax: (r) => `Date must be on or before ${r.toISOString().slice(0, 10)}` } } };
|
|
@@ -36579,6 +37645,145 @@ var p = class {
|
|
|
36579
37645
|
}
|
|
36580
37646
|
}
|
|
36581
37647
|
};
|
|
37648
|
+
var X = class extends p {
|
|
37649
|
+
get cursor() {
|
|
37650
|
+
return this.value ? 0 : 1;
|
|
37651
|
+
}
|
|
37652
|
+
get _value() {
|
|
37653
|
+
return this.cursor === 0;
|
|
37654
|
+
}
|
|
37655
|
+
constructor(t) {
|
|
37656
|
+
super(t, false), this.value = !!t.initialValue, this.on("userInput", () => {
|
|
37657
|
+
this.value = this._value;
|
|
37658
|
+
}), this.on("confirm", (s) => {
|
|
37659
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = s, this.state = "submit", this.close();
|
|
37660
|
+
}), this.on("cursor", () => {
|
|
37661
|
+
this.value = !this.value;
|
|
37662
|
+
});
|
|
37663
|
+
}
|
|
37664
|
+
};
|
|
37665
|
+
var rt = class extends p {
|
|
37666
|
+
#s = false;
|
|
37667
|
+
#r;
|
|
37668
|
+
focused = "editor";
|
|
37669
|
+
get userInputWithCursor() {
|
|
37670
|
+
if (this.state === "submit") return this.userInput;
|
|
37671
|
+
const t = this.userInput;
|
|
37672
|
+
if (this.cursor >= t.length) return `${t}\u2588`;
|
|
37673
|
+
const s = t.slice(0, this.cursor), e2 = t[this.cursor], i = t.slice(this.cursor + 1);
|
|
37674
|
+
return e2 === `
|
|
37675
|
+
` ? `${s}\u2588
|
|
37676
|
+
${i}` : `${s}${v("inverse", e2)}${i}`;
|
|
37677
|
+
}
|
|
37678
|
+
get cursor() {
|
|
37679
|
+
return this._cursor;
|
|
37680
|
+
}
|
|
37681
|
+
#t(t) {
|
|
37682
|
+
if (this.userInput.length === 0) {
|
|
37683
|
+
this._setUserInput(t);
|
|
37684
|
+
return;
|
|
37685
|
+
}
|
|
37686
|
+
this._setUserInput(this.userInput.slice(0, this.cursor) + t + this.userInput.slice(this.cursor));
|
|
37687
|
+
}
|
|
37688
|
+
#n(t) {
|
|
37689
|
+
const s = this.value ?? "";
|
|
37690
|
+
switch (t) {
|
|
37691
|
+
case "up":
|
|
37692
|
+
this._cursor = I(this._cursor, 0, -1, s);
|
|
37693
|
+
return;
|
|
37694
|
+
case "down":
|
|
37695
|
+
this._cursor = I(this._cursor, 0, 1, s);
|
|
37696
|
+
return;
|
|
37697
|
+
case "left":
|
|
37698
|
+
this._cursor = I(this._cursor, -1, 0, s);
|
|
37699
|
+
return;
|
|
37700
|
+
case "right":
|
|
37701
|
+
this._cursor = I(this._cursor, 1, 0, s);
|
|
37702
|
+
return;
|
|
37703
|
+
}
|
|
37704
|
+
}
|
|
37705
|
+
_shouldSubmit(t, s) {
|
|
37706
|
+
if (this.#r) return this.focused === "submit" ? true : (this.#t(`
|
|
37707
|
+
`), this._cursor++, false);
|
|
37708
|
+
const e2 = this.#s;
|
|
37709
|
+
return this.#s = true, e2 ? (this.userInput[this.cursor - 1] === `
|
|
37710
|
+
` && (this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--), true) : (this.#t(`
|
|
37711
|
+
`), this._cursor++, false);
|
|
37712
|
+
}
|
|
37713
|
+
constructor(t) {
|
|
37714
|
+
super(t, false), this.#r = t.showSubmit ?? false, this.on("key", (s, e2) => {
|
|
37715
|
+
if (e2?.name && h.actions.has(e2.name)) {
|
|
37716
|
+
this.#n(e2.name);
|
|
37717
|
+
return;
|
|
37718
|
+
}
|
|
37719
|
+
if (s === " " && this.#r) {
|
|
37720
|
+
this.focused = this.focused === "editor" ? "submit" : "editor";
|
|
37721
|
+
return;
|
|
37722
|
+
}
|
|
37723
|
+
if (e2?.name !== "return") {
|
|
37724
|
+
if (this.#s = false, e2?.name === "backspace" && this.cursor > 0) {
|
|
37725
|
+
this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--;
|
|
37726
|
+
return;
|
|
37727
|
+
}
|
|
37728
|
+
if (e2?.name === "delete" && this.cursor < this.userInput.length) {
|
|
37729
|
+
this._setUserInput(this.userInput.slice(0, this.cursor) + this.userInput.slice(this.cursor + 1));
|
|
37730
|
+
return;
|
|
37731
|
+
}
|
|
37732
|
+
s && (this.#r && this.focused === "submit" && (this.focused = "editor"), this.#t(s ?? ""), this._cursor++);
|
|
37733
|
+
}
|
|
37734
|
+
}), this.on("userInput", (s) => {
|
|
37735
|
+
this._setValue(s);
|
|
37736
|
+
}), this.on("finalize", () => {
|
|
37737
|
+
this.value || (this.value = t.defaultValue), this.value === void 0 && (this.value = "");
|
|
37738
|
+
});
|
|
37739
|
+
}
|
|
37740
|
+
};
|
|
37741
|
+
var nt = class extends p {
|
|
37742
|
+
options;
|
|
37743
|
+
cursor = 0;
|
|
37744
|
+
get _value() {
|
|
37745
|
+
return this.options[this.cursor].value;
|
|
37746
|
+
}
|
|
37747
|
+
get _enabledOptions() {
|
|
37748
|
+
return this.options.filter((t) => t.disabled !== true);
|
|
37749
|
+
}
|
|
37750
|
+
toggleAll() {
|
|
37751
|
+
const t = this._enabledOptions, s = this.value !== void 0 && this.value.length === t.length;
|
|
37752
|
+
this.value = s ? [] : t.map((e2) => e2.value);
|
|
37753
|
+
}
|
|
37754
|
+
toggleInvert() {
|
|
37755
|
+
const t = this.value;
|
|
37756
|
+
if (!t) return;
|
|
37757
|
+
const s = this._enabledOptions.filter((e2) => !t.includes(e2.value));
|
|
37758
|
+
this.value = s.map((e2) => e2.value);
|
|
37759
|
+
}
|
|
37760
|
+
toggleValue() {
|
|
37761
|
+
this.value === void 0 && (this.value = []);
|
|
37762
|
+
const t = this.value.includes(this._value);
|
|
37763
|
+
this.value = t ? this.value.filter((s) => s !== this._value) : [...this.value, this._value];
|
|
37764
|
+
}
|
|
37765
|
+
constructor(t) {
|
|
37766
|
+
super(t, false), this.options = t.options, this.value = [...t.initialValues ?? []];
|
|
37767
|
+
const s = Math.max(this.options.findIndex(({ value: e2 }) => e2 === t.cursorAt), 0);
|
|
37768
|
+
this.cursor = this.options[s].disabled ? d(s, 1, this.options) : s, this.on("key", (e2) => {
|
|
37769
|
+
e2 === "a" && this.toggleAll(), e2 === "i" && this.toggleInvert();
|
|
37770
|
+
}), this.on("cursor", (e2) => {
|
|
37771
|
+
switch (e2) {
|
|
37772
|
+
case "left":
|
|
37773
|
+
case "up":
|
|
37774
|
+
this.cursor = d(this.cursor, -1, this.options);
|
|
37775
|
+
break;
|
|
37776
|
+
case "down":
|
|
37777
|
+
case "right":
|
|
37778
|
+
this.cursor = d(this.cursor, 1, this.options);
|
|
37779
|
+
break;
|
|
37780
|
+
case "space":
|
|
37781
|
+
this.toggleValue();
|
|
37782
|
+
break;
|
|
37783
|
+
}
|
|
37784
|
+
});
|
|
37785
|
+
}
|
|
37786
|
+
};
|
|
36582
37787
|
var ot = class extends p {
|
|
36583
37788
|
_mask = "\u2022";
|
|
36584
37789
|
get cursor() {
|
|
@@ -36695,14 +37900,14 @@ var yt = (t) => {
|
|
|
36695
37900
|
};
|
|
36696
37901
|
var ee = (t, r, s, i, u) => {
|
|
36697
37902
|
let n = r, o = 0;
|
|
36698
|
-
for (let
|
|
36699
|
-
const a = t[
|
|
37903
|
+
for (let c51 = s; c51 < i; c51++) {
|
|
37904
|
+
const a = t[c51];
|
|
36700
37905
|
if (n = n - a.length, o++, n <= u) break;
|
|
36701
37906
|
}
|
|
36702
37907
|
return { lineCount: n, removals: o };
|
|
36703
37908
|
};
|
|
36704
37909
|
var Y2 = ({ cursor: t, options: r, style: s, output: i = process.stdout, maxItems: u = Number.POSITIVE_INFINITY, columnPadding: n = 0, rowPadding: o = 4 }) => {
|
|
36705
|
-
const
|
|
37910
|
+
const c51 = A(i) - n, a = L(i), l = e("dim", "..."), d2 = Math.max(a - o, 0), y = Math.max(Math.min(u, d2), 5);
|
|
36706
37911
|
let p2 = 0;
|
|
36707
37912
|
t >= y - 3 && (p2 = Math.max(Math.min(t - y + 3, r.length - y), 0));
|
|
36708
37913
|
let m = y < r.length && p2 > 0, g = y < r.length && p2 + y < r.length;
|
|
@@ -36711,7 +37916,7 @@ var Y2 = ({ cursor: t, options: r, style: s, output: i = process.stdout, maxItem
|
|
|
36711
37916
|
m && f++, g && f++;
|
|
36712
37917
|
const v2 = p2 + (m ? 1 : 0), T = S2 - (g ? 1 : 0);
|
|
36713
37918
|
for (let b2 = v2; b2 < T; b2++) {
|
|
36714
|
-
const G2 = wrapAnsi(s(r[b2], b2 === t),
|
|
37919
|
+
const G2 = wrapAnsi(s(r[b2], b2 === t), c51, { hard: true, trim: false }).split(`
|
|
36715
37920
|
`);
|
|
36716
37921
|
h2.push(G2), f += G2.length;
|
|
36717
37922
|
}
|
|
@@ -36725,15 +37930,129 @@ var Y2 = ({ cursor: t, options: r, style: s, output: i = process.stdout, maxItem
|
|
|
36725
37930
|
for (const b2 of h2) for (const G2 of b2) C2.push(G2);
|
|
36726
37931
|
return g && C2.push(l), C2;
|
|
36727
37932
|
};
|
|
37933
|
+
var ue = (t) => {
|
|
37934
|
+
const r = t.active ?? "Yes", s = t.inactive ?? "No";
|
|
37935
|
+
return new X({ active: r, inactive: s, signal: t.signal, input: t.input, output: t.output, initialValue: t.initialValue ?? true, render() {
|
|
37936
|
+
const i = t.withGuide ?? h.withGuide, u = `${M(this.state)} `, n = i ? `${e("gray", $)} ` : "", o = W(t.output, t.message, n, u), c51 = `${i ? `${e("gray", $)}
|
|
37937
|
+
` : ""}${o}
|
|
37938
|
+
`, a = this.value ? r : s;
|
|
37939
|
+
switch (this.state) {
|
|
37940
|
+
case "submit": {
|
|
37941
|
+
const l = i ? `${e("gray", $)} ` : "";
|
|
37942
|
+
return `${c51}${l}${e("dim", a)}`;
|
|
37943
|
+
}
|
|
37944
|
+
case "cancel": {
|
|
37945
|
+
const l = i ? `${e("gray", $)} ` : "";
|
|
37946
|
+
return `${c51}${l}${e(["strikethrough", "dim"], a)}${i ? `
|
|
37947
|
+
${e("gray", $)}` : ""}`;
|
|
37948
|
+
}
|
|
37949
|
+
default: {
|
|
37950
|
+
const l = i ? `${e("cyan", $)} ` : "", d2 = i ? e("cyan", E2) : "";
|
|
37951
|
+
return `${c51}${l}${this.value ? `${e("green", z4)} ${r}` : `${e("dim", H)} ${e("dim", r)}`}${t.vertical ? i ? `
|
|
37952
|
+
${e("cyan", $)} ` : `
|
|
37953
|
+
` : ` ${e("dim", "/")} `}${this.value ? `${e("dim", H)} ${e("dim", s)}` : `${e("green", z4)} ${s}`}
|
|
37954
|
+
${d2}
|
|
37955
|
+
`;
|
|
37956
|
+
}
|
|
37957
|
+
}
|
|
37958
|
+
} }).prompt();
|
|
37959
|
+
};
|
|
37960
|
+
var me = (t = "", r) => {
|
|
37961
|
+
const s = r?.output ?? process.stdout, i = r?.withGuide ?? h.withGuide ? `${e("gray", E2)} ` : "";
|
|
37962
|
+
s.write(`${i}${e("red", t)}
|
|
37963
|
+
|
|
37964
|
+
`);
|
|
37965
|
+
};
|
|
37966
|
+
var fe = (t) => new rt({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, showSubmit: t.showSubmit, output: t.output, signal: t.signal, input: t.input, render() {
|
|
37967
|
+
const r = t?.withGuide ?? h.withGuide, s = `${`${r ? `${e("gray", $)}
|
|
37968
|
+
` : ""}${M(this.state)} `}${t.message}
|
|
37969
|
+
`, i = t.placeholder ? e("inverse", t.placeholder[0]) + e("dim", t.placeholder.slice(1)) : e(["inverse", "hidden"], "_"), u = this.userInput ? this.userInputWithCursor : i, n = this.value ?? "", o = t.showSubmit ? `
|
|
37970
|
+
${e(this.focused === "submit" ? "cyan" : "dim", "[ submit ]")}` : "";
|
|
37971
|
+
switch (this.state) {
|
|
37972
|
+
case "error": {
|
|
37973
|
+
const c51 = `${e("yellow", $)} `, a = r ? W(t.output, u, c51, void 0) : u, l = e("yellow", E2);
|
|
37974
|
+
return `${s}${a}
|
|
37975
|
+
${l} ${e("yellow", this.error)}${o}
|
|
37976
|
+
`;
|
|
37977
|
+
}
|
|
37978
|
+
case "submit": {
|
|
37979
|
+
const c51 = `${e("gray", $)} `, a = r ? W(t.output, n, c51, void 0, (l) => e("dim", l)) : n ? e("dim", n) : "";
|
|
37980
|
+
return `${s}${a}`;
|
|
37981
|
+
}
|
|
37982
|
+
case "cancel": {
|
|
37983
|
+
const c51 = `${e("gray", $)} `, a = r ? W(t.output, n, c51, void 0, (l) => e(["strikethrough", "dim"], l)) : n ? e(["strikethrough", "dim"], n) : "";
|
|
37984
|
+
return `${s}${a}`;
|
|
37985
|
+
}
|
|
37986
|
+
default: {
|
|
37987
|
+
const c51 = r ? `${e("cyan", $)} ` : "", a = r ? e("cyan", E2) : "", l = r ? W(t.output, u, c51) : u;
|
|
37988
|
+
return `${s}${l}
|
|
37989
|
+
${a}${o}
|
|
37990
|
+
`;
|
|
37991
|
+
}
|
|
37992
|
+
}
|
|
37993
|
+
} }).prompt();
|
|
37994
|
+
var Q2 = (t, r) => t.split(`
|
|
37995
|
+
`).map((s) => r(s)).join(`
|
|
37996
|
+
`);
|
|
37997
|
+
var ve = (t) => {
|
|
37998
|
+
const r = (i, u) => {
|
|
37999
|
+
const n = i.label ?? String(i.value);
|
|
38000
|
+
return u === "disabled" ? `${e("gray", J)} ${Q2(n, (o) => e(["strikethrough", "gray"], o))}${i.hint ? ` ${e("dim", `(${i.hint ?? "disabled"})`)}` : ""}` : u === "active" ? `${e("cyan", et2)} ${n}${i.hint ? ` ${e("dim", `(${i.hint})`)}` : ""}` : u === "selected" ? `${e("green", U)} ${Q2(n, (o) => e("dim", o))}${i.hint ? ` ${e("dim", `(${i.hint})`)}` : ""}` : u === "cancelled" ? `${Q2(n, (o) => e(["strikethrough", "dim"], o))}` : u === "active-selected" ? `${e("green", U)} ${n}${i.hint ? ` ${e("dim", `(${i.hint})`)}` : ""}` : u === "submitted" ? `${Q2(n, (o) => e("dim", o))}` : `${e("dim", J)} ${Q2(n, (o) => e("dim", o))}`;
|
|
38001
|
+
}, s = t.required ?? true;
|
|
38002
|
+
return new nt({ options: t.options, signal: t.signal, input: t.input, output: t.output, initialValues: t.initialValues, required: s, cursorAt: t.cursorAt, validate(i) {
|
|
38003
|
+
if (s && (i === void 0 || i.length === 0)) return `Please select at least one option.
|
|
38004
|
+
${e("reset", e("dim", `Press ${e(["gray", "bgWhite", "inverse"], " space ")} to select, ${e("gray", e("bgWhite", e("inverse", " enter ")))} to submit`))}`;
|
|
38005
|
+
}, render() {
|
|
38006
|
+
const i = t.withGuide ?? h.withGuide, u = W(t.output, t.message, i ? `${yt(this.state)} ` : "", `${M(this.state)} `), n = `${i ? `${e("gray", $)}
|
|
38007
|
+
` : ""}${u}
|
|
38008
|
+
`, o = this.value ?? [], c51 = (a, l) => {
|
|
38009
|
+
if (a.disabled) return r(a, "disabled");
|
|
38010
|
+
const d2 = o.includes(a.value);
|
|
38011
|
+
return l && d2 ? r(a, "active-selected") : d2 ? r(a, "selected") : r(a, l ? "active" : "inactive");
|
|
38012
|
+
};
|
|
38013
|
+
switch (this.state) {
|
|
38014
|
+
case "submit": {
|
|
38015
|
+
const a = this.options.filter(({ value: d2 }) => o.includes(d2)).map((d2) => r(d2, "submitted")).join(e("dim", ", ")) || e("dim", "none"), l = W(t.output, a, i ? `${e("gray", $)} ` : "");
|
|
38016
|
+
return `${n}${l}`;
|
|
38017
|
+
}
|
|
38018
|
+
case "cancel": {
|
|
38019
|
+
const a = this.options.filter(({ value: d2 }) => o.includes(d2)).map((d2) => r(d2, "cancelled")).join(e("dim", ", "));
|
|
38020
|
+
if (a.trim() === "") return `${n}${e("gray", $)}`;
|
|
38021
|
+
const l = W(t.output, a, i ? `${e("gray", $)} ` : "");
|
|
38022
|
+
return `${n}${l}${i ? `
|
|
38023
|
+
${e("gray", $)}` : ""}`;
|
|
38024
|
+
}
|
|
38025
|
+
case "error": {
|
|
38026
|
+
const a = i ? `${e("yellow", $)} ` : "", l = this.error.split(`
|
|
38027
|
+
`).map((p2, m) => m === 0 ? `${i ? `${e("yellow", E2)} ` : ""}${e("yellow", p2)}` : ` ${p2}`).join(`
|
|
38028
|
+
`), d2 = n.split(`
|
|
38029
|
+
`).length, y = l.split(`
|
|
38030
|
+
`).length + 1;
|
|
38031
|
+
return `${n}${a}${Y2({ output: t.output, options: this.options, cursor: this.cursor, maxItems: t.maxItems, columnPadding: a.length, rowPadding: d2 + y, style: c51 }).join(`
|
|
38032
|
+
${a}`)}
|
|
38033
|
+
${l}
|
|
38034
|
+
`;
|
|
38035
|
+
}
|
|
38036
|
+
default: {
|
|
38037
|
+
const a = i ? `${e("cyan", $)} ` : "", l = n.split(`
|
|
38038
|
+
`).length, d2 = i ? 2 : 1;
|
|
38039
|
+
return `${n}${a}${Y2({ output: t.output, options: this.options, cursor: this.cursor, maxItems: t.maxItems, columnPadding: a.length, rowPadding: l + d2, style: c51 }).join(`
|
|
38040
|
+
${a}`)}
|
|
38041
|
+
${i ? e("cyan", E2) : ""}
|
|
38042
|
+
`;
|
|
38043
|
+
}
|
|
38044
|
+
}
|
|
38045
|
+
} }).prompt();
|
|
38046
|
+
};
|
|
36728
38047
|
var Ce = (t) => new ot({ validate: t.validate, mask: t.mask ?? Gt, signal: t.signal, input: t.input, output: t.output, render() {
|
|
36729
38048
|
const r = t.withGuide ?? h.withGuide, s = `${r ? `${e("gray", $)}
|
|
36730
38049
|
` : ""}${M(this.state)} ${t.message}
|
|
36731
38050
|
`, i = this.userInputWithCursor, u = this.masked;
|
|
36732
38051
|
switch (this.state) {
|
|
36733
38052
|
case "error": {
|
|
36734
|
-
const n = r ? `${e("yellow", $)} ` : "", o = r ? `${e("yellow", E2)} ` : "",
|
|
38053
|
+
const n = r ? `${e("yellow", $)} ` : "", o = r ? `${e("yellow", E2)} ` : "", c51 = u ?? "";
|
|
36735
38054
|
return t.clearOnError && this.clear(), `${s.trim()}
|
|
36736
|
-
${n}${
|
|
38055
|
+
${n}${c51}
|
|
36737
38056
|
${o}${e("yellow", this.error)}
|
|
36738
38057
|
`;
|
|
36739
38058
|
}
|
|
@@ -36781,19 +38100,19 @@ var Ee = (t) => {
|
|
|
36781
38100
|
`;
|
|
36782
38101
|
switch (this.state) {
|
|
36783
38102
|
case "submit": {
|
|
36784
|
-
const
|
|
38103
|
+
const c51 = s ? `${e("gray", $)} ` : "", a = W(t.output, r(this.options[this.cursor], "selected"), c51);
|
|
36785
38104
|
return `${o}${a}`;
|
|
36786
38105
|
}
|
|
36787
38106
|
case "cancel": {
|
|
36788
|
-
const
|
|
38107
|
+
const c51 = s ? `${e("gray", $)} ` : "", a = W(t.output, r(this.options[this.cursor], "cancelled"), c51);
|
|
36789
38108
|
return `${o}${a}${s ? `
|
|
36790
38109
|
${e("gray", $)}` : ""}`;
|
|
36791
38110
|
}
|
|
36792
38111
|
default: {
|
|
36793
|
-
const
|
|
38112
|
+
const c51 = s ? `${e("cyan", $)} ` : "", a = s ? e("cyan", E2) : "", l = o.split(`
|
|
36794
38113
|
`).length, d2 = s ? 2 : 1;
|
|
36795
|
-
return `${o}${
|
|
36796
|
-
${
|
|
38114
|
+
return `${o}${c51}${Y2({ output: t.output, cursor: this.cursor, options: this.options, maxItems: t.maxItems, columnPadding: c51.length, rowPadding: l + d2, style: (y, p2) => r(y, y.disabled ? "disabled" : p2 ? "active" : "inactive") }).join(`
|
|
38115
|
+
${c51}`)}
|
|
36797
38116
|
${a}
|
|
36798
38117
|
`;
|
|
36799
38118
|
}
|
|
@@ -37551,7 +38870,7 @@ function extractCommandTree(cmd) {
|
|
|
37551
38870
|
description: o.description,
|
|
37552
38871
|
takesValue: o.required || o.optional
|
|
37553
38872
|
}));
|
|
37554
|
-
const subcommands = cmd.commands.filter((
|
|
38873
|
+
const subcommands = cmd.commands.filter((c51) => !c51._hidden).map((c51) => extractCommandTree(c51));
|
|
37555
38874
|
return {
|
|
37556
38875
|
name: cmd.name(),
|
|
37557
38876
|
description: cmd.description(),
|
|
@@ -37617,7 +38936,7 @@ function generateBashCompletion(tree, binName) {
|
|
|
37617
38936
|
}
|
|
37618
38937
|
function collectBashCases(tree, prefix) {
|
|
37619
38938
|
const cases = /* @__PURE__ */ new Map();
|
|
37620
|
-
const subcommandNames = tree.subcommands.map((
|
|
38939
|
+
const subcommandNames = tree.subcommands.map((c51) => c51.name);
|
|
37621
38940
|
const optionNames = tree.options.flatMap((o) => o.short ? [o.long, o.short] : [o.long]);
|
|
37622
38941
|
const extraOptions = prefix === "" ? ["--help", "--version"] : ["--help"];
|
|
37623
38942
|
const allOptions = [.../* @__PURE__ */ new Set([...optionNames, ...extraOptions])];
|
|
@@ -38300,16 +39619,16 @@ function printCredentialsTsv(creds) {
|
|
|
38300
39619
|
}
|
|
38301
39620
|
}
|
|
38302
39621
|
function buildCredentialsTable(creds) {
|
|
38303
|
-
const cells = creds.map((
|
|
38304
|
-
id:
|
|
38305
|
-
label: sanitizeDisplay(
|
|
38306
|
-
type:
|
|
39622
|
+
const cells = creds.map((c51) => ({
|
|
39623
|
+
id: c51.credentialId,
|
|
39624
|
+
label: sanitizeDisplay(c51.label),
|
|
39625
|
+
type: c51.credentialType
|
|
38307
39626
|
}));
|
|
38308
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
38309
|
-
const labelWidth = Math.max(5, ...cells.map((
|
|
39627
|
+
const idWidth = Math.max(2, ...cells.map((c51) => c51.id.length));
|
|
39628
|
+
const labelWidth = Math.max(5, ...cells.map((c51) => c51.label.length));
|
|
38310
39629
|
const header = `${"ID".padEnd(idWidth)} ${"LABEL".padEnd(labelWidth)} TYPE`;
|
|
38311
39630
|
const rows = cells.map(
|
|
38312
|
-
(
|
|
39631
|
+
(c51) => `${c51.id.padEnd(idWidth)} ${c51.label.padEnd(labelWidth)} ${c51.type}`
|
|
38313
39632
|
);
|
|
38314
39633
|
return { header, rows };
|
|
38315
39634
|
}
|
|
@@ -38365,7 +39684,7 @@ async function runCreate2(options) {
|
|
|
38365
39684
|
}
|
|
38366
39685
|
const organizationId = await resolveOrganizationId();
|
|
38367
39686
|
const params = { organizationId, environmentId: options.env };
|
|
38368
|
-
const label = options.label;
|
|
39687
|
+
const label = options.label?.trim() ? options.label.trim() : void 0;
|
|
38369
39688
|
let body;
|
|
38370
39689
|
try {
|
|
38371
39690
|
body = await buildCreateBody(type, label, options);
|
|
@@ -38388,6 +39707,7 @@ async function runCreate2(options) {
|
|
|
38388
39707
|
outputCredential(result.body, output);
|
|
38389
39708
|
}
|
|
38390
39709
|
async function buildCreateBody(type, label, options) {
|
|
39710
|
+
const labelFields = label !== void 0 ? { label } : {};
|
|
38391
39711
|
switch (type) {
|
|
38392
39712
|
case "BEARER_TOKEN": {
|
|
38393
39713
|
const ac = buildBearerAuthConfig(options);
|
|
@@ -38395,7 +39715,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
38395
39715
|
const secretValue = await resolveSecret("secret value", "secret", secretOpts(options));
|
|
38396
39716
|
return {
|
|
38397
39717
|
credentialType: "BEARER_TOKEN",
|
|
38398
|
-
|
|
39718
|
+
...labelFields,
|
|
38399
39719
|
secretValue,
|
|
38400
39720
|
...ac.value ? { authConfig: ac.value } : {}
|
|
38401
39721
|
};
|
|
@@ -38406,7 +39726,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
38406
39726
|
const secretValue = await resolveSecret("secret value", "secret", secretOpts(options));
|
|
38407
39727
|
return {
|
|
38408
39728
|
credentialType: "JWT_TOKEN",
|
|
38409
|
-
|
|
39729
|
+
...labelFields,
|
|
38410
39730
|
secretValue,
|
|
38411
39731
|
...ac.value ? { authConfig: ac.value } : {}
|
|
38412
39732
|
};
|
|
@@ -38417,14 +39737,14 @@ async function buildCreateBody(type, label, options) {
|
|
|
38417
39737
|
const secretValue = await resolveSecret("secret value", "secret", secretOpts(options));
|
|
38418
39738
|
return {
|
|
38419
39739
|
credentialType: "API_KEY",
|
|
38420
|
-
|
|
39740
|
+
...labelFields,
|
|
38421
39741
|
secretValue,
|
|
38422
39742
|
...ac.value ? { authConfig: ac.value } : {}
|
|
38423
39743
|
};
|
|
38424
39744
|
}
|
|
38425
39745
|
case "PASSPHRASE": {
|
|
38426
39746
|
const secretValue = await resolveSecret("secret value", "secret", secretOpts(options));
|
|
38427
|
-
return { credentialType: "PASSPHRASE",
|
|
39747
|
+
return { credentialType: "PASSPHRASE", ...labelFields, secretValue };
|
|
38428
39748
|
}
|
|
38429
39749
|
case "SESSION_STATE": {
|
|
38430
39750
|
const secretValue = await resolveSecret(
|
|
@@ -38432,7 +39752,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
38432
39752
|
"secret",
|
|
38433
39753
|
secretOpts(options)
|
|
38434
39754
|
);
|
|
38435
|
-
return { credentialType: "SESSION_STATE",
|
|
39755
|
+
return { credentialType: "SESSION_STATE", ...labelFields, secretValue };
|
|
38436
39756
|
}
|
|
38437
39757
|
case "COOKIE": {
|
|
38438
39758
|
const ac = buildCookieAuthConfig(options);
|
|
@@ -38440,7 +39760,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
38440
39760
|
const secretValue = await resolveSecret("secret value", "secret", secretOpts(options));
|
|
38441
39761
|
return {
|
|
38442
39762
|
credentialType: "COOKIE",
|
|
38443
|
-
|
|
39763
|
+
...labelFields,
|
|
38444
39764
|
secretValue,
|
|
38445
39765
|
...ac.value ? { authConfig: ac.value } : {}
|
|
38446
39766
|
};
|
|
@@ -38451,7 +39771,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
38451
39771
|
const secretValue = await resolveSecret("test-account email", "secret", secretOpts(options));
|
|
38452
39772
|
return {
|
|
38453
39773
|
credentialType: "MAGIC_AUTH",
|
|
38454
|
-
|
|
39774
|
+
...labelFields,
|
|
38455
39775
|
secretValue,
|
|
38456
39776
|
...ac.value ? { authConfig: ac.value } : {}
|
|
38457
39777
|
};
|
|
@@ -38463,7 +39783,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
38463
39783
|
const password = await resolveSecret("password", "password", passwordOpts(options));
|
|
38464
39784
|
return {
|
|
38465
39785
|
credentialType: "USERNAME_PASSWORD",
|
|
38466
|
-
|
|
39786
|
+
...labelFields,
|
|
38467
39787
|
username,
|
|
38468
39788
|
password,
|
|
38469
39789
|
...ac.value ? { authConfig: ac.value } : {}
|
|
@@ -38616,17 +39936,21 @@ function createCreateCommand2() {
|
|
|
38616
39936
|
const command = new Command("create").description("Create a credential in an environment").requiredOption("--env <environmentId>", "Parent environment UUID").requiredOption(
|
|
38617
39937
|
"--type <type>",
|
|
38618
39938
|
"bearer-token, jwt-token, api-key, passphrase, username-password, cookie, magic-auth"
|
|
38619
|
-
).
|
|
39939
|
+
).option(
|
|
39940
|
+
"--label <label>",
|
|
39941
|
+
"Human-readable label (optional; defaults from type / username + environment)"
|
|
39942
|
+
).option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table");
|
|
38620
39943
|
addSecretInputOptions(command);
|
|
38621
39944
|
addAuthConfigOptions(command).addHelpText(
|
|
38622
39945
|
"after",
|
|
38623
39946
|
`
|
|
38624
39947
|
Secrets are read from stdin/file/env (or a no-echo prompt) \u2014 never an inline flag.
|
|
39948
|
+
--label is optional; when omitted the API picks a unique default.
|
|
38625
39949
|
|
|
38626
39950
|
Examples:
|
|
38627
|
-
vault read -field=token secret/x | tracecli credential create --env <envId> --type bearer-token --
|
|
39951
|
+
vault read -field=token secret/x | tracecli credential create --env <envId> --type bearer-token --secret-stdin
|
|
38628
39952
|
tracecli credential create --env <envId> --type api-key --label "prod key" --secret-env API_KEY --placement header --key-name X-API-Key
|
|
38629
|
-
tracecli credential create --env <envId> --type username-password --
|
|
39953
|
+
tracecli credential create --env <envId> --type username-password --username-env U --password-env P --method form --login-url https://acme.com/login`
|
|
38630
39954
|
);
|
|
38631
39955
|
return command.action(async (options) => {
|
|
38632
39956
|
await runCreate2(options);
|
|
@@ -38793,7 +40117,7 @@ function renderEnvironmentDetail(env2) {
|
|
|
38793
40117
|
return [
|
|
38794
40118
|
`${"ID:".padEnd(pad)} ${env2.environmentId}`,
|
|
38795
40119
|
`${"Name:".padEnd(pad)} ${sanitizeDisplay(env2.name)}`,
|
|
38796
|
-
`${"URL:".padEnd(pad)} ${sanitizeDisplay(env2.primaryUrl)}`,
|
|
40120
|
+
`${"URL:".padEnd(pad)} ${env2.primaryUrl != null ? sanitizeDisplay(env2.primaryUrl) : "\u2014"}`,
|
|
38797
40121
|
`${"Production:".padEnd(pad)} ${env2.isProduction ? "yes" : "no"}`,
|
|
38798
40122
|
`${"Description:".padEnd(pad)} ${env2.description ? sanitizeDisplay(env2.description) : "\u2014"}`,
|
|
38799
40123
|
`${"Application:".padEnd(pad)} ${env2.applicationId}`,
|
|
@@ -38809,7 +40133,7 @@ function printEnvironmentsTsv(envs) {
|
|
|
38809
40133
|
[
|
|
38810
40134
|
tsvSafe(env2.environmentId),
|
|
38811
40135
|
tsvSafe(sanitizeDisplay(env2.name)),
|
|
38812
|
-
tsvSafe(sanitizeDisplay(env2.primaryUrl)),
|
|
40136
|
+
tsvSafe(sanitizeDisplay(env2.primaryUrl ?? "")),
|
|
38813
40137
|
String(env2.isProduction),
|
|
38814
40138
|
tsvSafe(sanitizeDisplay(env2.description ?? "")),
|
|
38815
40139
|
tsvSafe(toIso(env2.createdAt))
|
|
@@ -38841,7 +40165,7 @@ function printOrgEnvironmentsTsv(envs) {
|
|
|
38841
40165
|
tsvSafe(env2.applicationId),
|
|
38842
40166
|
tsvSafe(sanitizeDisplay(env2.applicationName)),
|
|
38843
40167
|
tsvSafe(sanitizeDisplay(env2.name)),
|
|
38844
|
-
tsvSafe(sanitizeDisplay(env2.primaryUrl)),
|
|
40168
|
+
tsvSafe(sanitizeDisplay(env2.primaryUrl ?? "")),
|
|
38845
40169
|
String(env2.isProduction),
|
|
38846
40170
|
tsvSafe(toIso(env2.createdAt))
|
|
38847
40171
|
].join(" ")
|
|
@@ -38853,17 +40177,17 @@ function buildEnvironmentTable(envs, leading) {
|
|
|
38853
40177
|
leading: leading.map((column) => sanitizeDisplay(column.value(e2))),
|
|
38854
40178
|
name: sanitizeDisplay(e2.name),
|
|
38855
40179
|
prod: e2.isProduction ? "yes" : "no",
|
|
38856
|
-
url: sanitizeDisplay(e2.primaryUrl)
|
|
40180
|
+
url: e2.primaryUrl != null ? sanitizeDisplay(e2.primaryUrl) : "\u2014"
|
|
38857
40181
|
}));
|
|
38858
40182
|
const leadingWidths = leading.map(
|
|
38859
|
-
(column, i) => Math.max(column.header.length, ...cells.map((
|
|
40183
|
+
(column, i) => Math.max(column.header.length, ...cells.map((c51) => c51.leading[i]?.length ?? 0))
|
|
38860
40184
|
);
|
|
38861
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
40185
|
+
const nameWidth = Math.max(4, ...cells.map((c51) => c51.name.length));
|
|
38862
40186
|
const padLeading = (values) => values.map((v2, i) => v2.padEnd(leadingWidths[i] ?? 0)).join(" ");
|
|
38863
40187
|
return {
|
|
38864
|
-
header: `${padLeading(leading.map((
|
|
40188
|
+
header: `${padLeading(leading.map((c51) => c51.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
|
|
38865
40189
|
rows: cells.map(
|
|
38866
|
-
(
|
|
40190
|
+
(c51) => `${padLeading(c51.leading)} ${c51.name.padEnd(nameWidth)} ${c51.prod.padEnd(4)} ${c51.url}`
|
|
38867
40191
|
)
|
|
38868
40192
|
};
|
|
38869
40193
|
}
|
|
@@ -39225,6 +40549,120 @@ var packageMetadata = readPackageMetadata();
|
|
|
39225
40549
|
var CLI_PACKAGE_NAME = packageMetadata.name;
|
|
39226
40550
|
var CLI_VERSION = packageMetadata.version;
|
|
39227
40551
|
|
|
40552
|
+
// src/pentest/commands.ts
|
|
40553
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
40554
|
+
|
|
40555
|
+
// src/pentest/questionnaire.ts
|
|
40556
|
+
function buildUpsertQuestionnaireBody(answers) {
|
|
40557
|
+
if (answers === null) {
|
|
40558
|
+
return { answers: null };
|
|
40559
|
+
}
|
|
40560
|
+
return { answers: normalizePentestCustomerIntakeAnswers(answers) };
|
|
40561
|
+
}
|
|
40562
|
+
function parseQuestionnaireAnswersFile(raw, sourceLabel = "file") {
|
|
40563
|
+
let parsed;
|
|
40564
|
+
try {
|
|
40565
|
+
parsed = JSON.parse(raw);
|
|
40566
|
+
} catch {
|
|
40567
|
+
return { error: `Invalid JSON in ${sourceLabel}.` };
|
|
40568
|
+
}
|
|
40569
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
40570
|
+
return {
|
|
40571
|
+
error: `${sourceLabel} must be a JSON object of questionnaire answers (not an array or null).`
|
|
40572
|
+
};
|
|
40573
|
+
}
|
|
40574
|
+
if ("answers" in parsed && Object.keys(parsed).length === 1) {
|
|
40575
|
+
return {
|
|
40576
|
+
error: `${sourceLabel} must contain the answers object directly, not an { answers } wrapper. The CLI wraps it for the API.`
|
|
40577
|
+
};
|
|
40578
|
+
}
|
|
40579
|
+
const result = PentestCustomerIntakeAnswersSchema.safeParse(parsed);
|
|
40580
|
+
if (!result.success) {
|
|
40581
|
+
const issue2 = result.error.issues[0];
|
|
40582
|
+
const path = issue2?.path.length ? issue2.path.join(".") : "answers";
|
|
40583
|
+
const message = issue2?.message ?? "invalid";
|
|
40584
|
+
return { error: `Invalid questionnaire answers in ${sourceLabel}: ${path} \u2014 ${message}` };
|
|
40585
|
+
}
|
|
40586
|
+
return { answers: normalizePentestCustomerIntakeAnswers(result.data) };
|
|
40587
|
+
}
|
|
40588
|
+
function applyTextIntakeAnswer(current, key, input) {
|
|
40589
|
+
const trimmed = input.trim();
|
|
40590
|
+
if (trimmed.length === 0) {
|
|
40591
|
+
return current;
|
|
40592
|
+
}
|
|
40593
|
+
return { ...current, [key]: trimmed };
|
|
40594
|
+
}
|
|
40595
|
+
function applyMultiSelectIntakeAnswer(current, key, selected) {
|
|
40596
|
+
if (selected.length === 0) {
|
|
40597
|
+
return current;
|
|
40598
|
+
}
|
|
40599
|
+
return {
|
|
40600
|
+
...current,
|
|
40601
|
+
[key]: Array.from(new Set(selected)).sort()
|
|
40602
|
+
};
|
|
40603
|
+
}
|
|
40604
|
+
function formatIssueClasses(values) {
|
|
40605
|
+
return values.map((v2) => INTAKE_ISSUE_CLASS_LABELS[v2]).join(", ");
|
|
40606
|
+
}
|
|
40607
|
+
function formatSurfaces(values) {
|
|
40608
|
+
return values.map((v2) => INTAKE_SURFACE_LABELS[v2]).join(", ");
|
|
40609
|
+
}
|
|
40610
|
+
function formatAnswerValue(key, answers) {
|
|
40611
|
+
switch (key) {
|
|
40612
|
+
case "issueClasses": {
|
|
40613
|
+
const values = answers.issueClasses;
|
|
40614
|
+
if (values === void 0 || values.length === 0) {
|
|
40615
|
+
return null;
|
|
40616
|
+
}
|
|
40617
|
+
return formatIssueClasses(values);
|
|
40618
|
+
}
|
|
40619
|
+
case "surfaces": {
|
|
40620
|
+
const values = answers.surfaces;
|
|
40621
|
+
if (values === void 0 || values.length === 0) {
|
|
40622
|
+
return null;
|
|
40623
|
+
}
|
|
40624
|
+
return formatSurfaces(values);
|
|
40625
|
+
}
|
|
40626
|
+
default: {
|
|
40627
|
+
const value = answers[key];
|
|
40628
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
40629
|
+
return null;
|
|
40630
|
+
}
|
|
40631
|
+
return value;
|
|
40632
|
+
}
|
|
40633
|
+
}
|
|
40634
|
+
}
|
|
40635
|
+
function formatQuestionnaireShow(input) {
|
|
40636
|
+
const lines = [
|
|
40637
|
+
`Editable: ${input.editable ? "yes (scoping window open)" : "no (editing closed after scoping)"}`
|
|
40638
|
+
];
|
|
40639
|
+
if (input.answers === null || Object.keys(input.answers).length === 0) {
|
|
40640
|
+
lines.push("Answers: (none)");
|
|
40641
|
+
return lines.join("\n");
|
|
40642
|
+
}
|
|
40643
|
+
lines.push("Answers:");
|
|
40644
|
+
for (const key of PENTEST_CUSTOMER_INTAKE_ANSWER_KEYS) {
|
|
40645
|
+
const value = formatAnswerValue(key, input.answers);
|
|
40646
|
+
if (value === null) {
|
|
40647
|
+
continue;
|
|
40648
|
+
}
|
|
40649
|
+
lines.push(`${PENTEST_CUSTOMER_INTAKE_LABELS[key]}: ${value}`);
|
|
40650
|
+
}
|
|
40651
|
+
return lines.join("\n");
|
|
40652
|
+
}
|
|
40653
|
+
function issueClassSelectOptions() {
|
|
40654
|
+
return CustomerPriorityCategoryValues.map((value) => ({
|
|
40655
|
+
value,
|
|
40656
|
+
label: INTAKE_ISSUE_CLASS_LABELS[value]
|
|
40657
|
+
}));
|
|
40658
|
+
}
|
|
40659
|
+
function surfaceSelectOptions() {
|
|
40660
|
+
return IntakeSurfaceValues.map((value) => ({
|
|
40661
|
+
value,
|
|
40662
|
+
label: INTAKE_SURFACE_LABELS[value]
|
|
40663
|
+
}));
|
|
40664
|
+
}
|
|
40665
|
+
|
|
39228
40666
|
// src/pentest/commands.ts
|
|
39229
40667
|
var DEFAULT_LIMIT2 = 30;
|
|
39230
40668
|
var MAX_LIMIT2 = 100;
|
|
@@ -39474,13 +40912,9 @@ Examples:
|
|
|
39474
40912
|
console.error(`Failed to list findings (status ${result.status}).`);
|
|
39475
40913
|
process.exit(1);
|
|
39476
40914
|
}
|
|
39477
|
-
|
|
39478
|
-
|
|
39479
|
-
|
|
39480
|
-
}
|
|
39481
|
-
if (options.status) {
|
|
39482
|
-
filteredFindings = filteredFindings.filter((f) => f.status === options.status);
|
|
39483
|
-
}
|
|
40915
|
+
const filteredFindings = result.body.filter(
|
|
40916
|
+
(f) => (!options.severity || f.severity === options.severity) && (!options.status || f.status === options.status)
|
|
40917
|
+
);
|
|
39484
40918
|
filteredFindings.sort(
|
|
39485
40919
|
(a, b2) => (SEVERITY_ORDER[a.severity] ?? 99) - (SEVERITY_ORDER[b2.severity] ?? 99)
|
|
39486
40920
|
);
|
|
@@ -39764,16 +41198,248 @@ Examples:
|
|
|
39764
41198
|
await runUpdate4(pentestId, options);
|
|
39765
41199
|
});
|
|
39766
41200
|
}
|
|
41201
|
+
function failQuestionnaire(status, body, action, notFoundLabel) {
|
|
41202
|
+
const { message } = readErrorFields(body);
|
|
41203
|
+
if (status === UNAUTHORIZED_STATUS2) {
|
|
41204
|
+
exitAuthFailed();
|
|
41205
|
+
}
|
|
41206
|
+
if (status === 403) {
|
|
41207
|
+
if (action === "write") {
|
|
41208
|
+
console.error(
|
|
41209
|
+
colorError(
|
|
41210
|
+
"Questionnaire writes require an organization admin (or Trace staff) signed in with a browser session. API keys are rejected."
|
|
41211
|
+
)
|
|
41212
|
+
);
|
|
41213
|
+
} else {
|
|
41214
|
+
console.error(
|
|
41215
|
+
colorError(message ?? "You do not have permission to view this questionnaire.")
|
|
41216
|
+
);
|
|
41217
|
+
}
|
|
41218
|
+
process.exit(1);
|
|
41219
|
+
}
|
|
41220
|
+
if (status === 404) {
|
|
41221
|
+
console.error(
|
|
41222
|
+
colorError(notFoundLabel ? `Pentest not found: ${notFoundLabel}.` : message ?? "Not found.")
|
|
41223
|
+
);
|
|
41224
|
+
process.exit(1);
|
|
41225
|
+
}
|
|
41226
|
+
if (status === 400) {
|
|
41227
|
+
console.error(colorError(message ?? "Invalid questionnaire answers (status 400)."));
|
|
41228
|
+
process.exit(1);
|
|
41229
|
+
}
|
|
41230
|
+
if (status === 409) {
|
|
41231
|
+
console.error(
|
|
41232
|
+
colorError(
|
|
41233
|
+
message ?? "Questionnaire editing is closed after scoping starts (current stage is past DRAFT / READY_TO_START)."
|
|
41234
|
+
)
|
|
41235
|
+
);
|
|
41236
|
+
process.exit(1);
|
|
41237
|
+
}
|
|
41238
|
+
console.error(
|
|
41239
|
+
colorError(
|
|
41240
|
+
`Failed to ${action === "write" ? "save" : "load"} questionnaire (status ${status})${message ? `: ${message}` : "."}`
|
|
41241
|
+
)
|
|
41242
|
+
);
|
|
41243
|
+
process.exit(1);
|
|
41244
|
+
}
|
|
41245
|
+
async function fetchQuestionnaire(organizationId, pentestId, notFoundLabel) {
|
|
41246
|
+
const result = await authenticatedRequest(
|
|
41247
|
+
(client) => client.pentest.getCustomerPentestQuestionnaire({
|
|
41248
|
+
params: { organizationId, pentestId }
|
|
41249
|
+
})
|
|
41250
|
+
);
|
|
41251
|
+
if (result.status !== SUCCESS_STATUS) {
|
|
41252
|
+
failQuestionnaire(result.status, result.body, "read", notFoundLabel);
|
|
41253
|
+
}
|
|
41254
|
+
return result.body;
|
|
41255
|
+
}
|
|
41256
|
+
async function putQuestionnaire(organizationId, pentestId, answers, notFoundLabel) {
|
|
41257
|
+
const body = buildUpsertQuestionnaireBody(answers);
|
|
41258
|
+
const result = await authenticatedRequest(
|
|
41259
|
+
(client) => client.pentest.upsertCustomerPentestQuestionnaire({
|
|
41260
|
+
params: { organizationId, pentestId },
|
|
41261
|
+
body
|
|
41262
|
+
})
|
|
41263
|
+
);
|
|
41264
|
+
if (result.status !== SUCCESS_STATUS) {
|
|
41265
|
+
failQuestionnaire(result.status, result.body, "write", notFoundLabel);
|
|
41266
|
+
}
|
|
41267
|
+
return result.body;
|
|
41268
|
+
}
|
|
41269
|
+
function exitCancelled() {
|
|
41270
|
+
me("Cancelled.");
|
|
41271
|
+
process.exit(1);
|
|
41272
|
+
}
|
|
41273
|
+
async function promptQuestionnaireAnswers(existing) {
|
|
41274
|
+
let working = { ...existing ?? {} };
|
|
41275
|
+
const textPrompt = async (key, question) => {
|
|
41276
|
+
const previous = existing?.[key];
|
|
41277
|
+
const value = await fe({
|
|
41278
|
+
message: `${question} (empty keeps previous)`,
|
|
41279
|
+
initialValue: previous ?? "",
|
|
41280
|
+
...previous ? {} : { placeholder: "Optional, press Enter to skip" }
|
|
41281
|
+
});
|
|
41282
|
+
if (q(value)) {
|
|
41283
|
+
exitCancelled();
|
|
41284
|
+
}
|
|
41285
|
+
working = applyTextIntakeAnswer(working, key, value);
|
|
41286
|
+
};
|
|
41287
|
+
for (const entry of PENTEST_CUSTOMER_INTAKE_QUESTIONS) {
|
|
41288
|
+
if (entry.kind === "text") {
|
|
41289
|
+
await textPrompt(entry.key, entry.question);
|
|
41290
|
+
continue;
|
|
41291
|
+
}
|
|
41292
|
+
const message = `${entry.question} (empty keeps previous)`;
|
|
41293
|
+
if (entry.key === "issueClasses") {
|
|
41294
|
+
const selected = await ve({
|
|
41295
|
+
message,
|
|
41296
|
+
options: issueClassSelectOptions(),
|
|
41297
|
+
required: false,
|
|
41298
|
+
...existing?.issueClasses !== void 0 ? { initialValues: existing.issueClasses } : {}
|
|
41299
|
+
});
|
|
41300
|
+
if (q(selected)) {
|
|
41301
|
+
exitCancelled();
|
|
41302
|
+
}
|
|
41303
|
+
working = applyMultiSelectIntakeAnswer(working, "issueClasses", selected);
|
|
41304
|
+
} else {
|
|
41305
|
+
const selected = await ve({
|
|
41306
|
+
message,
|
|
41307
|
+
options: surfaceSelectOptions(),
|
|
41308
|
+
required: false,
|
|
41309
|
+
...existing?.surfaces !== void 0 ? { initialValues: existing.surfaces } : {}
|
|
41310
|
+
});
|
|
41311
|
+
if (q(selected)) {
|
|
41312
|
+
exitCancelled();
|
|
41313
|
+
}
|
|
41314
|
+
working = applyMultiSelectIntakeAnswer(working, "surfaces", selected);
|
|
41315
|
+
}
|
|
41316
|
+
await textPrompt(entry.notesKey, entry.notesQuestion);
|
|
41317
|
+
}
|
|
41318
|
+
const confirmed = await ue({
|
|
41319
|
+
message: "Save questionnaire answers?",
|
|
41320
|
+
initialValue: true
|
|
41321
|
+
});
|
|
41322
|
+
if (q(confirmed) || !confirmed) {
|
|
41323
|
+
exitCancelled();
|
|
41324
|
+
}
|
|
41325
|
+
if (Object.keys(working).length === 0) {
|
|
41326
|
+
return existing === null ? null : working;
|
|
41327
|
+
}
|
|
41328
|
+
return working;
|
|
41329
|
+
}
|
|
41330
|
+
async function runQuestionnaire(pentestIdentifier, options) {
|
|
41331
|
+
const show = options.show === true;
|
|
41332
|
+
const filePath = options.file;
|
|
41333
|
+
if (show && filePath !== void 0) {
|
|
41334
|
+
console.error(colorError("Pass only one of --show / --file."));
|
|
41335
|
+
process.exit(1);
|
|
41336
|
+
}
|
|
41337
|
+
const isInteractiveTty = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
41338
|
+
if (!show && filePath === void 0 && !isInteractiveTty) {
|
|
41339
|
+
console.error(
|
|
41340
|
+
colorError(
|
|
41341
|
+
"Interactive questionnaire requires a TTY. Use --show to print answers, or --file <path> to upload an answers JSON object."
|
|
41342
|
+
)
|
|
41343
|
+
);
|
|
41344
|
+
process.exit(2);
|
|
41345
|
+
}
|
|
41346
|
+
const organizationId = await resolveOrganizationId();
|
|
41347
|
+
const pentestId = await resolvePentestId(organizationId, pentestIdentifier);
|
|
41348
|
+
if (show) {
|
|
41349
|
+
const current2 = await fetchQuestionnaire(organizationId, pentestId, pentestIdentifier);
|
|
41350
|
+
console.log(
|
|
41351
|
+
formatQuestionnaireShow({
|
|
41352
|
+
answers: current2.answers,
|
|
41353
|
+
editable: current2.editable
|
|
41354
|
+
})
|
|
41355
|
+
);
|
|
41356
|
+
return;
|
|
41357
|
+
}
|
|
41358
|
+
if (filePath !== void 0) {
|
|
41359
|
+
let raw;
|
|
41360
|
+
try {
|
|
41361
|
+
raw = readFileSync4(filePath, "utf8");
|
|
41362
|
+
} catch {
|
|
41363
|
+
console.error(colorError(`Could not read answers file: ${filePath}`));
|
|
41364
|
+
process.exit(1);
|
|
41365
|
+
}
|
|
41366
|
+
const parsed = parseQuestionnaireAnswersFile(raw, filePath);
|
|
41367
|
+
if ("error" in parsed) {
|
|
41368
|
+
console.error(colorError(parsed.error));
|
|
41369
|
+
process.exit(1);
|
|
41370
|
+
}
|
|
41371
|
+
const saved2 = await putQuestionnaire(
|
|
41372
|
+
organizationId,
|
|
41373
|
+
pentestId,
|
|
41374
|
+
parsed.answers,
|
|
41375
|
+
pentestIdentifier
|
|
41376
|
+
);
|
|
41377
|
+
console.log(colorSuccess("Saved questionnaire answers."));
|
|
41378
|
+
console.log(
|
|
41379
|
+
formatQuestionnaireShow({
|
|
41380
|
+
answers: saved2.answers,
|
|
41381
|
+
editable: saved2.editable
|
|
41382
|
+
})
|
|
41383
|
+
);
|
|
41384
|
+
return;
|
|
41385
|
+
}
|
|
41386
|
+
const current = await fetchQuestionnaire(organizationId, pentestId, pentestIdentifier);
|
|
41387
|
+
if (!current.editable) {
|
|
41388
|
+
console.error(
|
|
41389
|
+
colorError(
|
|
41390
|
+
"Questionnaire editing is closed after scoping starts. Use --show to view the saved answers."
|
|
41391
|
+
)
|
|
41392
|
+
);
|
|
41393
|
+
process.exit(1);
|
|
41394
|
+
}
|
|
41395
|
+
const merged = await promptQuestionnaireAnswers(current.answers);
|
|
41396
|
+
const saved = await putQuestionnaire(organizationId, pentestId, merged, pentestIdentifier);
|
|
41397
|
+
console.log(colorSuccess("Saved questionnaire answers."));
|
|
41398
|
+
console.log(
|
|
41399
|
+
formatQuestionnaireShow({
|
|
41400
|
+
answers: saved.answers,
|
|
41401
|
+
editable: saved.editable
|
|
41402
|
+
})
|
|
41403
|
+
);
|
|
41404
|
+
}
|
|
41405
|
+
function createQuestionnaireCommand() {
|
|
41406
|
+
return new Command("questionnaire").description("View or fill the customer pentest intake questionnaire").argument("<pentestId>", "Pentest display ID (e.g. PT-3) or UUID").option("--show", "Print current answers using shared labels (GET)").option(
|
|
41407
|
+
"--file <path>",
|
|
41408
|
+
"Upload answers from a JSON file (answers object only \u2014 not { answers }; whole-object replace)"
|
|
41409
|
+
).addHelpText(
|
|
41410
|
+
"after",
|
|
41411
|
+
`
|
|
41412
|
+
Optional scoping questionnaire for a new pentest (editable while stage is DRAFT
|
|
41413
|
+
or READY_TO_START). Reads accept a browser session or API key; writes require an
|
|
41414
|
+
organization admin (or Trace staff) signed in via \`tracecli auth login\` \u2014 API
|
|
41415
|
+
keys are rejected.
|
|
41416
|
+
|
|
41417
|
+
Modes:
|
|
41418
|
+
--show GET and print key: value with shared customer-facing labels
|
|
41419
|
+
--file <path> PUT the file's answers object (CLI wraps { answers } for the API)
|
|
41420
|
+
(TTY default) load-merge-write: GET, prompt each question, confirm, PUT
|
|
41421
|
+
|
|
41422
|
+
Non-interactive shells must pass --show or --file (exit 2 otherwise).
|
|
41423
|
+
|
|
41424
|
+
Examples:
|
|
41425
|
+
tracecli pentest questionnaire PT-1 --show
|
|
41426
|
+
tracecli pentest questionnaire PT-1 --file answers.json
|
|
41427
|
+
tracecli pentest questionnaire PT-1`
|
|
41428
|
+
).action(async (pentestId, options) => {
|
|
41429
|
+
await runQuestionnaire(pentestId, options);
|
|
41430
|
+
});
|
|
41431
|
+
}
|
|
39767
41432
|
function createPentestCommand() {
|
|
39768
41433
|
const pentest = new Command("pentest").description("Manage pentests");
|
|
39769
41434
|
pentest.addCommand(createListCommand5());
|
|
39770
41435
|
pentest.addCommand(createUpdateCommand4());
|
|
41436
|
+
pentest.addCommand(createQuestionnaireCommand());
|
|
39771
41437
|
pentest.addCommand(createFindingsCommand());
|
|
39772
41438
|
return pentest;
|
|
39773
41439
|
}
|
|
39774
41440
|
|
|
39775
41441
|
// src/update/commands.ts
|
|
39776
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as
|
|
41442
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
39777
41443
|
import { dirname as dirname2, join as join5 } from "path";
|
|
39778
41444
|
import { createInterface as createInterface4 } from "readline/promises";
|
|
39779
41445
|
var UPDATE_CACHE_FILE = "update-check.json";
|
|
@@ -39791,7 +41457,7 @@ function readUpdateCheckCache() {
|
|
|
39791
41457
|
return null;
|
|
39792
41458
|
}
|
|
39793
41459
|
try {
|
|
39794
|
-
const rawCache =
|
|
41460
|
+
const rawCache = readFileSync5(cachePath, "utf-8");
|
|
39795
41461
|
const parsed = JSON.parse(rawCache);
|
|
39796
41462
|
if (typeof parsed !== "object" || parsed === null) {
|
|
39797
41463
|
return null;
|
|
@@ -40521,177 +42187,10 @@ Examples:
|
|
|
40521
42187
|
}
|
|
40522
42188
|
);
|
|
40523
42189
|
}
|
|
40524
|
-
var FIX_PR_TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
40525
|
-
"PR_OPENED",
|
|
40526
|
-
"NO_SAFE_FIX",
|
|
40527
|
-
"PATCH_TOO_LARGE",
|
|
40528
|
-
"TESTS_FAILED",
|
|
40529
|
-
"INFRA_FAILED",
|
|
40530
|
-
"STALE_VULN",
|
|
40531
|
-
"TIMED_OUT",
|
|
40532
|
-
"CANCELLED"
|
|
40533
|
-
]);
|
|
40534
|
-
var FIX_PR_AGENT_FLAVORS = ["claude-code", "codex"];
|
|
40535
|
-
var FIX_PR_POLL_MS = 3e3;
|
|
40536
|
-
function isFixPrAgentFlavor(value) {
|
|
40537
|
-
return FIX_PR_AGENT_FLAVORS.includes(value);
|
|
40538
|
-
}
|
|
40539
|
-
function formatFixPrWatchLine(row) {
|
|
40540
|
-
return `[${row.status}] run=${row.runId.slice(0, 8)} agent=${row.agentFlavor}`;
|
|
40541
|
-
}
|
|
40542
|
-
function formatFixPrTerminalLines(row) {
|
|
40543
|
-
const link = row.prUrl ? ` ${row.prUrl}` : "";
|
|
40544
|
-
const lines = [`Run ${row.runId} \u2192 ${row.status}${link}`];
|
|
40545
|
-
if (row.statusDetails) {
|
|
40546
|
-
lines.push(`Details: ${row.statusDetails}`);
|
|
40547
|
-
}
|
|
40548
|
-
return lines;
|
|
40549
|
-
}
|
|
40550
|
-
function createFixCommand() {
|
|
40551
|
-
return new Command("fix").description("Trigger a Trace auto-fix PR for the vulnerability (staff-only dogfood)").argument("<id>", "Vulnerability display ID (e.g. TRACE-123 or 123) or UUID").option(
|
|
40552
|
-
"--agent <flavor>",
|
|
40553
|
-
`Override the agent flavor (one of: ${FIX_PR_AGENT_FLAVORS.join(", ")})`
|
|
40554
|
-
).option("--watch", "Poll the run until it reaches a terminal status", false).option("-o, --output <format>", "Output format: table, json (default: table)", "table").addHelpText(
|
|
40555
|
-
"after",
|
|
40556
|
-
`
|
|
40557
|
-
Examples:
|
|
40558
|
-
# Trigger and exit immediately (scripting):
|
|
40559
|
-
tracecli vulnerabilities fix TRACE-123
|
|
40560
|
-
|
|
40561
|
-
# Trigger and watch until terminal:
|
|
40562
|
-
tracecli vulnerabilities fix TRACE-123 --watch
|
|
40563
|
-
|
|
40564
|
-
# Trigger with codex agent (requires AZURE_OPENAI_ENABLED):
|
|
40565
|
-
tracecli vulnerabilities fix TRACE-123 --agent codex
|
|
40566
|
-
|
|
40567
|
-
# JSON output (final row to stdout; rolling status to stderr under --watch):
|
|
40568
|
-
tracecli vulnerabilities fix TRACE-123 --watch --output json | jq .`
|
|
40569
|
-
).action(
|
|
40570
|
-
async (identifier, options) => {
|
|
40571
|
-
if (options.agent && !isFixPrAgentFlavor(options.agent)) {
|
|
40572
|
-
console.error(
|
|
40573
|
-
`Invalid --agent '${options.agent}'. Expected one of: ${FIX_PR_AGENT_FLAVORS.join(", ")}.`
|
|
40574
|
-
);
|
|
40575
|
-
process.exit(1);
|
|
40576
|
-
}
|
|
40577
|
-
if (options.output !== "table" && options.output !== "json") {
|
|
40578
|
-
console.error(`Invalid --output '${options.output}'. Expected one of: table, json.`);
|
|
40579
|
-
process.exit(1);
|
|
40580
|
-
}
|
|
40581
|
-
const organizationId = await resolveOrganizationId();
|
|
40582
|
-
const triggerResult = await authenticatedRequest(
|
|
40583
|
-
(client) => client.vulnerabilityFixRun.triggerRun({
|
|
40584
|
-
params: { organizationId, vulnerabilityId: identifier },
|
|
40585
|
-
body: options.agent ? { agentFlavor: options.agent } : {}
|
|
40586
|
-
})
|
|
40587
|
-
);
|
|
40588
|
-
if (triggerResult.status === 401) {
|
|
40589
|
-
console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
|
|
40590
|
-
process.exit(1);
|
|
40591
|
-
}
|
|
40592
|
-
if (triggerResult.status === 403) {
|
|
40593
|
-
console.error(
|
|
40594
|
-
"Forbidden \u2014 vulnerability fix-PR is a staff-only feature gated by the AUTO_FIX_PR capability."
|
|
40595
|
-
);
|
|
40596
|
-
process.exit(1);
|
|
40597
|
-
}
|
|
40598
|
-
if (triggerResult.status === 404) {
|
|
40599
|
-
console.error(
|
|
40600
|
-
`Vulnerability '${identifier}' not found.
|
|
40601
|
-
Run \`tracecli vulnerabilities list\` to see available vulnerabilities.`
|
|
40602
|
-
);
|
|
40603
|
-
process.exit(1);
|
|
40604
|
-
}
|
|
40605
|
-
if (triggerResult.status === 429) {
|
|
40606
|
-
const body = triggerResult.body;
|
|
40607
|
-
const retry = body.details?.retryAfterSeconds;
|
|
40608
|
-
console.error(
|
|
40609
|
-
`Daily cap exceeded. ${retry ? `Try again in ${retry}s.` : body.message ?? ""}`
|
|
40610
|
-
);
|
|
40611
|
-
process.exit(1);
|
|
40612
|
-
}
|
|
40613
|
-
if (triggerResult.status === 400) {
|
|
40614
|
-
const body = triggerResult.body;
|
|
40615
|
-
console.error(`Bad request: ${body.message ?? "invalid input"}`);
|
|
40616
|
-
process.exit(1);
|
|
40617
|
-
}
|
|
40618
|
-
if (triggerResult.status !== 201) {
|
|
40619
|
-
console.error(`Failed to trigger fix-PR run (status ${triggerResult.status}).`);
|
|
40620
|
-
process.exit(1);
|
|
40621
|
-
}
|
|
40622
|
-
const triggered = triggerResult.body;
|
|
40623
|
-
if (!options.watch) {
|
|
40624
|
-
if (options.output === "json") {
|
|
40625
|
-
console.log(JSON.stringify(triggered, null, 2));
|
|
40626
|
-
} else {
|
|
40627
|
-
console.log(
|
|
40628
|
-
`Triggered fix-PR run ${triggered.runId} (status=${triggered.status}, agent=${triggered.agentFlavor})`
|
|
40629
|
-
);
|
|
40630
|
-
}
|
|
40631
|
-
process.exit(0);
|
|
40632
|
-
}
|
|
40633
|
-
let latest = triggered;
|
|
40634
|
-
const isTTY = process.stderr.isTTY ?? false;
|
|
40635
|
-
const onSigint = () => {
|
|
40636
|
-
const msg = `
|
|
40637
|
-
watch interrupted; run id=${latest.runId}`;
|
|
40638
|
-
process.stderr.write(`${msg}
|
|
40639
|
-
`);
|
|
40640
|
-
process.exit(130);
|
|
40641
|
-
};
|
|
40642
|
-
process.on("SIGINT", onSigint);
|
|
40643
|
-
const writeRolling = (row) => {
|
|
40644
|
-
const line = formatFixPrWatchLine(row);
|
|
40645
|
-
if (isTTY && options.output !== "json") {
|
|
40646
|
-
process.stderr.write(`\r${line} `);
|
|
40647
|
-
} else {
|
|
40648
|
-
process.stderr.write(`${line}
|
|
40649
|
-
`);
|
|
40650
|
-
}
|
|
40651
|
-
};
|
|
40652
|
-
while (!FIX_PR_TERMINAL_STATUSES.has(latest.status)) {
|
|
40653
|
-
writeRolling(latest);
|
|
40654
|
-
await new Promise((resolve) => setTimeout(resolve, FIX_PR_POLL_MS));
|
|
40655
|
-
const pollResult = await authenticatedRequest(
|
|
40656
|
-
(client) => client.vulnerabilityFixRun.getRun({
|
|
40657
|
-
params: {
|
|
40658
|
-
organizationId,
|
|
40659
|
-
vulnerabilityId: identifier,
|
|
40660
|
-
runId: latest.runId
|
|
40661
|
-
}
|
|
40662
|
-
})
|
|
40663
|
-
);
|
|
40664
|
-
if (pollResult.status === 401) {
|
|
40665
|
-
process.stderr.write("\n");
|
|
40666
|
-
console.error("Authentication failed during watch. Run `tracecli auth login`.");
|
|
40667
|
-
process.exit(1);
|
|
40668
|
-
}
|
|
40669
|
-
if (pollResult.status !== 200) {
|
|
40670
|
-
process.stderr.write("\n");
|
|
40671
|
-
console.error(`Failed to read run status (status ${pollResult.status}).`);
|
|
40672
|
-
process.exit(1);
|
|
40673
|
-
}
|
|
40674
|
-
latest = pollResult.body;
|
|
40675
|
-
}
|
|
40676
|
-
if (isTTY && options.output !== "json") {
|
|
40677
|
-
process.stderr.write("\n");
|
|
40678
|
-
}
|
|
40679
|
-
if (options.output === "json") {
|
|
40680
|
-
console.log(JSON.stringify(latest, null, 2));
|
|
40681
|
-
} else {
|
|
40682
|
-
for (const line of formatFixPrTerminalLines(latest)) {
|
|
40683
|
-
console.log(line);
|
|
40684
|
-
}
|
|
40685
|
-
}
|
|
40686
|
-
process.exit(latest.status === "PR_OPENED" ? 0 : 2);
|
|
40687
|
-
}
|
|
40688
|
-
);
|
|
40689
|
-
}
|
|
40690
42190
|
function createVulnerabilitiesCommand() {
|
|
40691
42191
|
const vulnerabilities = new Command("vulnerabilities").description("Manage vulnerabilities");
|
|
40692
42192
|
vulnerabilities.addCommand(createGetCommand4());
|
|
40693
42193
|
vulnerabilities.addCommand(createListCommand6());
|
|
40694
|
-
vulnerabilities.addCommand(createFixCommand());
|
|
40695
42194
|
return vulnerabilities;
|
|
40696
42195
|
}
|
|
40697
42196
|
|