securewithtrace 0.32.0 → 0.34.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/README.md +1 -0
- package/dist/index.js +1237 -317
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -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);
|
|
@@ -21911,7 +21911,8 @@ var OperatorPentestContextSchema = external_exports.object({
|
|
|
21911
21911
|
environments: external_exports.array(
|
|
21912
21912
|
external_exports.object({
|
|
21913
21913
|
name: external_exports.string(),
|
|
21914
|
-
|
|
21914
|
+
// Null for repo-only application types (CLI, MOBILE, DESKTOP).
|
|
21915
|
+
primaryUrl: external_exports.string().nullable(),
|
|
21915
21916
|
isProduction: external_exports.boolean()
|
|
21916
21917
|
})
|
|
21917
21918
|
),
|
|
@@ -22365,27 +22366,12 @@ var ApplicationRepositoryRoleValues = [
|
|
|
22365
22366
|
"MOBILE_CLIENT",
|
|
22366
22367
|
"OTHER"
|
|
22367
22368
|
];
|
|
22368
|
-
var ScopeDomainSourceValues = ["DERIVED", "MANUAL"];
|
|
22369
22369
|
var ApplicationIdParamsSchema = OrgIdParamsSchema.extend({
|
|
22370
22370
|
applicationId: external_exports.uuid()
|
|
22371
22371
|
});
|
|
22372
22372
|
var ApplicationRepositoryIdParamsSchema = ApplicationIdParamsSchema.extend({
|
|
22373
22373
|
applicationRepositoryId: external_exports.uuid()
|
|
22374
22374
|
});
|
|
22375
|
-
var AuthorizedDomainIdParamsSchema = ApplicationIdParamsSchema.extend({
|
|
22376
|
-
applicationAuthorizedDomainId: external_exports.uuid()
|
|
22377
|
-
});
|
|
22378
|
-
var AuthorizedDomainResponseSchema = external_exports.object({
|
|
22379
|
-
applicationAuthorizedDomainId: external_exports.uuid(),
|
|
22380
|
-
applicationId: external_exports.uuid(),
|
|
22381
|
-
organizationId: external_exports.uuid(),
|
|
22382
|
-
domain: external_exports.string(),
|
|
22383
|
-
source: external_exports.enum(ScopeDomainSourceValues),
|
|
22384
|
-
createdAt: external_exports.date()
|
|
22385
|
-
});
|
|
22386
|
-
var CreateAuthorizedDomainRequestSchema = external_exports.object({
|
|
22387
|
-
domain: external_exports.string().trim().min(1).max(253)
|
|
22388
|
-
}).strict();
|
|
22389
22375
|
var ApplicationRepositorySummarySchema = external_exports.object({
|
|
22390
22376
|
applicationRepositoryId: external_exports.uuid().nullable(),
|
|
22391
22377
|
applicationId: external_exports.uuid(),
|
|
@@ -22426,7 +22412,6 @@ var ApplicationResponseSchema = external_exports.object({
|
|
|
22426
22412
|
// Environments-tab panel hydrates from this payload (no client GET). Defaulted
|
|
22427
22413
|
// (like `type`) so a new client reading a pre-this-release API during a rolling
|
|
22428
22414
|
// deploy doesn't reject application rows that predate the field.
|
|
22429
|
-
authorizedDomains: external_exports.array(AuthorizedDomainResponseSchema).default([]),
|
|
22430
22415
|
// Signed S3 URL for the Overview screenshot. Defaulted null so a new client
|
|
22431
22416
|
// reading a pre-this-release API during a rolling deploy doesn't reject rows
|
|
22432
22417
|
// that omit the field. The raw S3 key is never on the wire.
|
|
@@ -22602,35 +22587,6 @@ var applicationContract = c4.router({
|
|
|
22602
22587
|
409: ErrorResponseSchema,
|
|
22603
22588
|
500: ErrorResponseSchema
|
|
22604
22589
|
}
|
|
22605
|
-
},
|
|
22606
|
-
addAuthorizedDomain: {
|
|
22607
|
-
method: "POST",
|
|
22608
|
-
path: "/organizations/:organizationId/applications/:applicationId/authorized-domains",
|
|
22609
|
-
pathParams: ApplicationIdParamsSchema,
|
|
22610
|
-
body: CreateAuthorizedDomainRequestSchema,
|
|
22611
|
-
responses: {
|
|
22612
|
-
201: AuthorizedDomainResponseSchema,
|
|
22613
|
-
// 400 = INVALID_DOMAIN (not a registrable domain / IP / bare suffix);
|
|
22614
|
-
// 409 = DOMAIN_ALREADY_AUTHORIZED.
|
|
22615
|
-
400: ErrorResponseSchema,
|
|
22616
|
-
401: ErrorResponseSchema,
|
|
22617
|
-
403: ErrorResponseSchema,
|
|
22618
|
-
404: ErrorResponseSchema,
|
|
22619
|
-
409: ErrorResponseSchema,
|
|
22620
|
-
500: ErrorResponseSchema
|
|
22621
|
-
}
|
|
22622
|
-
},
|
|
22623
|
-
deleteAuthorizedDomain: {
|
|
22624
|
-
method: "DELETE",
|
|
22625
|
-
path: "/organizations/:organizationId/applications/:applicationId/authorized-domains/:applicationAuthorizedDomainId",
|
|
22626
|
-
pathParams: AuthorizedDomainIdParamsSchema,
|
|
22627
|
-
responses: {
|
|
22628
|
-
204: DeleteResponseSchema,
|
|
22629
|
-
401: ErrorResponseSchema,
|
|
22630
|
-
403: ErrorResponseSchema,
|
|
22631
|
-
404: ErrorResponseSchema,
|
|
22632
|
-
500: ErrorResponseSchema
|
|
22633
|
-
}
|
|
22634
22590
|
}
|
|
22635
22591
|
});
|
|
22636
22592
|
|
|
@@ -23871,6 +23827,140 @@ var cloudIntegrationContract = c7.router({
|
|
|
23871
23827
|
}
|
|
23872
23828
|
});
|
|
23873
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
|
+
var StaffCodeSizeRepositorySchema = external_exports.object({
|
|
23875
|
+
repositoryId: external_exports.uuid(),
|
|
23876
|
+
repositoryUrl: external_exports.url(),
|
|
23877
|
+
platform: external_exports.enum(CodeSizePlatformValues),
|
|
23878
|
+
/** Resolved branch the measurement is keyed on (scanningBranch ?? default). */
|
|
23879
|
+
branch: external_exports.string(),
|
|
23880
|
+
/** null = no successful measurement for the current resolved branch. */
|
|
23881
|
+
billableSloc: external_exports.number().int().nonnegative().nullable(),
|
|
23882
|
+
/** null exactly when `billableSloc` is null. */
|
|
23883
|
+
measuredAt: external_exports.iso.datetime().nullable()
|
|
23884
|
+
});
|
|
23885
|
+
var StaffOrganizationCodeSizeResponseSchema = external_exports.object({
|
|
23886
|
+
/** Same server-side sort as the customer wire: measured first by
|
|
23887
|
+
* billableSloc desc (ties repositoryUrl asc), then unmeasured by
|
|
23888
|
+
* repositoryUrl asc. */
|
|
23889
|
+
repositories: external_exports.array(StaffCodeSizeRepositorySchema),
|
|
23890
|
+
// No language breakdown here on purpose: this panel answers "is every
|
|
23891
|
+
// repository measured, and how fresh", and the language view already exists
|
|
23892
|
+
// on the customer panel staff can impersonate into.
|
|
23893
|
+
totals: external_exports.object({
|
|
23894
|
+
billableSloc: external_exports.number().int().nonnegative(),
|
|
23895
|
+
rawLines: external_exports.number().int().nonnegative(),
|
|
23896
|
+
/** Connected GitHub/Bitbucket repos — the re-measure `all` scope size. */
|
|
23897
|
+
repositoryCount: external_exports.number().int().nonnegative(),
|
|
23898
|
+
/** Repos with a measurement for their current resolved branch. */
|
|
23899
|
+
measuredCount: external_exports.number().int().nonnegative(),
|
|
23900
|
+
/** Newest measuredAt across the org; null when nothing is measured. */
|
|
23901
|
+
lastMeasuredAt: external_exports.iso.datetime().nullable()
|
|
23902
|
+
})
|
|
23903
|
+
});
|
|
23904
|
+
var StaffCodeSizeRemeasureScopeValues = ["all", "unmeasured"];
|
|
23905
|
+
var StaffCodeSizeRemeasureRequestSchema = external_exports.object({
|
|
23906
|
+
scope: external_exports.enum(StaffCodeSizeRemeasureScopeValues)
|
|
23907
|
+
});
|
|
23908
|
+
var StaffCodeSizeRemeasureResponseSchema = external_exports.object({
|
|
23909
|
+
scope: external_exports.enum(StaffCodeSizeRemeasureScopeValues),
|
|
23910
|
+
/** Repos the scope selected. */
|
|
23911
|
+
requested: external_exports.number().int().nonnegative(),
|
|
23912
|
+
/** Messages SQS accepted. Lower than `requested` means a partial send —
|
|
23913
|
+
* reported rather than masked (the panel states this number). */
|
|
23914
|
+
enqueued: external_exports.number().int().nonnegative()
|
|
23915
|
+
});
|
|
23916
|
+
|
|
23917
|
+
// ../../packages/api-contracts/src/contracts/v1/code-size.ts
|
|
23918
|
+
var c8 = initContract();
|
|
23919
|
+
var codeSizeContract = c8.router({
|
|
23920
|
+
getOrganizationCodeSize: {
|
|
23921
|
+
method: "GET",
|
|
23922
|
+
path: "/organizations/:organizationId/code-size",
|
|
23923
|
+
pathParams: OrgIdParamsSchema,
|
|
23924
|
+
responses: {
|
|
23925
|
+
200: OrganizationCodeSizeResponseSchema,
|
|
23926
|
+
401: ErrorResponseSchema,
|
|
23927
|
+
403: ErrorResponseSchema,
|
|
23928
|
+
404: ErrorResponseSchema,
|
|
23929
|
+
500: ErrorResponseSchema
|
|
23930
|
+
}
|
|
23931
|
+
},
|
|
23932
|
+
// Staff-only: per-repo measurement freshness for the admin Controls panel.
|
|
23933
|
+
getStaffOrganizationCodeSize: {
|
|
23934
|
+
method: "GET",
|
|
23935
|
+
path: "/staff/organizations/:organizationId/code-size",
|
|
23936
|
+
pathParams: OrgIdParamsSchema,
|
|
23937
|
+
responses: {
|
|
23938
|
+
200: StaffOrganizationCodeSizeResponseSchema,
|
|
23939
|
+
401: ErrorResponseSchema,
|
|
23940
|
+
403: ErrorResponseSchema,
|
|
23941
|
+
404: ErrorResponseSchema,
|
|
23942
|
+
500: ErrorResponseSchema
|
|
23943
|
+
}
|
|
23944
|
+
},
|
|
23945
|
+
// Staff-only: enqueue measurements for the scoped repos. Enqueue-only — the
|
|
23946
|
+
// worker measures asynchronously, so a 200 means "requested", not "measured".
|
|
23947
|
+
remeasureStaffOrganizationCodeSize: {
|
|
23948
|
+
method: "POST",
|
|
23949
|
+
path: "/staff/organizations/:organizationId/code-size/re-measure",
|
|
23950
|
+
pathParams: OrgIdParamsSchema,
|
|
23951
|
+
body: StaffCodeSizeRemeasureRequestSchema,
|
|
23952
|
+
responses: {
|
|
23953
|
+
200: StaffCodeSizeRemeasureResponseSchema,
|
|
23954
|
+
401: ErrorResponseSchema,
|
|
23955
|
+
403: ErrorResponseSchema,
|
|
23956
|
+
404: ErrorResponseSchema,
|
|
23957
|
+
500: ErrorResponseSchema,
|
|
23958
|
+
// Measurement enqueueing is unconfigured (REPO_METADATA_QUEUE_URL unset).
|
|
23959
|
+
503: ErrorResponseSchema
|
|
23960
|
+
}
|
|
23961
|
+
}
|
|
23962
|
+
});
|
|
23963
|
+
|
|
23874
23964
|
// ../../packages/api-contracts/src/schemas/domain/credential.schema.ts
|
|
23875
23965
|
var CredentialTypeValues = [
|
|
23876
23966
|
"BEARER_TOKEN",
|
|
@@ -23978,13 +24068,13 @@ var StorageStateSchema = external_exports.object({
|
|
|
23978
24068
|
} catch {
|
|
23979
24069
|
return;
|
|
23980
24070
|
}
|
|
23981
|
-
s.cookies.forEach((
|
|
23982
|
-
const d2 =
|
|
24071
|
+
s.cookies.forEach((c51, i) => {
|
|
24072
|
+
const d2 = c51.domain.replace(/^\./, "").toLowerCase();
|
|
23983
24073
|
if (d2 !== host && !host.endsWith(`.${d2}`)) {
|
|
23984
24074
|
ctx.addIssue({
|
|
23985
24075
|
code: "custom",
|
|
23986
24076
|
path: ["cookies", i, "domain"],
|
|
23987
|
-
message: `cookie domain "${
|
|
24077
|
+
message: `cookie domain "${c51.domain}" is not the capture origin host "${host}" or a parent domain of it`
|
|
23988
24078
|
});
|
|
23989
24079
|
}
|
|
23990
24080
|
});
|
|
@@ -24192,8 +24282,8 @@ var RevealCredentialSecretResponseSchema = external_exports.discriminatedUnion("
|
|
|
24192
24282
|
]);
|
|
24193
24283
|
|
|
24194
24284
|
// ../../packages/api-contracts/src/contracts/v1/credential.ts
|
|
24195
|
-
var
|
|
24196
|
-
var credentialContract =
|
|
24285
|
+
var c9 = initContract();
|
|
24286
|
+
var credentialContract = c9.router({
|
|
24197
24287
|
listCredentials: {
|
|
24198
24288
|
method: "GET",
|
|
24199
24289
|
path: "/organizations/:organizationId/environments/:environmentId/credentials",
|
|
@@ -24285,7 +24375,7 @@ var credentialContract = c8.router({
|
|
|
24285
24375
|
method: "POST",
|
|
24286
24376
|
path: "/organizations/:organizationId/environments/:environmentId/credentials/:credentialId/reveal",
|
|
24287
24377
|
pathParams: CredentialIdParamsSchema,
|
|
24288
|
-
body:
|
|
24378
|
+
body: c9.noBody(),
|
|
24289
24379
|
responses: {
|
|
24290
24380
|
200: RevealCredentialSecretResponseSchema,
|
|
24291
24381
|
401: ErrorResponseSchema,
|
|
@@ -24512,8 +24602,8 @@ var DependencySummaryResponseSchema = external_exports.object({
|
|
|
24512
24602
|
});
|
|
24513
24603
|
|
|
24514
24604
|
// ../../packages/api-contracts/src/contracts/v1/dependency.ts
|
|
24515
|
-
var
|
|
24516
|
-
var dependencyContract =
|
|
24605
|
+
var c10 = initContract();
|
|
24606
|
+
var dependencyContract = c10.router({
|
|
24517
24607
|
/** Cross-repo dependency search. Two-phase: pg_trgm on Package, then join repos. */
|
|
24518
24608
|
searchDependencies: {
|
|
24519
24609
|
method: "POST",
|
|
@@ -24658,8 +24748,8 @@ var DockerScoutIntegrationResponseSchema = external_exports.object({
|
|
|
24658
24748
|
});
|
|
24659
24749
|
|
|
24660
24750
|
// ../../packages/api-contracts/src/contracts/v1/docker-scout-integration.ts
|
|
24661
|
-
var
|
|
24662
|
-
var dockerScoutIntegrationContract =
|
|
24751
|
+
var c11 = initContract();
|
|
24752
|
+
var dockerScoutIntegrationContract = c11.router({
|
|
24663
24753
|
createDockerScoutIntegration: {
|
|
24664
24754
|
method: "POST",
|
|
24665
24755
|
path: "/organizations/:organizationId/docker-scout-integration",
|
|
@@ -24848,12 +24938,12 @@ var EngagementResponseSchema = external_exports.object({
|
|
|
24848
24938
|
});
|
|
24849
24939
|
|
|
24850
24940
|
// ../../packages/api-contracts/src/contracts/v1/engagement.ts
|
|
24851
|
-
var
|
|
24941
|
+
var c12 = initContract();
|
|
24852
24942
|
var RecordDashboardSessionRequest = external_exports.object({
|
|
24853
24943
|
sessionId: external_exports.string().min(1).max(100)
|
|
24854
24944
|
});
|
|
24855
24945
|
var RecordDashboardSessionResponse = external_exports.object({});
|
|
24856
|
-
var engagementContract =
|
|
24946
|
+
var engagementContract = c12.router({
|
|
24857
24947
|
recordDashboardSession: {
|
|
24858
24948
|
method: "POST",
|
|
24859
24949
|
// `pathPrefix: '/v1'` is applied at the router level (see
|
|
@@ -24902,7 +24992,7 @@ var EnvironmentResponseSchema = external_exports.object({
|
|
|
24902
24992
|
applicationId: external_exports.uuid(),
|
|
24903
24993
|
organizationId: external_exports.uuid(),
|
|
24904
24994
|
name: external_exports.string(),
|
|
24905
|
-
primaryUrl: external_exports.string(),
|
|
24995
|
+
primaryUrl: external_exports.string().nullable(),
|
|
24906
24996
|
description: external_exports.string().nullable(),
|
|
24907
24997
|
isProduction: external_exports.boolean(),
|
|
24908
24998
|
createdAt: external_exports.date(),
|
|
@@ -24911,7 +25001,7 @@ var EnvironmentResponseSchema = external_exports.object({
|
|
|
24911
25001
|
var ListEnvironmentsResponseSchema = external_exports.array(EnvironmentResponseSchema);
|
|
24912
25002
|
var CreateEnvironmentRequestSchema = external_exports.object({
|
|
24913
25003
|
name: EnvNameSchema,
|
|
24914
|
-
primaryUrl: external_exports.url().max(2048),
|
|
25004
|
+
primaryUrl: external_exports.url().max(2048).optional(),
|
|
24915
25005
|
description: external_exports.string().max(1e3).optional(),
|
|
24916
25006
|
isProduction: external_exports.boolean().optional().default(false)
|
|
24917
25007
|
}).strict();
|
|
@@ -24923,8 +25013,8 @@ var UpdateEnvironmentRequestSchema = external_exports.object({
|
|
|
24923
25013
|
}).strict();
|
|
24924
25014
|
|
|
24925
25015
|
// ../../packages/api-contracts/src/contracts/v1/environment.ts
|
|
24926
|
-
var
|
|
24927
|
-
var environmentContract =
|
|
25016
|
+
var c13 = initContract();
|
|
25017
|
+
var environmentContract = c13.router({
|
|
24928
25018
|
listEnvironments: {
|
|
24929
25019
|
method: "GET",
|
|
24930
25020
|
path: "/organizations/:organizationId/applications/:applicationId/environments",
|
|
@@ -25174,8 +25264,8 @@ var GitHubRepoSchema = external_exports.object({
|
|
|
25174
25264
|
var ListGitHubInstallationReposResponseSchema = external_exports.array(GitHubRepoSchema);
|
|
25175
25265
|
|
|
25176
25266
|
// ../../packages/api-contracts/src/contracts/v1/github.ts
|
|
25177
|
-
var
|
|
25178
|
-
var githubContract =
|
|
25267
|
+
var c14 = initContract();
|
|
25268
|
+
var githubContract = c14.router({
|
|
25179
25269
|
// Tier chooser data: which app tiers this env can connect + the org's
|
|
25180
25270
|
// entitlement default. Pure read (auth context + server config).
|
|
25181
25271
|
getConnectOptions: {
|
|
@@ -25274,7 +25364,7 @@ var githubContract = c13.router({
|
|
|
25274
25364
|
method: "POST",
|
|
25275
25365
|
path: "/organizations/:organizationId/github/install-requests/:requestId/cancel",
|
|
25276
25366
|
pathParams: GitHubInstallRequestParamsSchema,
|
|
25277
|
-
body:
|
|
25367
|
+
body: c14.type(),
|
|
25278
25368
|
responses: {
|
|
25279
25369
|
200: GitHubInstallRequestSchema,
|
|
25280
25370
|
401: ErrorResponseSchema,
|
|
@@ -25285,7 +25375,7 @@ var githubContract = c13.router({
|
|
|
25285
25375
|
}
|
|
25286
25376
|
}
|
|
25287
25377
|
});
|
|
25288
|
-
var staffGithubContract =
|
|
25378
|
+
var staffGithubContract = c14.router({
|
|
25289
25379
|
listStaffInstallations: {
|
|
25290
25380
|
method: "GET",
|
|
25291
25381
|
path: "/staff/github/installations",
|
|
@@ -25328,8 +25418,8 @@ var ManagedInboxLabelParamsSchema = OrgIdParamsSchema.extend({
|
|
|
25328
25418
|
});
|
|
25329
25419
|
|
|
25330
25420
|
// ../../packages/api-contracts/src/contracts/v1/inbox.ts
|
|
25331
|
-
var
|
|
25332
|
-
var inboxContract =
|
|
25421
|
+
var c15 = initContract();
|
|
25422
|
+
var inboxContract = c15.router({
|
|
25333
25423
|
listInboxes: {
|
|
25334
25424
|
method: "GET",
|
|
25335
25425
|
path: "/organizations/:organizationId/inboxes",
|
|
@@ -25406,8 +25496,8 @@ var UpdateKnowledgeBaseResponseSchema = external_exports.object({
|
|
|
25406
25496
|
});
|
|
25407
25497
|
|
|
25408
25498
|
// ../../packages/api-contracts/src/contracts/v1/knowledge-base.ts
|
|
25409
|
-
var
|
|
25410
|
-
var knowledgeBaseContract =
|
|
25499
|
+
var c16 = initContract();
|
|
25500
|
+
var knowledgeBaseContract = c16.router({
|
|
25411
25501
|
getKnowledgeBase: {
|
|
25412
25502
|
method: "GET",
|
|
25413
25503
|
path: "/organizations/:organizationId/knowledge-base",
|
|
@@ -25628,8 +25718,8 @@ var UpdateRepoDocumentContentResponseSchema = external_exports.object({
|
|
|
25628
25718
|
});
|
|
25629
25719
|
|
|
25630
25720
|
// ../../packages/api-contracts/src/contracts/v1/knowledge-document.ts
|
|
25631
|
-
var
|
|
25632
|
-
var knowledgeDocumentContract =
|
|
25721
|
+
var c17 = initContract();
|
|
25722
|
+
var knowledgeDocumentContract = c17.router({
|
|
25633
25723
|
createDocument: {
|
|
25634
25724
|
method: "POST",
|
|
25635
25725
|
path: "/organizations/:organizationId/knowledge-documents",
|
|
@@ -25955,8 +26045,8 @@ var LinearMetadataResponseSchema = external_exports.object({
|
|
|
25955
26045
|
});
|
|
25956
26046
|
|
|
25957
26047
|
// ../../packages/api-contracts/src/contracts/v1/linear-integration.ts
|
|
25958
|
-
var
|
|
25959
|
-
var linearIntegrationContract =
|
|
26048
|
+
var c18 = initContract();
|
|
26049
|
+
var linearIntegrationContract = c18.router({
|
|
25960
26050
|
getLinearIntegration: {
|
|
25961
26051
|
method: "GET",
|
|
25962
26052
|
path: "/organizations/:organizationId/integrations/linear",
|
|
@@ -25974,7 +26064,7 @@ var linearIntegrationContract = c17.router({
|
|
|
25974
26064
|
method: "POST",
|
|
25975
26065
|
path: "/organizations/:organizationId/integrations/linear/connect",
|
|
25976
26066
|
pathParams: OrgIdParamsSchema,
|
|
25977
|
-
body:
|
|
26067
|
+
body: c18.noBody(),
|
|
25978
26068
|
responses: {
|
|
25979
26069
|
200: LinearConnectResponseSchema,
|
|
25980
26070
|
401: ErrorResponseSchema,
|
|
@@ -25989,7 +26079,7 @@ var linearIntegrationContract = c17.router({
|
|
|
25989
26079
|
method: "POST",
|
|
25990
26080
|
path: "/organizations/:organizationId/integrations/linear/disconnect",
|
|
25991
26081
|
pathParams: OrgIdParamsSchema,
|
|
25992
|
-
body:
|
|
26082
|
+
body: c18.noBody(),
|
|
25993
26083
|
responses: {
|
|
25994
26084
|
200: LinearIntegrationResponseSchema,
|
|
25995
26085
|
401: ErrorResponseSchema,
|
|
@@ -26151,8 +26241,8 @@ var LinearTicketContextResponseSchema = external_exports.object({
|
|
|
26151
26241
|
});
|
|
26152
26242
|
|
|
26153
26243
|
// ../../packages/api-contracts/src/contracts/v1/linear-tickets.ts
|
|
26154
|
-
var
|
|
26155
|
-
var linearTicketContract =
|
|
26244
|
+
var c19 = initContract();
|
|
26245
|
+
var linearTicketContract = c19.router({
|
|
26156
26246
|
/**
|
|
26157
26247
|
* Push one or more pentest findings to Linear as tickets. Customer-side
|
|
26158
26248
|
* (VIEW_RESULTS + PENTEST capability); non-admins create into the org's
|
|
@@ -26256,8 +26346,8 @@ var LlmProviderKeyResponseSchema = external_exports.object({
|
|
|
26256
26346
|
var ListLlmProviderKeysResponseSchema = external_exports.array(LlmProviderKeyResponseSchema);
|
|
26257
26347
|
|
|
26258
26348
|
// ../../packages/api-contracts/src/contracts/v1/llm-provider-key.ts
|
|
26259
|
-
var
|
|
26260
|
-
var llmProviderKeyContract =
|
|
26349
|
+
var c20 = initContract();
|
|
26350
|
+
var llmProviderKeyContract = c20.router({
|
|
26261
26351
|
createLlmProviderKey: {
|
|
26262
26352
|
method: "POST",
|
|
26263
26353
|
path: "/organizations/:organizationId/llm-provider-keys",
|
|
@@ -26451,8 +26541,8 @@ var LogoDeleteRequestSchema = external_exports.object({
|
|
|
26451
26541
|
});
|
|
26452
26542
|
|
|
26453
26543
|
// ../../packages/api-contracts/src/contracts/v1/organization.ts
|
|
26454
|
-
var
|
|
26455
|
-
var organizationContract =
|
|
26544
|
+
var c21 = initContract();
|
|
26545
|
+
var organizationContract = c21.router({
|
|
26456
26546
|
listOrganizations: {
|
|
26457
26547
|
method: "GET",
|
|
26458
26548
|
path: "/organizations",
|
|
@@ -26656,7 +26746,7 @@ var organizationContract = c20.router({
|
|
|
26656
26746
|
method: "POST",
|
|
26657
26747
|
path: "/organizations/:organizationId/logos-from-homepage",
|
|
26658
26748
|
pathParams: OrgIdParamsSchema,
|
|
26659
|
-
body:
|
|
26749
|
+
body: c21.type(),
|
|
26660
26750
|
responses: {
|
|
26661
26751
|
200: OrganizationResponseSchema,
|
|
26662
26752
|
// 400 — no homepage set on the organization.
|
|
@@ -27269,11 +27359,19 @@ var CustomerPentestDetailResponseSchema = CustomerPentestResponseSchema.extend({
|
|
|
27269
27359
|
* GET …/questionnaire. `.optional()` for rolling-deploy safety.
|
|
27270
27360
|
*/
|
|
27271
27361
|
questionnaireEditable: external_exports.boolean().optional(),
|
|
27272
|
-
hasQuestionnaireAnswers: external_exports.boolean().optional()
|
|
27362
|
+
hasQuestionnaireAnswers: external_exports.boolean().optional(),
|
|
27363
|
+
/**
|
|
27364
|
+
* True once the customer has submitted the questionnaire (frozen). Optional
|
|
27365
|
+
* for rolling-deploy safety against an older API that does not send it.
|
|
27366
|
+
*/
|
|
27367
|
+
questionnaireSubmitted: external_exports.boolean().optional()
|
|
27273
27368
|
});
|
|
27274
27369
|
var CustomerPentestQuestionnaireResponseSchema = external_exports.object({
|
|
27275
27370
|
pentestId: external_exports.uuid(),
|
|
27276
|
-
/**
|
|
27371
|
+
/**
|
|
27372
|
+
* True iff the engagement is still in a scoping stage AND the questionnaire
|
|
27373
|
+
* has not been submitted. A submitted intake is frozen even during scoping.
|
|
27374
|
+
*/
|
|
27277
27375
|
editable: external_exports.boolean(),
|
|
27278
27376
|
/**
|
|
27279
27377
|
* Lenient on unknown keys: during a rolling deploy the dashboard runs against
|
|
@@ -27282,7 +27380,13 @@ var CustomerPentestQuestionnaireResponseSchema = external_exports.object({
|
|
|
27282
27380
|
* strict — see the upsert request below.
|
|
27283
27381
|
*/
|
|
27284
27382
|
answers: PentestCustomerIntakeStoredAnswersSchema.nullable(),
|
|
27285
|
-
updatedAt: external_exports.coerce.date()
|
|
27383
|
+
updatedAt: external_exports.coerce.date(),
|
|
27384
|
+
/**
|
|
27385
|
+
* When the customer submitted (froze) the questionnaire. Null = still a
|
|
27386
|
+
* draft. Optional so an older API response still parses during a rolling
|
|
27387
|
+
* deploy; absence means "not submitted" to new clients.
|
|
27388
|
+
*/
|
|
27389
|
+
submittedAt: external_exports.coerce.date().nullable().optional()
|
|
27286
27390
|
});
|
|
27287
27391
|
var UpsertCustomerPentestQuestionnaireRequestSchema = external_exports.object({
|
|
27288
27392
|
/**
|
|
@@ -27292,6 +27396,14 @@ var UpsertCustomerPentestQuestionnaireRequestSchema = external_exports.object({
|
|
|
27292
27396
|
*/
|
|
27293
27397
|
answers: PentestCustomerIntakeWriteAnswersSchema.nullable()
|
|
27294
27398
|
}).strict();
|
|
27399
|
+
var SubmitCustomerPentestQuestionnaireRequestSchema = external_exports.object({
|
|
27400
|
+
/**
|
|
27401
|
+
* Optional last draft to persist atomically with the freeze. Omitted keeps
|
|
27402
|
+
* whatever is already stored. Retired keys are accepted and dropped, same
|
|
27403
|
+
* as the upsert path.
|
|
27404
|
+
*/
|
|
27405
|
+
answers: PentestCustomerIntakeWriteAnswersSchema.optional()
|
|
27406
|
+
}).strict();
|
|
27295
27407
|
var ReadPentestResponseSchema = external_exports.union([
|
|
27296
27408
|
PentestDetailResponseSchema,
|
|
27297
27409
|
CustomerPentestShellResponseSchema
|
|
@@ -27429,8 +27541,8 @@ var ScanReuseSuggestionsResponseSchema = external_exports.object({
|
|
|
27429
27541
|
});
|
|
27430
27542
|
|
|
27431
27543
|
// ../../packages/api-contracts/src/contracts/v1/pentest.ts
|
|
27432
|
-
var
|
|
27433
|
-
var pentestContract =
|
|
27544
|
+
var c22 = initContract();
|
|
27545
|
+
var pentestContract = c22.router({
|
|
27434
27546
|
listPentests: {
|
|
27435
27547
|
method: "GET",
|
|
27436
27548
|
path: "/organizations/:organizationId/pentests",
|
|
@@ -27507,6 +27619,21 @@ var pentestContract = c21.router({
|
|
|
27507
27619
|
500: ErrorResponseSchema
|
|
27508
27620
|
}
|
|
27509
27621
|
},
|
|
27622
|
+
submitCustomerPentestQuestionnaire: {
|
|
27623
|
+
method: "POST",
|
|
27624
|
+
path: "/organizations/:organizationId/customer-pentests/:pentestId/questionnaire/submit",
|
|
27625
|
+
pathParams: CustomerPentestIdParamsSchema,
|
|
27626
|
+
body: SubmitCustomerPentestQuestionnaireRequestSchema,
|
|
27627
|
+
responses: {
|
|
27628
|
+
200: CustomerPentestQuestionnaireResponseSchema,
|
|
27629
|
+
400: ErrorResponseSchema,
|
|
27630
|
+
401: ErrorResponseSchema,
|
|
27631
|
+
403: ErrorResponseSchema,
|
|
27632
|
+
404: ErrorResponseSchema,
|
|
27633
|
+
409: ErrorResponseSchema,
|
|
27634
|
+
500: ErrorResponseSchema
|
|
27635
|
+
}
|
|
27636
|
+
},
|
|
27510
27637
|
createPentest: {
|
|
27511
27638
|
method: "POST",
|
|
27512
27639
|
path: "/organizations/:organizationId/pentests",
|
|
@@ -27866,8 +27993,8 @@ var ReadAttestationDownloadResponseSchema = external_exports.union([
|
|
|
27866
27993
|
]);
|
|
27867
27994
|
|
|
27868
27995
|
// ../../packages/api-contracts/src/contracts/v1/pentest-attestation.ts
|
|
27869
|
-
var
|
|
27870
|
-
var pentestAttestationContract =
|
|
27996
|
+
var c23 = initContract();
|
|
27997
|
+
var pentestAttestationContract = c23.router({
|
|
27871
27998
|
getDefaults: {
|
|
27872
27999
|
method: "GET",
|
|
27873
28000
|
path: "/organizations/:organizationId/pentests/:pentestId/attestations/defaults",
|
|
@@ -28009,8 +28136,8 @@ var ListPentestAuditLogResponseSchema = external_exports.object({
|
|
|
28009
28136
|
});
|
|
28010
28137
|
|
|
28011
28138
|
// ../../packages/api-contracts/src/contracts/v1/pentest-audit-log.ts
|
|
28012
|
-
var
|
|
28013
|
-
var pentestAuditLogContract =
|
|
28139
|
+
var c24 = initContract();
|
|
28140
|
+
var pentestAuditLogContract = c24.router({
|
|
28014
28141
|
listAuditLog: {
|
|
28015
28142
|
method: "GET",
|
|
28016
28143
|
path: "/organizations/:organizationId/pentests/:pentestId/audit-log",
|
|
@@ -28026,6 +28153,86 @@ var pentestAuditLogContract = c23.router({
|
|
|
28026
28153
|
}
|
|
28027
28154
|
});
|
|
28028
28155
|
|
|
28156
|
+
// ../../packages/api-contracts/src/schemas/api/v1/pentest-authorized-domain.api.ts
|
|
28157
|
+
var PentestAuthorizedDomainIdParamsSchema = PentestIdParamsSchema.extend({
|
|
28158
|
+
pentestAuthorizedDomainId: external_exports.uuid()
|
|
28159
|
+
});
|
|
28160
|
+
var AuthorizedDomainOriginValues = ["DERIVED", "ENGAGEMENT"];
|
|
28161
|
+
var AuthorizedDomainOrigin = external_exports.enum(AuthorizedDomainOriginValues);
|
|
28162
|
+
var PentestAuthorizedDomainResponseSchema = external_exports.object({
|
|
28163
|
+
/**
|
|
28164
|
+
* NULL for a domain contributed by a bound application while the engagement is
|
|
28165
|
+
* still tracking — there is no row yet, and nothing to address by id.
|
|
28166
|
+
*/
|
|
28167
|
+
pentestAuthorizedDomainId: external_exports.uuid().nullable(),
|
|
28168
|
+
pentestId: external_exports.uuid(),
|
|
28169
|
+
organizationId: external_exports.uuid(),
|
|
28170
|
+
domain: external_exports.string(),
|
|
28171
|
+
applicationIds: external_exports.array(external_exports.uuid()),
|
|
28172
|
+
origin: AuthorizedDomainOrigin,
|
|
28173
|
+
/** NULL when the row was written by materialization rather than by a person. */
|
|
28174
|
+
addedById: external_exports.uuid().nullable(),
|
|
28175
|
+
addedAt: external_exports.date().nullable()
|
|
28176
|
+
});
|
|
28177
|
+
var PentestAuthorizedScopeResponseSchema = external_exports.object({
|
|
28178
|
+
domains: external_exports.array(PentestAuthorizedDomainResponseSchema),
|
|
28179
|
+
/** Null while the engagement still tracks its bound applications. */
|
|
28180
|
+
materializedAt: external_exports.date().nullable()
|
|
28181
|
+
});
|
|
28182
|
+
var CreatePentestAuthorizedDomainRequestSchema = external_exports.object({
|
|
28183
|
+
domain: external_exports.string().trim().min(1).max(253)
|
|
28184
|
+
}).strict();
|
|
28185
|
+
|
|
28186
|
+
// ../../packages/api-contracts/src/contracts/v1/pentest-authorized-domain.ts
|
|
28187
|
+
var c25 = initContract();
|
|
28188
|
+
var pentestAuthorizedDomainContract = c25.router({
|
|
28189
|
+
getPentestAuthorizedScope: {
|
|
28190
|
+
method: "GET",
|
|
28191
|
+
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope",
|
|
28192
|
+
pathParams: PentestIdParamsSchema,
|
|
28193
|
+
responses: {
|
|
28194
|
+
200: PentestAuthorizedScopeResponseSchema,
|
|
28195
|
+
401: ErrorResponseSchema,
|
|
28196
|
+
403: ErrorResponseSchema,
|
|
28197
|
+
404: ErrorResponseSchema,
|
|
28198
|
+
500: ErrorResponseSchema
|
|
28199
|
+
}
|
|
28200
|
+
},
|
|
28201
|
+
addPentestAuthorizedDomain: {
|
|
28202
|
+
method: "POST",
|
|
28203
|
+
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope/domains",
|
|
28204
|
+
pathParams: PentestIdParamsSchema,
|
|
28205
|
+
body: CreatePentestAuthorizedDomainRequestSchema,
|
|
28206
|
+
responses: {
|
|
28207
|
+
201: PentestAuthorizedDomainResponseSchema,
|
|
28208
|
+
// 400 = INVALID_DOMAIN (not a registrable domain / IP / bare suffix);
|
|
28209
|
+
// 409 = DOMAIN_ALREADY_AUTHORIZED or PENTEST_CLOSED.
|
|
28210
|
+
400: ErrorResponseSchema,
|
|
28211
|
+
401: ErrorResponseSchema,
|
|
28212
|
+
403: ErrorResponseSchema,
|
|
28213
|
+
404: ErrorResponseSchema,
|
|
28214
|
+
409: ErrorResponseSchema,
|
|
28215
|
+
500: ErrorResponseSchema
|
|
28216
|
+
}
|
|
28217
|
+
},
|
|
28218
|
+
removePentestAuthorizedDomain: {
|
|
28219
|
+
method: "DELETE",
|
|
28220
|
+
path: "/organizations/:organizationId/pentests/:pentestId/authorized-scope/domains/:pentestAuthorizedDomainId",
|
|
28221
|
+
pathParams: PentestAuthorizedDomainIdParamsSchema,
|
|
28222
|
+
responses: {
|
|
28223
|
+
204: DeleteResponseSchema,
|
|
28224
|
+
// 409 = DOMAIN_FROM_ENVIRONMENT (derived from a selected environment's
|
|
28225
|
+
// Target URL, so removing the row here would not remove it from scope) or
|
|
28226
|
+
// PENTEST_CLOSED.
|
|
28227
|
+
401: ErrorResponseSchema,
|
|
28228
|
+
403: ErrorResponseSchema,
|
|
28229
|
+
404: ErrorResponseSchema,
|
|
28230
|
+
409: ErrorResponseSchema,
|
|
28231
|
+
500: ErrorResponseSchema
|
|
28232
|
+
}
|
|
28233
|
+
}
|
|
28234
|
+
});
|
|
28235
|
+
|
|
28029
28236
|
// ../../packages/api-contracts/src/schemas/api/v1/pentest-engagement-exclusion.api.ts
|
|
28030
28237
|
var PentestEngagementExclusionsParamsSchema = OrgIdParamsSchema.extend({
|
|
28031
28238
|
pentestId: external_exports.string().min(1)
|
|
@@ -28051,8 +28258,8 @@ var CreatePentestEngagementExclusionRequestSchema = external_exports.object({
|
|
|
28051
28258
|
}).strict();
|
|
28052
28259
|
|
|
28053
28260
|
// ../../packages/api-contracts/src/contracts/v1/pentest-engagement-exclusion.ts
|
|
28054
|
-
var
|
|
28055
|
-
var pentestEngagementExclusionContract =
|
|
28261
|
+
var c26 = initContract();
|
|
28262
|
+
var pentestEngagementExclusionContract = c26.router({
|
|
28056
28263
|
listPentestEngagementExclusions: {
|
|
28057
28264
|
method: "GET",
|
|
28058
28265
|
path: "/organizations/:organizationId/pentests/:pentestId/engagement-exclusions",
|
|
@@ -28116,8 +28323,8 @@ var CreatePentestEnvironmentRequestSchema = external_exports.object({
|
|
|
28116
28323
|
}).strict();
|
|
28117
28324
|
|
|
28118
28325
|
// ../../packages/api-contracts/src/contracts/v1/pentest-environment.ts
|
|
28119
|
-
var
|
|
28120
|
-
var pentestEnvironmentContract =
|
|
28326
|
+
var c27 = initContract();
|
|
28327
|
+
var pentestEnvironmentContract = c27.router({
|
|
28121
28328
|
listPentestEnvironments: {
|
|
28122
28329
|
method: "GET",
|
|
28123
28330
|
path: "/organizations/:organizationId/pentests/:pentestId/environments",
|
|
@@ -28976,6 +29183,25 @@ var CurateFindingEvidenceRequestSchema = external_exports.object({
|
|
|
28976
29183
|
}).strict().refine((v2) => Object.keys(v2).length > 0, {
|
|
28977
29184
|
message: "At least one curation field must be provided"
|
|
28978
29185
|
});
|
|
29186
|
+
var MAX_STAFF_EVIDENCE_UPLOAD_BYTES = 256 * 1024 * 1024;
|
|
29187
|
+
var CreateFindingEvidenceUploadRequestSchema = external_exports.object({
|
|
29188
|
+
filename: external_exports.string().min(1).max(255),
|
|
29189
|
+
sizeBytes: external_exports.number().int().positive().max(MAX_STAFF_EVIDENCE_UPLOAD_BYTES)
|
|
29190
|
+
}).strict();
|
|
29191
|
+
var CreateFindingEvidenceUploadResponseSchema = external_exports.object({
|
|
29192
|
+
key: external_exports.string(),
|
|
29193
|
+
uploadUrl: external_exports.url(),
|
|
29194
|
+
expiresAt: external_exports.coerce.date(),
|
|
29195
|
+
kind: PentestExploitArtifactKind,
|
|
29196
|
+
mimeType: external_exports.string()
|
|
29197
|
+
});
|
|
29198
|
+
var AttachFindingEvidenceRequestSchema = external_exports.object({
|
|
29199
|
+
key: external_exports.string().min(1).max(1024),
|
|
29200
|
+
kind: PentestExploitArtifactKind.optional(),
|
|
29201
|
+
caption: external_exports.string().min(1).max(500).optional(),
|
|
29202
|
+
section: ValidationEvidenceSection.optional(),
|
|
29203
|
+
customerFacing: external_exports.boolean().optional()
|
|
29204
|
+
}).strict();
|
|
28979
29205
|
var PentestFindingRepositorySchema = external_exports.object({
|
|
28980
29206
|
repositoryId: external_exports.uuid(),
|
|
28981
29207
|
repositoryName: external_exports.string(),
|
|
@@ -29492,8 +29718,8 @@ var GetParseTaskStatusResponseSchema = external_exports.object({
|
|
|
29492
29718
|
});
|
|
29493
29719
|
|
|
29494
29720
|
// ../../packages/api-contracts/src/contracts/v1/pentest-finding.ts
|
|
29495
|
-
var
|
|
29496
|
-
var pentestFindingContract =
|
|
29721
|
+
var c28 = initContract();
|
|
29722
|
+
var pentestFindingContract = c28.router({
|
|
29497
29723
|
// ─── Findings ───
|
|
29498
29724
|
listFindings: {
|
|
29499
29725
|
method: "GET",
|
|
@@ -29582,6 +29808,43 @@ var pentestFindingContract = c26.router({
|
|
|
29582
29808
|
500: ErrorResponseSchema
|
|
29583
29809
|
}
|
|
29584
29810
|
},
|
|
29811
|
+
// ─── Evidence (staff manual attach) ───
|
|
29812
|
+
//
|
|
29813
|
+
// Two calls, because the bytes never pass through the api: mint a presigned
|
|
29814
|
+
// PUT, upload straight to S3, then register the object as an exhibit. That
|
|
29815
|
+
// keeps a screen-recorded PoC off the request path entirely (no body limit, no
|
|
29816
|
+
// request timeout, no api memory) and mirrors how the operator agent session
|
|
29817
|
+
// already attaches evidence.
|
|
29818
|
+
createFindingEvidenceUpload: {
|
|
29819
|
+
method: "POST",
|
|
29820
|
+
path: "/organizations/:organizationId/pentests/:pentestId/findings/:pentestFindingId/evidence/uploads",
|
|
29821
|
+
pathParams: PentestFindingIdParamsSchema,
|
|
29822
|
+
body: CreateFindingEvidenceUploadRequestSchema,
|
|
29823
|
+
responses: {
|
|
29824
|
+
201: CreateFindingEvidenceUploadResponseSchema,
|
|
29825
|
+
400: ErrorResponseSchema,
|
|
29826
|
+
401: ErrorResponseSchema,
|
|
29827
|
+
403: ErrorResponseSchema,
|
|
29828
|
+
404: ErrorResponseSchema,
|
|
29829
|
+
409: ErrorResponseSchema,
|
|
29830
|
+
500: ErrorResponseSchema
|
|
29831
|
+
}
|
|
29832
|
+
},
|
|
29833
|
+
attachFindingEvidence: {
|
|
29834
|
+
method: "POST",
|
|
29835
|
+
path: "/organizations/:organizationId/pentests/:pentestId/findings/:pentestFindingId/evidence",
|
|
29836
|
+
pathParams: PentestFindingIdParamsSchema,
|
|
29837
|
+
body: AttachFindingEvidenceRequestSchema,
|
|
29838
|
+
responses: {
|
|
29839
|
+
201: PentestExploitArtifactMetadataResponseSchema,
|
|
29840
|
+
400: ErrorResponseSchema,
|
|
29841
|
+
401: ErrorResponseSchema,
|
|
29842
|
+
403: ErrorResponseSchema,
|
|
29843
|
+
404: ErrorResponseSchema,
|
|
29844
|
+
409: ErrorResponseSchema,
|
|
29845
|
+
500: ErrorResponseSchema
|
|
29846
|
+
}
|
|
29847
|
+
},
|
|
29585
29848
|
curateFindingEvidence: {
|
|
29586
29849
|
method: "PATCH",
|
|
29587
29850
|
path: "/organizations/:organizationId/pentests/:pentestId/findings/:pentestFindingId/evidence/:artifactId",
|
|
@@ -29962,6 +30225,12 @@ var PentestHypothesisAttemptSummarySchema = external_exports.object({
|
|
|
29962
30225
|
status: PentestHypothesisAttemptStatus,
|
|
29963
30226
|
attemptOrdinal: external_exports.number().int().positive(),
|
|
29964
30227
|
conclusion: external_exports.string().nullable(),
|
|
30228
|
+
// Optional for rolling-deploy safety: web (Vercel) can deploy this schema before the
|
|
30229
|
+
// API sends the field, and web strictly `.parse()`s the response. Absent → undefined,
|
|
30230
|
+
// which the web serializer coalesces to null. Carries the Blocked/Failed reason so the
|
|
30231
|
+
// hypothesis drawer's verdict panel can show it when the deciding attempt is only in
|
|
30232
|
+
// hand as this summary (a verdict from a prior run).
|
|
30233
|
+
blockerReason: external_exports.string().nullable().optional(),
|
|
29965
30234
|
startedAt: external_exports.coerce.date().nullable(),
|
|
29966
30235
|
completedAt: external_exports.coerce.date().nullable(),
|
|
29967
30236
|
durationMs: external_exports.number().int().nonnegative().nullable(),
|
|
@@ -30082,8 +30351,8 @@ var PromotePentestHypothesisRequestSchema = external_exports.object({
|
|
|
30082
30351
|
}).strict().optional();
|
|
30083
30352
|
|
|
30084
30353
|
// ../../packages/api-contracts/src/contracts/v1/pentest-hypothesis.ts
|
|
30085
|
-
var
|
|
30086
|
-
var pentestHypothesisContract =
|
|
30354
|
+
var c29 = initContract();
|
|
30355
|
+
var pentestHypothesisContract = c29.router({
|
|
30087
30356
|
listHypotheses: {
|
|
30088
30357
|
method: "GET",
|
|
30089
30358
|
path: "/organizations/:organizationId/pentests/:pentestId/hypotheses",
|
|
@@ -30186,8 +30455,8 @@ var pentestHypothesisContract = c27.router({
|
|
|
30186
30455
|
});
|
|
30187
30456
|
|
|
30188
30457
|
// ../../packages/api-contracts/src/contracts/v1/pentest-manual-finding.ts
|
|
30189
|
-
var
|
|
30190
|
-
var pentestManualFindingContract =
|
|
30458
|
+
var c30 = initContract();
|
|
30459
|
+
var pentestManualFindingContract = c30.router({
|
|
30191
30460
|
listManualFindings: {
|
|
30192
30461
|
method: "GET",
|
|
30193
30462
|
path: "/organizations/:organizationId/pentests/:pentestId/manual-findings",
|
|
@@ -30274,8 +30543,8 @@ var pentestManualFindingContract = c28.router({
|
|
|
30274
30543
|
});
|
|
30275
30544
|
|
|
30276
30545
|
// ../../packages/api-contracts/src/contracts/v1/pentest-report-pdf.ts
|
|
30277
|
-
var
|
|
30278
|
-
var pentestReportPdfContract =
|
|
30546
|
+
var c31 = initContract();
|
|
30547
|
+
var pentestReportPdfContract = c31.router({
|
|
30279
30548
|
getCurrent: {
|
|
30280
30549
|
method: "GET",
|
|
30281
30550
|
path: "/organizations/:organizationId/pentests/:pentestId/report-pdf",
|
|
@@ -30368,7 +30637,7 @@ var pentestReportPdfContract = c29.router({
|
|
|
30368
30637
|
// No body: the render always reads current DB state (cover derived via
|
|
30369
30638
|
// deriveReportCover(), narrative/scope from the row's columns). The legacy
|
|
30370
30639
|
// dialog payload was retired with the Generate dialog (report-session RS5).
|
|
30371
|
-
body:
|
|
30640
|
+
body: c31.noBody(),
|
|
30372
30641
|
responses: {
|
|
30373
30642
|
202: StartReportPdfGenerationTaskResponseSchema,
|
|
30374
30643
|
400: ErrorResponseSchema,
|
|
@@ -30559,8 +30828,8 @@ var pentestReportPdfContract = c29.router({
|
|
|
30559
30828
|
});
|
|
30560
30829
|
|
|
30561
30830
|
// ../../packages/api-contracts/src/contracts/v1/pentest-validation.ts
|
|
30562
|
-
var
|
|
30563
|
-
var pentestValidationContract =
|
|
30831
|
+
var c32 = initContract();
|
|
30832
|
+
var pentestValidationContract = c32.router({
|
|
30564
30833
|
listValidationRuns: {
|
|
30565
30834
|
method: "GET",
|
|
30566
30835
|
path: "/organizations/:organizationId/pentests/:pentestId/validation-runs",
|
|
@@ -30668,8 +30937,8 @@ var pentestValidationContract = c30.router({
|
|
|
30668
30937
|
});
|
|
30669
30938
|
|
|
30670
30939
|
// ../../packages/api-contracts/src/contracts/v1/repository.ts
|
|
30671
|
-
var
|
|
30672
|
-
var repositoryContract =
|
|
30940
|
+
var c33 = initContract();
|
|
30941
|
+
var repositoryContract = c33.router({
|
|
30673
30942
|
createRepository: {
|
|
30674
30943
|
method: "POST",
|
|
30675
30944
|
path: "/organizations/:organizationId/repositories",
|
|
@@ -30826,7 +31095,7 @@ var repositoryContract = c31.router({
|
|
|
30826
31095
|
method: "POST",
|
|
30827
31096
|
path: "/organizations/:organizationId/repositories/scanning-branch/confirm-defaults",
|
|
30828
31097
|
pathParams: OrgIdParamsSchema,
|
|
30829
|
-
body:
|
|
31098
|
+
body: c33.noBody(),
|
|
30830
31099
|
responses: {
|
|
30831
31100
|
200: ConfirmScanningBranchDefaultsResponseSchema,
|
|
30832
31101
|
401: ErrorResponseSchema,
|
|
@@ -30960,8 +31229,8 @@ var ListScanLogsResponseSchema = external_exports.object({
|
|
|
30960
31229
|
});
|
|
30961
31230
|
|
|
30962
31231
|
// ../../packages/api-contracts/src/contracts/v1/scan.ts
|
|
30963
|
-
var
|
|
30964
|
-
var scanContract =
|
|
31232
|
+
var c34 = initContract();
|
|
31233
|
+
var scanContract = c34.router({
|
|
30965
31234
|
createScan: {
|
|
30966
31235
|
method: "POST",
|
|
30967
31236
|
path: "/organizations/:organizationId/scans",
|
|
@@ -31123,8 +31392,8 @@ var AttachTestIntegrationRequestSchema = external_exports.object({
|
|
|
31123
31392
|
}).strict();
|
|
31124
31393
|
|
|
31125
31394
|
// ../../packages/api-contracts/src/contracts/v1/test-integration.ts
|
|
31126
|
-
var
|
|
31127
|
-
var testIntegrationContract =
|
|
31395
|
+
var c35 = initContract();
|
|
31396
|
+
var testIntegrationContract = c35.router({
|
|
31128
31397
|
// -- Fixture CRUD (org-less, staff-only) ----------------------------------
|
|
31129
31398
|
listTestIntegrations: {
|
|
31130
31399
|
method: "GET",
|
|
@@ -31251,8 +31520,8 @@ var UpdateStaffProfileRequestSchema = external_exports.object({
|
|
|
31251
31520
|
});
|
|
31252
31521
|
|
|
31253
31522
|
// ../../packages/api-contracts/src/contracts/v1/user.ts
|
|
31254
|
-
var
|
|
31255
|
-
var userContract =
|
|
31523
|
+
var c36 = initContract();
|
|
31524
|
+
var userContract = c36.router({
|
|
31256
31525
|
getStaffProfile: {
|
|
31257
31526
|
method: "GET",
|
|
31258
31527
|
path: "/staff/profile",
|
|
@@ -31349,8 +31618,8 @@ var VantaIntegrationResponseSchema = external_exports.object({
|
|
|
31349
31618
|
});
|
|
31350
31619
|
|
|
31351
31620
|
// ../../packages/api-contracts/src/contracts/v1/vanta-integration.ts
|
|
31352
|
-
var
|
|
31353
|
-
var vantaIntegrationContract =
|
|
31621
|
+
var c37 = initContract();
|
|
31622
|
+
var vantaIntegrationContract = c37.router({
|
|
31354
31623
|
createVantaIntegration: {
|
|
31355
31624
|
method: "POST",
|
|
31356
31625
|
path: "/organizations/:organizationId/vanta-integration",
|
|
@@ -31682,8 +31951,8 @@ var VerifySharedVulnerabilityEmailCodeResponseSchema = external_exports.object({
|
|
|
31682
31951
|
});
|
|
31683
31952
|
|
|
31684
31953
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability.ts
|
|
31685
|
-
var
|
|
31686
|
-
var vulnerabilityContract =
|
|
31954
|
+
var c38 = initContract();
|
|
31955
|
+
var vulnerabilityContract = c38.router({
|
|
31687
31956
|
filterVulnerabilities: {
|
|
31688
31957
|
method: "POST",
|
|
31689
31958
|
path: "/organizations/:organizationId/vulnerabilities/filter",
|
|
@@ -31891,8 +32160,8 @@ var UpdateVulnerabilityNoteRequestSchema = external_exports.object({
|
|
|
31891
32160
|
});
|
|
31892
32161
|
|
|
31893
32162
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability-note.ts
|
|
31894
|
-
var
|
|
31895
|
-
var vulnerabilityNoteContract =
|
|
32163
|
+
var c39 = initContract();
|
|
32164
|
+
var vulnerabilityNoteContract = c39.router({
|
|
31896
32165
|
listNotes: {
|
|
31897
32166
|
method: "GET",
|
|
31898
32167
|
path: "/organizations/:organizationId/vulnerabilities/:vulnerabilityId/notes",
|
|
@@ -32073,8 +32342,8 @@ var ListWebhookDeliveriesResponseSchema = external_exports.object({
|
|
|
32073
32342
|
});
|
|
32074
32343
|
|
|
32075
32344
|
// ../../packages/api-contracts/src/contracts/v1/webhook-settings.ts
|
|
32076
|
-
var
|
|
32077
|
-
var webhookSettingsContract =
|
|
32345
|
+
var c40 = initContract();
|
|
32346
|
+
var webhookSettingsContract = c40.router({
|
|
32078
32347
|
listWebhookEndpoints: {
|
|
32079
32348
|
method: "GET",
|
|
32080
32349
|
path: "/organizations/:organizationId/webhook-settings/endpoints",
|
|
@@ -32212,11 +32481,12 @@ var webhookSettingsContract = c38.router({
|
|
|
32212
32481
|
});
|
|
32213
32482
|
|
|
32214
32483
|
// ../../packages/api-contracts/src/contracts/v1/index.ts
|
|
32215
|
-
var
|
|
32216
|
-
var v1Contract =
|
|
32484
|
+
var c41 = initContract();
|
|
32485
|
+
var v1Contract = c41.router(
|
|
32217
32486
|
{
|
|
32218
32487
|
admin: adminContract,
|
|
32219
32488
|
cloudIntegration: cloudIntegrationContract,
|
|
32489
|
+
codeSize: codeSizeContract,
|
|
32220
32490
|
scan: scanContract,
|
|
32221
32491
|
organization: organizationContract,
|
|
32222
32492
|
user: userContract,
|
|
@@ -32243,6 +32513,7 @@ var v1Contract = c39.router(
|
|
|
32243
32513
|
pentestAuditLog: pentestAuditLogContract,
|
|
32244
32514
|
pentestEnvironment: pentestEnvironmentContract,
|
|
32245
32515
|
pentestEngagementExclusion: pentestEngagementExclusionContract,
|
|
32516
|
+
pentestAuthorizedDomain: pentestAuthorizedDomainContract,
|
|
32246
32517
|
pentestFinding: pentestFindingContract,
|
|
32247
32518
|
pentestHypothesis: pentestHypothesisContract,
|
|
32248
32519
|
pentestValidation: pentestValidationContract,
|
|
@@ -32261,8 +32532,8 @@ var v1Contract = c39.router(
|
|
|
32261
32532
|
);
|
|
32262
32533
|
|
|
32263
32534
|
// ../../packages/api-contracts/src/contracts/index.ts
|
|
32264
|
-
var
|
|
32265
|
-
var contract =
|
|
32535
|
+
var c42 = initContract();
|
|
32536
|
+
var contract = c42.router({
|
|
32266
32537
|
v1: v1Contract
|
|
32267
32538
|
});
|
|
32268
32539
|
|
|
@@ -32311,7 +32582,7 @@ var ComplianceRegimeValues = [
|
|
|
32311
32582
|
var ComplianceRegime = external_exports.enum(ComplianceRegimeValues);
|
|
32312
32583
|
|
|
32313
32584
|
// ../../packages/api-contracts/src/contracts/v1/agent-session-internal.ts
|
|
32314
|
-
var
|
|
32585
|
+
var c43 = initContract();
|
|
32315
32586
|
var AgentSessionInternalParamsSchema = external_exports.object({
|
|
32316
32587
|
agentSessionId: external_exports.uuid()
|
|
32317
32588
|
});
|
|
@@ -33166,7 +33437,7 @@ var ReportUpdateScopeRequestSchema = external_exports.object({
|
|
|
33166
33437
|
expectedUpdatedAt: reportExpectedUpdatedAt,
|
|
33167
33438
|
rows: external_exports.array(ScopeRowSchema).max(100)
|
|
33168
33439
|
});
|
|
33169
|
-
var agentSessionInternalContract =
|
|
33440
|
+
var agentSessionInternalContract = c43.router({
|
|
33170
33441
|
postEvents: {
|
|
33171
33442
|
method: "POST",
|
|
33172
33443
|
path: "/internal/v1/agent-sessions/:agentSessionId/events",
|
|
@@ -33866,8 +34137,8 @@ var GitHubWebhookResponseSchema = external_exports.object({
|
|
|
33866
34137
|
});
|
|
33867
34138
|
|
|
33868
34139
|
// ../../packages/api-contracts/src/contracts/webhooks/github.ts
|
|
33869
|
-
var
|
|
33870
|
-
var githubWebhookContract =
|
|
34140
|
+
var c44 = initContract();
|
|
34141
|
+
var githubWebhookContract = c44.router(
|
|
33871
34142
|
{
|
|
33872
34143
|
handleWebhook: {
|
|
33873
34144
|
method: "POST",
|
|
@@ -33885,7 +34156,7 @@ var githubWebhookContract = c42.router(
|
|
|
33885
34156
|
pathPrefix: "/webhooks"
|
|
33886
34157
|
}
|
|
33887
34158
|
);
|
|
33888
|
-
var githubReadonlyWebhookContract =
|
|
34159
|
+
var githubReadonlyWebhookContract = c44.router(
|
|
33889
34160
|
{
|
|
33890
34161
|
handleWebhook: {
|
|
33891
34162
|
method: "POST",
|
|
@@ -33905,9 +34176,9 @@ var githubReadonlyWebhookContract = c42.router(
|
|
|
33905
34176
|
);
|
|
33906
34177
|
|
|
33907
34178
|
// ../../packages/api-contracts/src/contracts/webhooks/linear.ts
|
|
33908
|
-
var
|
|
34179
|
+
var c45 = initContract();
|
|
33909
34180
|
var LinearWebhookResponseSchema = external_exports.object({ ok: external_exports.boolean() });
|
|
33910
|
-
var linearWebhookContract =
|
|
34181
|
+
var linearWebhookContract = c45.router(
|
|
33911
34182
|
{
|
|
33912
34183
|
handleWebhook: {
|
|
33913
34184
|
method: "POST",
|
|
@@ -33927,7 +34198,7 @@ var linearWebhookContract = c43.router(
|
|
|
33927
34198
|
);
|
|
33928
34199
|
|
|
33929
34200
|
// ../../packages/api-contracts/src/contracts/forge/bitbucket.ts
|
|
33930
|
-
var
|
|
34201
|
+
var c46 = initContract();
|
|
33931
34202
|
var InstallEventSchema = external_exports.object({
|
|
33932
34203
|
eventType: external_exports.enum(["avi:forge:installed:app", "avi:forge:upgraded:app"]),
|
|
33933
34204
|
context: external_exports.object({ cloudId: external_exports.string().min(1) }).loose(),
|
|
@@ -33956,7 +34227,7 @@ var ForgePairingCodeResponseSchema = external_exports.discriminatedUnion("state"
|
|
|
33956
34227
|
expiresInSeconds: external_exports.number().int()
|
|
33957
34228
|
})
|
|
33958
34229
|
]);
|
|
33959
|
-
var forgeBitbucketContract =
|
|
34230
|
+
var forgeBitbucketContract = c46.router(
|
|
33960
34231
|
{
|
|
33961
34232
|
lifecycle: {
|
|
33962
34233
|
method: "POST",
|
|
@@ -34003,8 +34274,8 @@ var HealthResponseSchema = external_exports.object({
|
|
|
34003
34274
|
});
|
|
34004
34275
|
|
|
34005
34276
|
// ../../packages/api-contracts/src/contracts/health.ts
|
|
34006
|
-
var
|
|
34007
|
-
var healthContract =
|
|
34277
|
+
var c47 = initContract();
|
|
34278
|
+
var healthContract = c47.router({
|
|
34008
34279
|
getHealth: {
|
|
34009
34280
|
method: "GET",
|
|
34010
34281
|
path: "/health",
|
|
@@ -34016,8 +34287,8 @@ var healthContract = c45.router({
|
|
|
34016
34287
|
});
|
|
34017
34288
|
|
|
34018
34289
|
// ../../packages/api-contracts/src/contracts/v1/vulnerability-share.ts
|
|
34019
|
-
var
|
|
34020
|
-
var vulnerabilityShareContract =
|
|
34290
|
+
var c48 = initContract();
|
|
34291
|
+
var vulnerabilityShareContract = c48.router(
|
|
34021
34292
|
{
|
|
34022
34293
|
resolveShareLink: {
|
|
34023
34294
|
method: "GET",
|
|
@@ -34104,8 +34375,8 @@ var UpdatePrVulnerabilityRequestSchema = external_exports.object({
|
|
|
34104
34375
|
});
|
|
34105
34376
|
|
|
34106
34377
|
// ../../packages/api-contracts/src/contracts/v1/pr-vulnerability.ts
|
|
34107
|
-
var
|
|
34108
|
-
var prVulnerabilityContract =
|
|
34378
|
+
var c49 = initContract();
|
|
34379
|
+
var prVulnerabilityContract = c49.router(
|
|
34109
34380
|
{
|
|
34110
34381
|
listPrVulnerabilities: {
|
|
34111
34382
|
method: "GET",
|
|
@@ -36658,12 +36929,12 @@ function buildApplicationsTable(apps) {
|
|
|
36658
36929
|
repos: String(a.repositories.length),
|
|
36659
36930
|
url: a.applicationUrl ? sanitizeDisplay(a.applicationUrl) : "\u2014"
|
|
36660
36931
|
}));
|
|
36661
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
36662
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
36663
|
-
const typeWidth = Math.max(4, ...cells.map((
|
|
36932
|
+
const idWidth = Math.max(2, ...cells.map((c51) => c51.id.length));
|
|
36933
|
+
const nameWidth = Math.max(4, ...cells.map((c51) => c51.name.length));
|
|
36934
|
+
const typeWidth = Math.max(4, ...cells.map((c51) => c51.type.length));
|
|
36664
36935
|
const header = `${"ID".padEnd(idWidth)} ${"NAME".padEnd(nameWidth)} ${"TYPE".padEnd(typeWidth)} REPOS URL`;
|
|
36665
36936
|
const rows = cells.map(
|
|
36666
|
-
(
|
|
36937
|
+
(c51) => `${c51.id.padEnd(idWidth)} ${c51.name.padEnd(nameWidth)} ${c51.type.padEnd(typeWidth)} ${c51.repos.padStart(5)} ${c51.url}`
|
|
36667
36938
|
);
|
|
36668
36939
|
return { header, rows };
|
|
36669
36940
|
}
|
|
@@ -36683,12 +36954,12 @@ function buildApplicationRepositoriesTable(links) {
|
|
|
36683
36954
|
path: l.repositoryPath ? sanitizeDisplay(l.repositoryPath) : "\u2014",
|
|
36684
36955
|
status: formatStatus(l.repositoryStatus)
|
|
36685
36956
|
}));
|
|
36686
|
-
const nameWidth = Math.max(10, ...cells.map((
|
|
36687
|
-
const roleWidth = Math.max(4, ...cells.map((
|
|
36688
|
-
const pathWidth = Math.max(4, ...cells.map((
|
|
36957
|
+
const nameWidth = Math.max(10, ...cells.map((c51) => c51.name.length));
|
|
36958
|
+
const roleWidth = Math.max(4, ...cells.map((c51) => c51.role.length));
|
|
36959
|
+
const pathWidth = Math.max(4, ...cells.map((c51) => c51.path.length));
|
|
36689
36960
|
const header = `${"REPOSITORY".padEnd(nameWidth)} SCAN ${"ROLE".padEnd(roleWidth)} ${"PATH".padEnd(pathWidth)} STATUS`;
|
|
36690
36961
|
const rows = cells.map(
|
|
36691
|
-
(
|
|
36962
|
+
(c51) => `${c51.name.padEnd(nameWidth)} ${c51.scan.padEnd(4)} ${c51.role.padEnd(roleWidth)} ${c51.path.padEnd(pathWidth)} ${c51.status}`
|
|
36692
36963
|
);
|
|
36693
36964
|
return { header, rows };
|
|
36694
36965
|
}
|
|
@@ -37800,14 +38071,14 @@ var yt = (t) => {
|
|
|
37800
38071
|
};
|
|
37801
38072
|
var ee = (t, r, s, i, u) => {
|
|
37802
38073
|
let n = r, o = 0;
|
|
37803
|
-
for (let
|
|
37804
|
-
const a = t[
|
|
38074
|
+
for (let c51 = s; c51 < i; c51++) {
|
|
38075
|
+
const a = t[c51];
|
|
37805
38076
|
if (n = n - a.length, o++, n <= u) break;
|
|
37806
38077
|
}
|
|
37807
38078
|
return { lineCount: n, removals: o };
|
|
37808
38079
|
};
|
|
37809
38080
|
var Y2 = ({ cursor: t, options: r, style: s, output: i = process.stdout, maxItems: u = Number.POSITIVE_INFINITY, columnPadding: n = 0, rowPadding: o = 4 }) => {
|
|
37810
|
-
const
|
|
38081
|
+
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);
|
|
37811
38082
|
let p2 = 0;
|
|
37812
38083
|
t >= y - 3 && (p2 = Math.max(Math.min(t - y + 3, r.length - y), 0));
|
|
37813
38084
|
let m = y < r.length && p2 > 0, g = y < r.length && p2 + y < r.length;
|
|
@@ -37816,7 +38087,7 @@ var Y2 = ({ cursor: t, options: r, style: s, output: i = process.stdout, maxItem
|
|
|
37816
38087
|
m && f++, g && f++;
|
|
37817
38088
|
const v2 = p2 + (m ? 1 : 0), T = S2 - (g ? 1 : 0);
|
|
37818
38089
|
for (let b2 = v2; b2 < T; b2++) {
|
|
37819
|
-
const G2 = wrapAnsi(s(r[b2], b2 === t),
|
|
38090
|
+
const G2 = wrapAnsi(s(r[b2], b2 === t), c51, { hard: true, trim: false }).split(`
|
|
37820
38091
|
`);
|
|
37821
38092
|
h2.push(G2), f += G2.length;
|
|
37822
38093
|
}
|
|
@@ -37833,22 +38104,22 @@ var Y2 = ({ cursor: t, options: r, style: s, output: i = process.stdout, maxItem
|
|
|
37833
38104
|
var ue = (t) => {
|
|
37834
38105
|
const r = t.active ?? "Yes", s = t.inactive ?? "No";
|
|
37835
38106
|
return new X({ active: r, inactive: s, signal: t.signal, input: t.input, output: t.output, initialValue: t.initialValue ?? true, render() {
|
|
37836
|
-
const i = t.withGuide ?? h.withGuide, u = `${M(this.state)} `, n = i ? `${e("gray", $)} ` : "", o = W(t.output, t.message, n, u),
|
|
38107
|
+
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", $)}
|
|
37837
38108
|
` : ""}${o}
|
|
37838
38109
|
`, a = this.value ? r : s;
|
|
37839
38110
|
switch (this.state) {
|
|
37840
38111
|
case "submit": {
|
|
37841
38112
|
const l = i ? `${e("gray", $)} ` : "";
|
|
37842
|
-
return `${
|
|
38113
|
+
return `${c51}${l}${e("dim", a)}`;
|
|
37843
38114
|
}
|
|
37844
38115
|
case "cancel": {
|
|
37845
38116
|
const l = i ? `${e("gray", $)} ` : "";
|
|
37846
|
-
return `${
|
|
38117
|
+
return `${c51}${l}${e(["strikethrough", "dim"], a)}${i ? `
|
|
37847
38118
|
${e("gray", $)}` : ""}`;
|
|
37848
38119
|
}
|
|
37849
38120
|
default: {
|
|
37850
38121
|
const l = i ? `${e("cyan", $)} ` : "", d2 = i ? e("cyan", E2) : "";
|
|
37851
|
-
return `${
|
|
38122
|
+
return `${c51}${l}${this.value ? `${e("green", z4)} ${r}` : `${e("dim", H)} ${e("dim", r)}`}${t.vertical ? i ? `
|
|
37852
38123
|
${e("cyan", $)} ` : `
|
|
37853
38124
|
` : ` ${e("dim", "/")} `}${this.value ? `${e("dim", H)} ${e("dim", s)}` : `${e("green", z4)} ${s}`}
|
|
37854
38125
|
${d2}
|
|
@@ -37870,21 +38141,21 @@ var fe = (t) => new rt({ validate: t.validate, placeholder: t.placeholder, defau
|
|
|
37870
38141
|
${e(this.focused === "submit" ? "cyan" : "dim", "[ submit ]")}` : "";
|
|
37871
38142
|
switch (this.state) {
|
|
37872
38143
|
case "error": {
|
|
37873
|
-
const
|
|
38144
|
+
const c51 = `${e("yellow", $)} `, a = r ? W(t.output, u, c51, void 0) : u, l = e("yellow", E2);
|
|
37874
38145
|
return `${s}${a}
|
|
37875
38146
|
${l} ${e("yellow", this.error)}${o}
|
|
37876
38147
|
`;
|
|
37877
38148
|
}
|
|
37878
38149
|
case "submit": {
|
|
37879
|
-
const
|
|
38150
|
+
const c51 = `${e("gray", $)} `, a = r ? W(t.output, n, c51, void 0, (l) => e("dim", l)) : n ? e("dim", n) : "";
|
|
37880
38151
|
return `${s}${a}`;
|
|
37881
38152
|
}
|
|
37882
38153
|
case "cancel": {
|
|
37883
|
-
const
|
|
38154
|
+
const c51 = `${e("gray", $)} `, a = r ? W(t.output, n, c51, void 0, (l) => e(["strikethrough", "dim"], l)) : n ? e(["strikethrough", "dim"], n) : "";
|
|
37884
38155
|
return `${s}${a}`;
|
|
37885
38156
|
}
|
|
37886
38157
|
default: {
|
|
37887
|
-
const
|
|
38158
|
+
const c51 = r ? `${e("cyan", $)} ` : "", a = r ? e("cyan", E2) : "", l = r ? W(t.output, u, c51) : u;
|
|
37888
38159
|
return `${s}${l}
|
|
37889
38160
|
${a}${o}
|
|
37890
38161
|
`;
|
|
@@ -37905,7 +38176,7 @@ ${e("reset", e("dim", `Press ${e(["gray", "bgWhite", "inverse"], " space ")} to
|
|
|
37905
38176
|
}, render() {
|
|
37906
38177
|
const i = t.withGuide ?? h.withGuide, u = W(t.output, t.message, i ? `${yt(this.state)} ` : "", `${M(this.state)} `), n = `${i ? `${e("gray", $)}
|
|
37907
38178
|
` : ""}${u}
|
|
37908
|
-
`, o = this.value ?? [],
|
|
38179
|
+
`, o = this.value ?? [], c51 = (a, l) => {
|
|
37909
38180
|
if (a.disabled) return r(a, "disabled");
|
|
37910
38181
|
const d2 = o.includes(a.value);
|
|
37911
38182
|
return l && d2 ? r(a, "active-selected") : d2 ? r(a, "selected") : r(a, l ? "active" : "inactive");
|
|
@@ -37928,7 +38199,7 @@ ${e("gray", $)}` : ""}`;
|
|
|
37928
38199
|
`), d2 = n.split(`
|
|
37929
38200
|
`).length, y = l.split(`
|
|
37930
38201
|
`).length + 1;
|
|
37931
|
-
return `${n}${a}${Y2({ output: t.output, options: this.options, cursor: this.cursor, maxItems: t.maxItems, columnPadding: a.length, rowPadding: d2 + y, style:
|
|
38202
|
+
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(`
|
|
37932
38203
|
${a}`)}
|
|
37933
38204
|
${l}
|
|
37934
38205
|
`;
|
|
@@ -37936,7 +38207,7 @@ ${l}
|
|
|
37936
38207
|
default: {
|
|
37937
38208
|
const a = i ? `${e("cyan", $)} ` : "", l = n.split(`
|
|
37938
38209
|
`).length, d2 = i ? 2 : 1;
|
|
37939
|
-
return `${n}${a}${Y2({ output: t.output, options: this.options, cursor: this.cursor, maxItems: t.maxItems, columnPadding: a.length, rowPadding: l + d2, style:
|
|
38210
|
+
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(`
|
|
37940
38211
|
${a}`)}
|
|
37941
38212
|
${i ? e("cyan", E2) : ""}
|
|
37942
38213
|
`;
|
|
@@ -37950,9 +38221,9 @@ var Ce = (t) => new ot({ validate: t.validate, mask: t.mask ?? Gt, signal: t.sig
|
|
|
37950
38221
|
`, i = this.userInputWithCursor, u = this.masked;
|
|
37951
38222
|
switch (this.state) {
|
|
37952
38223
|
case "error": {
|
|
37953
|
-
const n = r ? `${e("yellow", $)} ` : "", o = r ? `${e("yellow", E2)} ` : "",
|
|
38224
|
+
const n = r ? `${e("yellow", $)} ` : "", o = r ? `${e("yellow", E2)} ` : "", c51 = u ?? "";
|
|
37954
38225
|
return t.clearOnError && this.clear(), `${s.trim()}
|
|
37955
|
-
${n}${
|
|
38226
|
+
${n}${c51}
|
|
37956
38227
|
${o}${e("yellow", this.error)}
|
|
37957
38228
|
`;
|
|
37958
38229
|
}
|
|
@@ -38000,19 +38271,19 @@ var Ee = (t) => {
|
|
|
38000
38271
|
`;
|
|
38001
38272
|
switch (this.state) {
|
|
38002
38273
|
case "submit": {
|
|
38003
|
-
const
|
|
38274
|
+
const c51 = s ? `${e("gray", $)} ` : "", a = W(t.output, r(this.options[this.cursor], "selected"), c51);
|
|
38004
38275
|
return `${o}${a}`;
|
|
38005
38276
|
}
|
|
38006
38277
|
case "cancel": {
|
|
38007
|
-
const
|
|
38278
|
+
const c51 = s ? `${e("gray", $)} ` : "", a = W(t.output, r(this.options[this.cursor], "cancelled"), c51);
|
|
38008
38279
|
return `${o}${a}${s ? `
|
|
38009
38280
|
${e("gray", $)}` : ""}`;
|
|
38010
38281
|
}
|
|
38011
38282
|
default: {
|
|
38012
|
-
const
|
|
38283
|
+
const c51 = s ? `${e("cyan", $)} ` : "", a = s ? e("cyan", E2) : "", l = o.split(`
|
|
38013
38284
|
`).length, d2 = s ? 2 : 1;
|
|
38014
|
-
return `${o}${
|
|
38015
|
-
${
|
|
38285
|
+
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(`
|
|
38286
|
+
${c51}`)}
|
|
38016
38287
|
${a}
|
|
38017
38288
|
`;
|
|
38018
38289
|
}
|
|
@@ -38760,17 +39031,205 @@ function showBanner() {
|
|
|
38760
39031
|
`);
|
|
38761
39032
|
}
|
|
38762
39033
|
|
|
38763
|
-
// src/
|
|
38764
|
-
function
|
|
38765
|
-
|
|
38766
|
-
|
|
39034
|
+
// src/code-size/format.ts
|
|
39035
|
+
function formatCount(value) {
|
|
39036
|
+
return value.toLocaleString("en-US");
|
|
39037
|
+
}
|
|
39038
|
+
function repoDisplayName(repositoryUrl) {
|
|
39039
|
+
try {
|
|
39040
|
+
const path = new URL(repositoryUrl).pathname.replace(/^\//, "").replace(/\.git$/, "");
|
|
39041
|
+
return path || repositoryUrl;
|
|
39042
|
+
} catch {
|
|
39043
|
+
return repositoryUrl;
|
|
39044
|
+
}
|
|
39045
|
+
}
|
|
39046
|
+
function countedRows(totals) {
|
|
39047
|
+
const b2 = totals.buckets;
|
|
39048
|
+
return [
|
|
39049
|
+
{ label: "Billable code", value: b2.code.code },
|
|
39050
|
+
{ label: "Blank & comment lines in billable files", value: b2.code.lines - b2.code.code },
|
|
39051
|
+
{ label: "Tests", value: b2.tests.lines },
|
|
39052
|
+
{ label: "Documentation", value: b2.docs.lines },
|
|
39053
|
+
{ label: "Configuration & data", value: b2.config_data.lines },
|
|
39054
|
+
{ label: "Vendored & generated", value: b2.vendored_generated.lines }
|
|
39055
|
+
];
|
|
39056
|
+
}
|
|
39057
|
+
function countedTotal(totals) {
|
|
39058
|
+
return countedRows(totals).reduce((sum, row) => sum + row.value, 0);
|
|
39059
|
+
}
|
|
39060
|
+
function padValues(rows) {
|
|
39061
|
+
const formatted = rows.map((row) => formatCount(row.value));
|
|
39062
|
+
const labelWidth = Math.max(...rows.map((row) => row.label.length));
|
|
39063
|
+
const valueWidth = Math.max(...formatted.map((value) => value.length));
|
|
39064
|
+
return rows.map(
|
|
39065
|
+
(row, i) => ` ${row.label.padEnd(labelWidth)} ${(formatted[i] ?? "").padStart(valueWidth)}`
|
|
39066
|
+
);
|
|
39067
|
+
}
|
|
39068
|
+
function renderCodeSizeTable(codeSize, options) {
|
|
39069
|
+
const { repositories, totals } = codeSize;
|
|
39070
|
+
const measured = repositories.filter((repo) => repo.billableSloc !== null);
|
|
39071
|
+
const lines = [`Code size for ${options.orgSlug}`, ""];
|
|
39072
|
+
if (measured.length === 0) {
|
|
39073
|
+
lines.push(
|
|
39074
|
+
" No measurements yet.",
|
|
39075
|
+
` ${formatCount(repositories.length)} connected ${plural(repositories.length, "repository has", "repositories have")} not been measured.`
|
|
39076
|
+
);
|
|
39077
|
+
return lines;
|
|
39078
|
+
}
|
|
39079
|
+
lines.push(
|
|
39080
|
+
` ${formatCount(totals.billableSloc)} billable SLOC`,
|
|
39081
|
+
` of ${formatCount(totals.rawLines)} total lines across ${formatCount(measured.length)} measured ${plural(measured.length, "repository", "repositories")}`
|
|
39082
|
+
);
|
|
39083
|
+
const unmeasured = repositories.length - measured.length;
|
|
39084
|
+
if (unmeasured > 0) {
|
|
39085
|
+
lines.push(
|
|
39086
|
+
` ${formatCount(unmeasured)} connected ${plural(unmeasured, "repository is", "repositories are")} not measured yet and not included`
|
|
39087
|
+
);
|
|
39088
|
+
}
|
|
39089
|
+
lines.push("", "What's counted", ...padValues(countedRows(totals)));
|
|
39090
|
+
const counted = countedTotal(totals);
|
|
39091
|
+
if (counted !== totals.rawLines) {
|
|
39092
|
+
lines.push(
|
|
39093
|
+
` These sum to ${formatCount(counted)}, not the ${formatCount(totals.rawLines)} above.`,
|
|
39094
|
+
" Some measurement predates the current counting rules; re-measure to reconcile."
|
|
39095
|
+
);
|
|
39096
|
+
}
|
|
39097
|
+
lines.push("", "By repository");
|
|
39098
|
+
const shown = measured.slice(0, options.repoLimit);
|
|
39099
|
+
lines.push(
|
|
39100
|
+
...padValues(
|
|
39101
|
+
shown.map((repo) => ({
|
|
39102
|
+
label: repoDisplayName(repo.repositoryUrl),
|
|
39103
|
+
value: repo.billableSloc ?? 0
|
|
39104
|
+
}))
|
|
39105
|
+
)
|
|
39106
|
+
);
|
|
39107
|
+
const hidden = measured.length - shown.length;
|
|
39108
|
+
if (hidden > 0) {
|
|
39109
|
+
lines.push(` ... ${formatCount(hidden)} more`);
|
|
39110
|
+
}
|
|
39111
|
+
return lines;
|
|
39112
|
+
}
|
|
39113
|
+
function renderCodeSizeTsv(codeSize) {
|
|
39114
|
+
return [
|
|
39115
|
+
"repository billableSloc",
|
|
39116
|
+
...codeSize.repositories.map(
|
|
39117
|
+
(repo) => `${repoDisplayName(repo.repositoryUrl)} ${repo.billableSloc === null ? "" : repo.billableSloc}`
|
|
39118
|
+
)
|
|
39119
|
+
];
|
|
39120
|
+
}
|
|
39121
|
+
function plural(count, one, many) {
|
|
39122
|
+
return count === 1 ? one : many;
|
|
39123
|
+
}
|
|
39124
|
+
|
|
39125
|
+
// src/code-size/commands.ts
|
|
39126
|
+
var DEFAULT_REPO_LIMIT = 20;
|
|
39127
|
+
var OUTPUT_FORMATS = ["table", "json", "tsv"];
|
|
39128
|
+
function isOutputFormat(value) {
|
|
39129
|
+
return OUTPUT_FORMATS.includes(value);
|
|
39130
|
+
}
|
|
39131
|
+
function parseRepoLimit(value) {
|
|
39132
|
+
if (!/^\d+$/.test(value.trim())) {
|
|
39133
|
+
console.error("--repos must be a non-negative whole number (0 shows every repository).");
|
|
39134
|
+
process.exit(1);
|
|
39135
|
+
}
|
|
39136
|
+
return Number.parseInt(value, 10);
|
|
39137
|
+
}
|
|
39138
|
+
function createCodeSizeCommand() {
|
|
39139
|
+
return new Command("code-size").description("Show the organization's billable lines of code").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").option(
|
|
39140
|
+
"-n, --repos <count>",
|
|
39141
|
+
`Per-repository rows to show in table output (default: ${DEFAULT_REPO_LIMIT}, 0 for all)`,
|
|
39142
|
+
parseRepoLimit
|
|
39143
|
+
).option("-w, --web", "Open the code size panel in a browser").addHelpText(
|
|
39144
|
+
"after",
|
|
39145
|
+
`
|
|
39146
|
+
Billable SLOC is counted from each connected repository's current scanning
|
|
39147
|
+
branch. Blanks, comments, tests, docs, config and vendored code are excluded;
|
|
39148
|
+
"What's counted" reconciles the billable number to what plain scc reports.
|
|
39149
|
+
See ${getAppBaseUrl()}/docs/integrations/code-size
|
|
39150
|
+
|
|
39151
|
+
Examples:
|
|
39152
|
+
tracecli code-size
|
|
39153
|
+
tracecli code-size --repos 0
|
|
39154
|
+
tracecli code-size --output json | jq '.totals.billableSloc'
|
|
39155
|
+
tracecli code-size --output tsv | cut -f1,2
|
|
39156
|
+
tracecli code-size --web`
|
|
39157
|
+
).action(async (options) => {
|
|
39158
|
+
if (!isOutputFormat(options.output)) {
|
|
39159
|
+
console.error(
|
|
39160
|
+
`Unsupported --output '${options.output}'. Expected one of: ${OUTPUT_FORMATS.join(", ")}.`
|
|
39161
|
+
);
|
|
39162
|
+
process.exit(1);
|
|
39163
|
+
}
|
|
39164
|
+
const listed = await authenticatedRequest(
|
|
39165
|
+
(client) => client.organization.listMyOrganizations()
|
|
39166
|
+
);
|
|
39167
|
+
if (listed.status === 401) {
|
|
39168
|
+
console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
|
|
39169
|
+
process.exit(1);
|
|
39170
|
+
}
|
|
39171
|
+
if (listed.status !== 200) {
|
|
39172
|
+
console.error(`Failed to resolve organization (status ${listed.status}).`);
|
|
39173
|
+
process.exit(1);
|
|
39174
|
+
}
|
|
39175
|
+
const resolution = determineActiveOrganization(
|
|
39176
|
+
listed.body,
|
|
39177
|
+
readSelectedOrganizationId(),
|
|
39178
|
+
extractOrganizationIdFromToken(readToken())
|
|
39179
|
+
);
|
|
39180
|
+
if (!resolution) {
|
|
39181
|
+
console.error("No organization found for your account.");
|
|
39182
|
+
process.exit(1);
|
|
39183
|
+
}
|
|
39184
|
+
const { organizationId, slug } = resolution.organization;
|
|
39185
|
+
if (options.web) {
|
|
39186
|
+
const url2 = `${getAppBaseUrl()}/dashboard/${slug}/settings/integrations/github`;
|
|
39187
|
+
const opened = await openBrowser(url2);
|
|
39188
|
+
if (!opened) {
|
|
39189
|
+
console.log(`Open in browser: ${url2}`);
|
|
39190
|
+
}
|
|
39191
|
+
return;
|
|
39192
|
+
}
|
|
39193
|
+
const result = await authenticatedRequest(
|
|
39194
|
+
(client) => client.codeSize.getOrganizationCodeSize({ params: { organizationId } })
|
|
39195
|
+
);
|
|
39196
|
+
if (result.status === 401) {
|
|
39197
|
+
console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
|
|
39198
|
+
process.exit(1);
|
|
39199
|
+
}
|
|
39200
|
+
if (result.status !== 200) {
|
|
39201
|
+
console.error(`Failed to read code size (status ${result.status}).`);
|
|
39202
|
+
process.exit(1);
|
|
39203
|
+
}
|
|
39204
|
+
const codeSize = result.body;
|
|
39205
|
+
if (options.output === "json") {
|
|
39206
|
+
console.log(JSON.stringify(codeSize, null, 2));
|
|
39207
|
+
return;
|
|
39208
|
+
}
|
|
39209
|
+
if (options.output === "tsv") {
|
|
39210
|
+
for (const line of renderCodeSizeTsv(codeSize)) {
|
|
39211
|
+
console.log(line);
|
|
39212
|
+
}
|
|
39213
|
+
return;
|
|
39214
|
+
}
|
|
39215
|
+
const repoLimit = options.repos === void 0 ? DEFAULT_REPO_LIMIT : options.repos === 0 ? Number.POSITIVE_INFINITY : options.repos;
|
|
39216
|
+
for (const line of renderCodeSizeTable(codeSize, { orgSlug: slug, repoLimit })) {
|
|
39217
|
+
console.log(line);
|
|
39218
|
+
}
|
|
39219
|
+
});
|
|
39220
|
+
}
|
|
39221
|
+
|
|
39222
|
+
// src/completion/index.ts
|
|
39223
|
+
function extractCommandTree(cmd) {
|
|
39224
|
+
const BUILTIN_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V"]);
|
|
39225
|
+
const options = cmd.options.filter((o) => !o.hidden).filter((o) => !BUILTIN_FLAGS.has(o.long ?? "") && !BUILTIN_FLAGS.has(o.short ?? "")).map((o) => ({
|
|
38767
39226
|
flags: o.flags,
|
|
38768
39227
|
long: o.long ?? "",
|
|
38769
39228
|
short: o.short ?? null,
|
|
38770
39229
|
description: o.description,
|
|
38771
39230
|
takesValue: o.required || o.optional
|
|
38772
39231
|
}));
|
|
38773
|
-
const subcommands = cmd.commands.filter((
|
|
39232
|
+
const subcommands = cmd.commands.filter((c51) => !c51._hidden).map((c51) => extractCommandTree(c51));
|
|
38774
39233
|
return {
|
|
38775
39234
|
name: cmd.name(),
|
|
38776
39235
|
description: cmd.description(),
|
|
@@ -38836,7 +39295,7 @@ function generateBashCompletion(tree, binName) {
|
|
|
38836
39295
|
}
|
|
38837
39296
|
function collectBashCases(tree, prefix) {
|
|
38838
39297
|
const cases = /* @__PURE__ */ new Map();
|
|
38839
|
-
const subcommandNames = tree.subcommands.map((
|
|
39298
|
+
const subcommandNames = tree.subcommands.map((c51) => c51.name);
|
|
38840
39299
|
const optionNames = tree.options.flatMap((o) => o.short ? [o.long, o.short] : [o.long]);
|
|
38841
39300
|
const extraOptions = prefix === "" ? ["--help", "--version"] : ["--help"];
|
|
38842
39301
|
const allOptions = [.../* @__PURE__ */ new Set([...optionNames, ...extraOptions])];
|
|
@@ -39131,6 +39590,251 @@ Examples:
|
|
|
39131
39590
|
});
|
|
39132
39591
|
}
|
|
39133
39592
|
|
|
39593
|
+
// src/inbox/commands.ts
|
|
39594
|
+
function validateInboxLabel(label) {
|
|
39595
|
+
const parsed = InboxLabelSchema.safeParse(label);
|
|
39596
|
+
if (parsed.success) {
|
|
39597
|
+
return null;
|
|
39598
|
+
}
|
|
39599
|
+
return "Inbox label must be lowercase letters, digits, or dashes, starting with a letter (max 40 characters).";
|
|
39600
|
+
}
|
|
39601
|
+
function buildCreateInboxBody(label) {
|
|
39602
|
+
return { label };
|
|
39603
|
+
}
|
|
39604
|
+
function failWriteOp2(action, status, body, notFoundLabel) {
|
|
39605
|
+
const { message, errorCode } = readErrorFields(body);
|
|
39606
|
+
if (status === UNAUTHORIZED_STATUS2) {
|
|
39607
|
+
exitAuthFailed();
|
|
39608
|
+
}
|
|
39609
|
+
if (status === 403) {
|
|
39610
|
+
console.error(
|
|
39611
|
+
colorError(
|
|
39612
|
+
`Only an organization admin (or Trace staff) on a pentest-enabled organization can ${action} inboxes.`
|
|
39613
|
+
)
|
|
39614
|
+
);
|
|
39615
|
+
process.exit(1);
|
|
39616
|
+
}
|
|
39617
|
+
if (status === 404) {
|
|
39618
|
+
console.error(
|
|
39619
|
+
colorError(message ?? (notFoundLabel ? `No inbox labeled '${notFoundLabel}'.` : "Not found."))
|
|
39620
|
+
);
|
|
39621
|
+
process.exit(1);
|
|
39622
|
+
}
|
|
39623
|
+
if (status === 400) {
|
|
39624
|
+
console.error(colorError(message ?? "Invalid request (status 400)."));
|
|
39625
|
+
process.exit(1);
|
|
39626
|
+
}
|
|
39627
|
+
if (status === 409) {
|
|
39628
|
+
if (errorCode === "INBOX_ALREADY_EXISTS") {
|
|
39629
|
+
console.error(
|
|
39630
|
+
colorError(message ?? "An inbox with this label already exists in this organization.")
|
|
39631
|
+
);
|
|
39632
|
+
} else if (errorCode === "INBOX_BEING_DELETED") {
|
|
39633
|
+
console.error(
|
|
39634
|
+
colorError(
|
|
39635
|
+
message ?? "That name was recently removed and is still being cleaned up. Try again shortly, or choose another."
|
|
39636
|
+
)
|
|
39637
|
+
);
|
|
39638
|
+
} else if (errorCode === "INBOX_QUOTA_EXCEEDED") {
|
|
39639
|
+
console.error(
|
|
39640
|
+
colorError(message ?? "Inbox limit reached. Delete an unused inbox to create a new one.")
|
|
39641
|
+
);
|
|
39642
|
+
} else {
|
|
39643
|
+
console.error(colorError(message ?? "Conflict (status 409)."));
|
|
39644
|
+
}
|
|
39645
|
+
process.exit(1);
|
|
39646
|
+
}
|
|
39647
|
+
if (status === 503) {
|
|
39648
|
+
console.error(
|
|
39649
|
+
colorError(
|
|
39650
|
+
message ?? "Managed inboxes are not enabled on this server: no mail provider is configured."
|
|
39651
|
+
)
|
|
39652
|
+
);
|
|
39653
|
+
process.exit(1);
|
|
39654
|
+
}
|
|
39655
|
+
console.error(
|
|
39656
|
+
colorError(`Failed to ${action} inbox (status ${status})${message ? `: ${message}` : "."}`)
|
|
39657
|
+
);
|
|
39658
|
+
process.exit(1);
|
|
39659
|
+
}
|
|
39660
|
+
function failReadOp2(status, body) {
|
|
39661
|
+
const { message } = readErrorFields(body);
|
|
39662
|
+
if (status === UNAUTHORIZED_STATUS2) {
|
|
39663
|
+
exitAuthFailed();
|
|
39664
|
+
}
|
|
39665
|
+
if (status === 403) {
|
|
39666
|
+
console.error(colorError("You don't have access to view inboxes in this organization."));
|
|
39667
|
+
process.exit(1);
|
|
39668
|
+
}
|
|
39669
|
+
if (status === 503) {
|
|
39670
|
+
console.error(
|
|
39671
|
+
colorError(
|
|
39672
|
+
message ?? "Managed inboxes are not enabled on this server: no mail provider is configured."
|
|
39673
|
+
)
|
|
39674
|
+
);
|
|
39675
|
+
process.exit(1);
|
|
39676
|
+
}
|
|
39677
|
+
console.error(
|
|
39678
|
+
colorError(`Failed to list inboxes (status ${status})${message ? `: ${message}` : "."}`)
|
|
39679
|
+
);
|
|
39680
|
+
process.exit(1);
|
|
39681
|
+
}
|
|
39682
|
+
function renderInboxDetail(inbox) {
|
|
39683
|
+
const pad = 10;
|
|
39684
|
+
return [
|
|
39685
|
+
`${"Address:".padEnd(pad)} ${sanitizeDisplay(inbox.address)}`,
|
|
39686
|
+
`${"Label:".padEnd(pad)} ${sanitizeDisplay(inbox.label)}`,
|
|
39687
|
+
`${"Created:".padEnd(pad)} ${formatDate(inbox.createdAt)}`
|
|
39688
|
+
].join("\n");
|
|
39689
|
+
}
|
|
39690
|
+
function printInboxesTsv(inboxes) {
|
|
39691
|
+
console.log(["address", "label", "createdAt"].join(" "));
|
|
39692
|
+
for (const inbox of inboxes) {
|
|
39693
|
+
console.log(
|
|
39694
|
+
[
|
|
39695
|
+
tsvSafe(sanitizeDisplay(inbox.address)),
|
|
39696
|
+
tsvSafe(sanitizeDisplay(inbox.label)),
|
|
39697
|
+
tsvSafe(toIso(inbox.createdAt))
|
|
39698
|
+
].join(" ")
|
|
39699
|
+
);
|
|
39700
|
+
}
|
|
39701
|
+
}
|
|
39702
|
+
function buildInboxesTable(inboxes) {
|
|
39703
|
+
const cells = inboxes.map((inbox) => ({
|
|
39704
|
+
address: sanitizeDisplay(inbox.address),
|
|
39705
|
+
label: sanitizeDisplay(inbox.label)
|
|
39706
|
+
}));
|
|
39707
|
+
const addressWidth = Math.max(7, ...cells.map((c51) => c51.address.length));
|
|
39708
|
+
const header = `${"ADDRESS".padEnd(addressWidth)} LABEL`;
|
|
39709
|
+
const rows = cells.map((c51) => `${c51.address.padEnd(addressWidth)} ${c51.label}`);
|
|
39710
|
+
return { header, rows };
|
|
39711
|
+
}
|
|
39712
|
+
function formatInboxQuota(quota) {
|
|
39713
|
+
return `${quota.used} of ${quota.limit} inboxes`;
|
|
39714
|
+
}
|
|
39715
|
+
function outputInbox(inbox, output) {
|
|
39716
|
+
if (output === "json") {
|
|
39717
|
+
console.log(JSON.stringify(inbox, null, 2));
|
|
39718
|
+
return;
|
|
39719
|
+
}
|
|
39720
|
+
if (output === "tsv") {
|
|
39721
|
+
printInboxesTsv([inbox]);
|
|
39722
|
+
return;
|
|
39723
|
+
}
|
|
39724
|
+
console.log(renderInboxDetail(inbox));
|
|
39725
|
+
}
|
|
39726
|
+
function requireInboxLabel(label) {
|
|
39727
|
+
const error48 = validateInboxLabel(label);
|
|
39728
|
+
if (error48) {
|
|
39729
|
+
console.error(colorError(error48));
|
|
39730
|
+
process.exit(1);
|
|
39731
|
+
}
|
|
39732
|
+
}
|
|
39733
|
+
async function runCreate2(label, options) {
|
|
39734
|
+
const output = parseOutput(options.output);
|
|
39735
|
+
requireInboxLabel(label);
|
|
39736
|
+
const organizationId = await resolveOrganizationId();
|
|
39737
|
+
const result = await authenticatedRequest(
|
|
39738
|
+
(client) => client.inbox.createInbox({
|
|
39739
|
+
params: { organizationId },
|
|
39740
|
+
body: buildCreateInboxBody(label)
|
|
39741
|
+
})
|
|
39742
|
+
);
|
|
39743
|
+
if (result.status !== CREATED_STATUS) {
|
|
39744
|
+
failWriteOp2("create", result.status, result.body);
|
|
39745
|
+
}
|
|
39746
|
+
if (output === "table") {
|
|
39747
|
+
console.log(colorSuccess(`Created inbox ${sanitizeDisplay(result.body.address)}`));
|
|
39748
|
+
}
|
|
39749
|
+
outputInbox(result.body, output);
|
|
39750
|
+
}
|
|
39751
|
+
async function runList2(options) {
|
|
39752
|
+
const output = parseOutput(options.output);
|
|
39753
|
+
const organizationId = await resolveOrganizationId();
|
|
39754
|
+
const result = await authenticatedRequest(
|
|
39755
|
+
(client) => client.inbox.listInboxes({ params: { organizationId } })
|
|
39756
|
+
);
|
|
39757
|
+
if (result.status !== SUCCESS_STATUS) {
|
|
39758
|
+
failReadOp2(result.status, result.body);
|
|
39759
|
+
}
|
|
39760
|
+
const { inboxes, quota } = result.body;
|
|
39761
|
+
if (output === "json") {
|
|
39762
|
+
console.log(JSON.stringify({ inboxes, quota }, null, 2));
|
|
39763
|
+
return;
|
|
39764
|
+
}
|
|
39765
|
+
if (output === "tsv") {
|
|
39766
|
+
printInboxesTsv(inboxes);
|
|
39767
|
+
return;
|
|
39768
|
+
}
|
|
39769
|
+
if (inboxes.length === 0) {
|
|
39770
|
+
console.log(`No inboxes found. ${formatInboxQuota(quota)}.`);
|
|
39771
|
+
return;
|
|
39772
|
+
}
|
|
39773
|
+
const { header, rows } = buildInboxesTable(inboxes);
|
|
39774
|
+
await runInteractivePager({
|
|
39775
|
+
items: inboxes,
|
|
39776
|
+
header,
|
|
39777
|
+
renderItem: (_inbox, i) => [rows[i] ?? ""],
|
|
39778
|
+
disabled: options.pager === false
|
|
39779
|
+
});
|
|
39780
|
+
console.log(formatInboxQuota(quota));
|
|
39781
|
+
}
|
|
39782
|
+
async function runDelete2(label, options) {
|
|
39783
|
+
requireInboxLabel(label);
|
|
39784
|
+
const confirmed = await confirmDeletion(`inbox ${label}`, options.yes);
|
|
39785
|
+
if (!confirmed) {
|
|
39786
|
+
console.log("Aborted.");
|
|
39787
|
+
return;
|
|
39788
|
+
}
|
|
39789
|
+
const organizationId = await resolveOrganizationId();
|
|
39790
|
+
const result = await authenticatedRequest(
|
|
39791
|
+
(client) => client.inbox.deleteInbox({
|
|
39792
|
+
params: { organizationId, label }
|
|
39793
|
+
})
|
|
39794
|
+
);
|
|
39795
|
+
if (result.status !== NO_CONTENT_STATUS) {
|
|
39796
|
+
failWriteOp2("delete", result.status, result.body, label);
|
|
39797
|
+
}
|
|
39798
|
+
console.log(colorSuccess(`Deleted inbox ${sanitizeDisplay(label)}`));
|
|
39799
|
+
}
|
|
39800
|
+
function createCreateCommand2() {
|
|
39801
|
+
return new Command("create").description("Provision a Trace-hosted email inbox").argument("<label>", "Inbox name (lowercase letters/digits/dashes, max 40)").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
|
|
39802
|
+
"after",
|
|
39803
|
+
`
|
|
39804
|
+
Trace hosts this inbox; the pentest agent reads its emails automatically.
|
|
39805
|
+
The minted address is {org-slug}-{label}@pentest.securewithtrace.com.
|
|
39806
|
+
|
|
39807
|
+
Use the printed address as the test-account email when creating a magic-auth
|
|
39808
|
+
or username-password credential.
|
|
39809
|
+
|
|
39810
|
+
Examples:
|
|
39811
|
+
tracecli credential inbox create portal
|
|
39812
|
+
ADDRESS=$(tracecli credential inbox create qa-admin -o json | jq -r .address)
|
|
39813
|
+
echo "$ADDRESS" | tracecli credential create --env <envId> --type magic-auth --secret-stdin`
|
|
39814
|
+
).action(async (label, options) => {
|
|
39815
|
+
await runCreate2(label, options);
|
|
39816
|
+
});
|
|
39817
|
+
}
|
|
39818
|
+
function createListCommand3() {
|
|
39819
|
+
return new Command("list").description("List Trace-hosted email inboxes in the active organization").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").option("--no-pager", "Disable the interactive pager for table output").action(async (options) => {
|
|
39820
|
+
await runList2(options);
|
|
39821
|
+
});
|
|
39822
|
+
}
|
|
39823
|
+
function createDeleteCommand2() {
|
|
39824
|
+
return new Command("delete").description("Delete a Trace-hosted email inbox").argument("<label>", "Inbox label").option("-y, --yes", "Skip the confirmation prompt (required in non-interactive shells)").action(async (label, options) => {
|
|
39825
|
+
await runDelete2(label, options);
|
|
39826
|
+
});
|
|
39827
|
+
}
|
|
39828
|
+
function createInboxCommand() {
|
|
39829
|
+
const inbox = new Command("inbox").description(
|
|
39830
|
+
"Provision Trace-hosted email inboxes for test-account credentials"
|
|
39831
|
+
);
|
|
39832
|
+
inbox.addCommand(createCreateCommand2());
|
|
39833
|
+
inbox.addCommand(createListCommand3());
|
|
39834
|
+
inbox.addCommand(createDeleteCommand2());
|
|
39835
|
+
return inbox;
|
|
39836
|
+
}
|
|
39837
|
+
|
|
39134
39838
|
// src/secret-input.ts
|
|
39135
39839
|
import { readFileSync as readFileSync2 } from "fs";
|
|
39136
39840
|
var SecretInputError = class extends Error {
|
|
@@ -39423,7 +40127,7 @@ function usernameOpts(opts) {
|
|
|
39423
40127
|
function passwordOpts(opts) {
|
|
39424
40128
|
return { stdin: opts.passwordStdin, file: opts.passwordFile, env: opts.passwordEnv };
|
|
39425
40129
|
}
|
|
39426
|
-
function
|
|
40130
|
+
function failWriteOp3(action, status, body, notFoundLabel) {
|
|
39427
40131
|
const { message, errorCode } = readErrorFields(body);
|
|
39428
40132
|
if (status === UNAUTHORIZED_STATUS2) {
|
|
39429
40133
|
exitAuthFailed();
|
|
@@ -39467,7 +40171,7 @@ function failWriteOp2(action, status, body, notFoundLabel) {
|
|
|
39467
40171
|
);
|
|
39468
40172
|
process.exit(1);
|
|
39469
40173
|
}
|
|
39470
|
-
function
|
|
40174
|
+
function failReadOp3(action, status, body, notFoundLabel) {
|
|
39471
40175
|
const { message } = readErrorFields(body);
|
|
39472
40176
|
if (status === UNAUTHORIZED_STATUS2) {
|
|
39473
40177
|
exitAuthFailed();
|
|
@@ -39519,16 +40223,16 @@ function printCredentialsTsv(creds) {
|
|
|
39519
40223
|
}
|
|
39520
40224
|
}
|
|
39521
40225
|
function buildCredentialsTable(creds) {
|
|
39522
|
-
const cells = creds.map((
|
|
39523
|
-
id:
|
|
39524
|
-
label: sanitizeDisplay(
|
|
39525
|
-
type:
|
|
40226
|
+
const cells = creds.map((c51) => ({
|
|
40227
|
+
id: c51.credentialId,
|
|
40228
|
+
label: sanitizeDisplay(c51.label),
|
|
40229
|
+
type: c51.credentialType
|
|
39526
40230
|
}));
|
|
39527
|
-
const idWidth = Math.max(2, ...cells.map((
|
|
39528
|
-
const labelWidth = Math.max(5, ...cells.map((
|
|
40231
|
+
const idWidth = Math.max(2, ...cells.map((c51) => c51.id.length));
|
|
40232
|
+
const labelWidth = Math.max(5, ...cells.map((c51) => c51.label.length));
|
|
39529
40233
|
const header = `${"ID".padEnd(idWidth)} ${"LABEL".padEnd(labelWidth)} TYPE`;
|
|
39530
40234
|
const rows = cells.map(
|
|
39531
|
-
(
|
|
40235
|
+
(c51) => `${c51.id.padEnd(idWidth)} ${c51.label.padEnd(labelWidth)} ${c51.type}`
|
|
39532
40236
|
);
|
|
39533
40237
|
return { header, rows };
|
|
39534
40238
|
}
|
|
@@ -39559,7 +40263,7 @@ function failAuthBuild(result) {
|
|
|
39559
40263
|
console.error(colorError(result.error));
|
|
39560
40264
|
process.exit(1);
|
|
39561
40265
|
}
|
|
39562
|
-
async function
|
|
40266
|
+
async function runCreate3(options) {
|
|
39563
40267
|
const output = parseOutput(options.output);
|
|
39564
40268
|
requireEnvId(options.env);
|
|
39565
40269
|
const type = normalizeCredentialType(options.type);
|
|
@@ -39599,7 +40303,7 @@ async function runCreate2(options) {
|
|
|
39599
40303
|
(client) => client.credential.createCredential({ params, body })
|
|
39600
40304
|
);
|
|
39601
40305
|
if (result.status !== CREATED_STATUS) {
|
|
39602
|
-
|
|
40306
|
+
failWriteOp3("create", result.status, result.body);
|
|
39603
40307
|
}
|
|
39604
40308
|
if (output === "table") {
|
|
39605
40309
|
console.log(colorSuccess(`Created credential ${sanitizeDisplay(result.body.label)}`));
|
|
@@ -39691,7 +40395,7 @@ async function buildCreateBody(type, label, options) {
|
|
|
39691
40395
|
}
|
|
39692
40396
|
}
|
|
39693
40397
|
}
|
|
39694
|
-
async function
|
|
40398
|
+
async function runList3(options) {
|
|
39695
40399
|
const output = parseOutput(options.output);
|
|
39696
40400
|
requireEnvId(options.env);
|
|
39697
40401
|
const organizationId = await resolveOrganizationId();
|
|
@@ -39699,7 +40403,7 @@ async function runList2(options) {
|
|
|
39699
40403
|
(client) => client.credential.listCredentials({ params: { organizationId, environmentId: options.env } })
|
|
39700
40404
|
);
|
|
39701
40405
|
if (result.status !== SUCCESS_STATUS) {
|
|
39702
|
-
|
|
40406
|
+
failReadOp3("list credentials", result.status, result.body, options.env);
|
|
39703
40407
|
}
|
|
39704
40408
|
const creds = result.body;
|
|
39705
40409
|
if (output === "json") {
|
|
@@ -39733,7 +40437,7 @@ async function runGet2(credentialId, options) {
|
|
|
39733
40437
|
})
|
|
39734
40438
|
);
|
|
39735
40439
|
if (result.status !== SUCCESS_STATUS) {
|
|
39736
|
-
|
|
40440
|
+
failReadOp3("get credential", result.status, result.body, credentialId);
|
|
39737
40441
|
}
|
|
39738
40442
|
outputCredential(result.body, output);
|
|
39739
40443
|
}
|
|
@@ -39767,7 +40471,7 @@ async function runUpdate2(credentialId, options) {
|
|
|
39767
40471
|
(client) => client.credential.getCredential({ params })
|
|
39768
40472
|
);
|
|
39769
40473
|
if (current.status !== SUCCESS_STATUS) {
|
|
39770
|
-
|
|
40474
|
+
failReadOp3("get credential", current.status, current.body, credentialId);
|
|
39771
40475
|
}
|
|
39772
40476
|
const type = current.body.credentialType;
|
|
39773
40477
|
const foreign = rejectForeignAuthFlags(type, options);
|
|
@@ -39800,14 +40504,14 @@ async function runUpdate2(credentialId, options) {
|
|
|
39800
40504
|
(client) => client.credential.updateCredential({ params, body })
|
|
39801
40505
|
);
|
|
39802
40506
|
if (result.status !== SUCCESS_STATUS) {
|
|
39803
|
-
|
|
40507
|
+
failWriteOp3("update", result.status, result.body, credentialId);
|
|
39804
40508
|
}
|
|
39805
40509
|
if (output === "table") {
|
|
39806
40510
|
console.log(colorSuccess(`Updated credential ${sanitizeDisplay(result.body.label)}`));
|
|
39807
40511
|
}
|
|
39808
40512
|
outputCredential(result.body, output);
|
|
39809
40513
|
}
|
|
39810
|
-
async function
|
|
40514
|
+
async function runDelete3(credentialId, options) {
|
|
39811
40515
|
requireEnvId(options.env);
|
|
39812
40516
|
requireCredId(credentialId);
|
|
39813
40517
|
const confirmed = await confirmDeletion(`credential ${credentialId}`, options.yes);
|
|
@@ -39822,7 +40526,7 @@ async function runDelete2(credentialId, options) {
|
|
|
39822
40526
|
})
|
|
39823
40527
|
);
|
|
39824
40528
|
if (result.status !== NO_CONTENT_STATUS) {
|
|
39825
|
-
|
|
40529
|
+
failWriteOp3("delete", result.status, result.body, credentialId);
|
|
39826
40530
|
}
|
|
39827
40531
|
console.log(colorSuccess(`Deleted credential ${credentialId}`));
|
|
39828
40532
|
}
|
|
@@ -39832,7 +40536,7 @@ function addSecretInputOptions(command) {
|
|
|
39832
40536
|
function addAuthConfigOptions(command) {
|
|
39833
40537
|
return command.option("--header-name <name>", "authConfig: header name (bearer-token/jwt-token)").option("--token-prefix <prefix>", "authConfig: token prefix (bearer-token/jwt-token)").option("--placement <header|query>", "authConfig: API key placement (api-key)").option("--key-name <name>", "authConfig: API key name (api-key)").option("--cookie-name <name>", "authConfig: cookie name (cookie)").option("--cookie-domain <domain>", "authConfig: cookie domain (cookie)").option("--cookie-path <path>", "authConfig: cookie path (cookie)").option("--method <form|basic|json>", "authConfig: login method (username-password)").option("--login-url <url>", "authConfig: login URL (username-password)").option("--username-field <name>", "authConfig: username field (username-password)").option("--password-field <name>", "authConfig: password field (username-password)").option("--session-cookie-name <name>", "authConfig: session cookie (username-password)").option("--csrf-token-selector <sel>", "authConfig: CSRF token selector (username-password)").option("--csrf-field-name <name>", "authConfig: CSRF field name (username-password)");
|
|
39834
40538
|
}
|
|
39835
|
-
function
|
|
40539
|
+
function createCreateCommand3() {
|
|
39836
40540
|
const command = new Command("create").description("Create a credential in an environment").requiredOption("--env <environmentId>", "Parent environment UUID").requiredOption(
|
|
39837
40541
|
"--type <type>",
|
|
39838
40542
|
"bearer-token, jwt-token, api-key, passphrase, username-password, cookie, magic-auth"
|
|
@@ -39850,15 +40554,17 @@ Secrets are read from stdin/file/env (or a no-echo prompt) \u2014 never an inlin
|
|
|
39850
40554
|
Examples:
|
|
39851
40555
|
vault read -field=token secret/x | tracecli credential create --env <envId> --type bearer-token --secret-stdin
|
|
39852
40556
|
tracecli credential create --env <envId> --type api-key --label "prod key" --secret-env API_KEY --placement header --key-name X-API-Key
|
|
39853
|
-
tracecli credential create --env <envId> --type username-password --username-env U --password-env P --method form --login-url https://acme.com/login
|
|
40557
|
+
tracecli credential create --env <envId> --type username-password --username-env U --password-env P --method form --login-url https://acme.com/login
|
|
40558
|
+
ADDRESS=$(tracecli credential inbox create portal -o json | jq -r .address)
|
|
40559
|
+
echo "$ADDRESS" | tracecli credential create --env <envId> --type magic-auth --secret-stdin`
|
|
39854
40560
|
);
|
|
39855
40561
|
return command.action(async (options) => {
|
|
39856
|
-
await
|
|
40562
|
+
await runCreate3(options);
|
|
39857
40563
|
});
|
|
39858
40564
|
}
|
|
39859
|
-
function
|
|
40565
|
+
function createListCommand4() {
|
|
39860
40566
|
return new Command("list").description("List an environment's credentials (secrets are never shown)").requiredOption("--env <environmentId>", "Parent environment UUID").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").option("--no-pager", "Disable the interactive pager for table output").action(async (options) => {
|
|
39861
|
-
await
|
|
40567
|
+
await runList3(options);
|
|
39862
40568
|
});
|
|
39863
40569
|
}
|
|
39864
40570
|
function createGetCommand2() {
|
|
@@ -39884,18 +40590,19 @@ Examples:
|
|
|
39884
40590
|
await runUpdate2(credentialId, options);
|
|
39885
40591
|
});
|
|
39886
40592
|
}
|
|
39887
|
-
function
|
|
40593
|
+
function createDeleteCommand3() {
|
|
39888
40594
|
return new Command("delete").description("Delete a credential").argument("<credentialId>", "Credential UUID").requiredOption("--env <environmentId>", "Parent environment UUID").option("-y, --yes", "Skip the confirmation prompt (required in non-interactive shells)").action(async (credentialId, options) => {
|
|
39889
|
-
await
|
|
40595
|
+
await runDelete3(credentialId, options);
|
|
39890
40596
|
});
|
|
39891
40597
|
}
|
|
39892
40598
|
function createCredentialCommand() {
|
|
39893
40599
|
const credential = new Command("credential").alias("cred").description("Manage environment credentials");
|
|
39894
|
-
credential.addCommand(
|
|
39895
|
-
credential.addCommand(
|
|
40600
|
+
credential.addCommand(createCreateCommand3());
|
|
40601
|
+
credential.addCommand(createListCommand4());
|
|
39896
40602
|
credential.addCommand(createGetCommand2());
|
|
39897
40603
|
credential.addCommand(createUpdateCommand2());
|
|
39898
|
-
credential.addCommand(
|
|
40604
|
+
credential.addCommand(createDeleteCommand3());
|
|
40605
|
+
credential.addCommand(createInboxCommand());
|
|
39899
40606
|
return credential;
|
|
39900
40607
|
}
|
|
39901
40608
|
|
|
@@ -39938,7 +40645,7 @@ function resolveProductionFlag(input) {
|
|
|
39938
40645
|
}
|
|
39939
40646
|
return { value: void 0 };
|
|
39940
40647
|
}
|
|
39941
|
-
function
|
|
40648
|
+
function failWriteOp4(action, status, body, notFoundLabel) {
|
|
39942
40649
|
const { message, errorCode } = readErrorFields(body);
|
|
39943
40650
|
if (status === UNAUTHORIZED_STATUS2) {
|
|
39944
40651
|
exitAuthFailed();
|
|
@@ -39986,7 +40693,7 @@ function failWriteOp3(action, status, body, notFoundLabel) {
|
|
|
39986
40693
|
);
|
|
39987
40694
|
process.exit(1);
|
|
39988
40695
|
}
|
|
39989
|
-
function
|
|
40696
|
+
function failReadOp4(action, status, body, notFoundLabel) {
|
|
39990
40697
|
const { message } = readErrorFields(body);
|
|
39991
40698
|
if (status === UNAUTHORIZED_STATUS2) {
|
|
39992
40699
|
exitAuthFailed();
|
|
@@ -40017,7 +40724,7 @@ function renderEnvironmentDetail(env2) {
|
|
|
40017
40724
|
return [
|
|
40018
40725
|
`${"ID:".padEnd(pad)} ${env2.environmentId}`,
|
|
40019
40726
|
`${"Name:".padEnd(pad)} ${sanitizeDisplay(env2.name)}`,
|
|
40020
|
-
`${"URL:".padEnd(pad)} ${sanitizeDisplay(env2.primaryUrl)}`,
|
|
40727
|
+
`${"URL:".padEnd(pad)} ${env2.primaryUrl != null ? sanitizeDisplay(env2.primaryUrl) : "\u2014"}`,
|
|
40021
40728
|
`${"Production:".padEnd(pad)} ${env2.isProduction ? "yes" : "no"}`,
|
|
40022
40729
|
`${"Description:".padEnd(pad)} ${env2.description ? sanitizeDisplay(env2.description) : "\u2014"}`,
|
|
40023
40730
|
`${"Application:".padEnd(pad)} ${env2.applicationId}`,
|
|
@@ -40033,7 +40740,7 @@ function printEnvironmentsTsv(envs) {
|
|
|
40033
40740
|
[
|
|
40034
40741
|
tsvSafe(env2.environmentId),
|
|
40035
40742
|
tsvSafe(sanitizeDisplay(env2.name)),
|
|
40036
|
-
tsvSafe(sanitizeDisplay(env2.primaryUrl)),
|
|
40743
|
+
tsvSafe(sanitizeDisplay(env2.primaryUrl ?? "")),
|
|
40037
40744
|
String(env2.isProduction),
|
|
40038
40745
|
tsvSafe(sanitizeDisplay(env2.description ?? "")),
|
|
40039
40746
|
tsvSafe(toIso(env2.createdAt))
|
|
@@ -40065,7 +40772,7 @@ function printOrgEnvironmentsTsv(envs) {
|
|
|
40065
40772
|
tsvSafe(env2.applicationId),
|
|
40066
40773
|
tsvSafe(sanitizeDisplay(env2.applicationName)),
|
|
40067
40774
|
tsvSafe(sanitizeDisplay(env2.name)),
|
|
40068
|
-
tsvSafe(sanitizeDisplay(env2.primaryUrl)),
|
|
40775
|
+
tsvSafe(sanitizeDisplay(env2.primaryUrl ?? "")),
|
|
40069
40776
|
String(env2.isProduction),
|
|
40070
40777
|
tsvSafe(toIso(env2.createdAt))
|
|
40071
40778
|
].join(" ")
|
|
@@ -40077,17 +40784,17 @@ function buildEnvironmentTable(envs, leading) {
|
|
|
40077
40784
|
leading: leading.map((column) => sanitizeDisplay(column.value(e2))),
|
|
40078
40785
|
name: sanitizeDisplay(e2.name),
|
|
40079
40786
|
prod: e2.isProduction ? "yes" : "no",
|
|
40080
|
-
url: sanitizeDisplay(e2.primaryUrl)
|
|
40787
|
+
url: e2.primaryUrl != null ? sanitizeDisplay(e2.primaryUrl) : "\u2014"
|
|
40081
40788
|
}));
|
|
40082
40789
|
const leadingWidths = leading.map(
|
|
40083
|
-
(column, i) => Math.max(column.header.length, ...cells.map((
|
|
40790
|
+
(column, i) => Math.max(column.header.length, ...cells.map((c51) => c51.leading[i]?.length ?? 0))
|
|
40084
40791
|
);
|
|
40085
|
-
const nameWidth = Math.max(4, ...cells.map((
|
|
40792
|
+
const nameWidth = Math.max(4, ...cells.map((c51) => c51.name.length));
|
|
40086
40793
|
const padLeading = (values) => values.map((v2, i) => v2.padEnd(leadingWidths[i] ?? 0)).join(" ");
|
|
40087
40794
|
return {
|
|
40088
|
-
header: `${padLeading(leading.map((
|
|
40795
|
+
header: `${padLeading(leading.map((c51) => c51.header))} ${"NAME".padEnd(nameWidth)} PROD URL`,
|
|
40089
40796
|
rows: cells.map(
|
|
40090
|
-
(
|
|
40797
|
+
(c51) => `${padLeading(c51.leading)} ${c51.name.padEnd(nameWidth)} ${c51.prod.padEnd(4)} ${c51.url}`
|
|
40091
40798
|
)
|
|
40092
40799
|
};
|
|
40093
40800
|
}
|
|
@@ -40127,7 +40834,7 @@ function requireEnvId2(environmentId) {
|
|
|
40127
40834
|
process.exit(1);
|
|
40128
40835
|
}
|
|
40129
40836
|
}
|
|
40130
|
-
async function
|
|
40837
|
+
async function runCreate4(name, options) {
|
|
40131
40838
|
const output = parseOutput(options.output);
|
|
40132
40839
|
requireAppId(options.app);
|
|
40133
40840
|
const nameError = validateEnvName(name);
|
|
@@ -40149,7 +40856,7 @@ async function runCreate3(name, options) {
|
|
|
40149
40856
|
})
|
|
40150
40857
|
);
|
|
40151
40858
|
if (result.status !== CREATED_STATUS) {
|
|
40152
|
-
|
|
40859
|
+
failWriteOp4("create", result.status, result.body);
|
|
40153
40860
|
}
|
|
40154
40861
|
if (output === "table") {
|
|
40155
40862
|
console.log(colorSuccess(`Created environment ${sanitizeDisplay(result.body.name)}`));
|
|
@@ -40176,7 +40883,7 @@ function createOrgEnvironmentRequests(organizationId) {
|
|
|
40176
40883
|
async function collectOrgEnvironments(requests) {
|
|
40177
40884
|
const appsResult = await requests.listApplications();
|
|
40178
40885
|
if (!appsResult.ok) {
|
|
40179
|
-
|
|
40886
|
+
failReadOp4("list applications", appsResult.status, appsResult.body);
|
|
40180
40887
|
}
|
|
40181
40888
|
const apps = appsResult.data;
|
|
40182
40889
|
const environments = [];
|
|
@@ -40248,7 +40955,7 @@ async function runListAcrossOrganization(output, pager) {
|
|
|
40248
40955
|
disabled: pager === false
|
|
40249
40956
|
});
|
|
40250
40957
|
}
|
|
40251
|
-
async function
|
|
40958
|
+
async function runList4(options) {
|
|
40252
40959
|
const output = parseOutput(options.output);
|
|
40253
40960
|
if (options.app === void 0) {
|
|
40254
40961
|
await runListAcrossOrganization(output, options.pager);
|
|
@@ -40263,7 +40970,7 @@ async function runList3(options) {
|
|
|
40263
40970
|
})
|
|
40264
40971
|
);
|
|
40265
40972
|
if (result.status !== SUCCESS_STATUS) {
|
|
40266
|
-
|
|
40973
|
+
failReadOp4("list environments", result.status, result.body, applicationId);
|
|
40267
40974
|
}
|
|
40268
40975
|
const envs = result.body;
|
|
40269
40976
|
if (output === "json") {
|
|
@@ -40297,7 +41004,7 @@ async function runGet3(environmentId, options) {
|
|
|
40297
41004
|
})
|
|
40298
41005
|
);
|
|
40299
41006
|
if (result.status !== SUCCESS_STATUS) {
|
|
40300
|
-
|
|
41007
|
+
failReadOp4("get environment", result.status, result.body, environmentId);
|
|
40301
41008
|
}
|
|
40302
41009
|
outputEnvironment(result.body, output);
|
|
40303
41010
|
}
|
|
@@ -40339,14 +41046,14 @@ async function runUpdate3(environmentId, options) {
|
|
|
40339
41046
|
})
|
|
40340
41047
|
);
|
|
40341
41048
|
if (result.status !== SUCCESS_STATUS) {
|
|
40342
|
-
|
|
41049
|
+
failWriteOp4("update", result.status, result.body, environmentId);
|
|
40343
41050
|
}
|
|
40344
41051
|
if (output === "table") {
|
|
40345
41052
|
console.log(colorSuccess(`Updated environment ${sanitizeDisplay(result.body.name)}`));
|
|
40346
41053
|
}
|
|
40347
41054
|
outputEnvironment(result.body, output);
|
|
40348
41055
|
}
|
|
40349
|
-
async function
|
|
41056
|
+
async function runDelete4(environmentId, options) {
|
|
40350
41057
|
requireAppId(options.app);
|
|
40351
41058
|
requireEnvId2(environmentId);
|
|
40352
41059
|
const confirmed = await confirmDeletion(`environment ${environmentId}`, options.yes);
|
|
@@ -40361,11 +41068,11 @@ async function runDelete3(environmentId, options) {
|
|
|
40361
41068
|
})
|
|
40362
41069
|
);
|
|
40363
41070
|
if (result.status !== NO_CONTENT_STATUS) {
|
|
40364
|
-
|
|
41071
|
+
failWriteOp4("delete", result.status, result.body, environmentId);
|
|
40365
41072
|
}
|
|
40366
41073
|
console.log(colorSuccess(`Deleted environment ${environmentId}`));
|
|
40367
41074
|
}
|
|
40368
|
-
function
|
|
41075
|
+
function createCreateCommand4() {
|
|
40369
41076
|
return new Command("create").description("Create an environment for an application").argument("<name>", "Environment name (lowercase letters/digits/dashes)").requiredOption("--app <applicationId>", "Parent application UUID").requiredOption("--url <url>", "Primary URL for the environment").option("--description <text>", "Description").option("--production", "Mark as the production environment").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
|
|
40370
41077
|
"after",
|
|
40371
41078
|
`
|
|
@@ -40373,10 +41080,10 @@ Examples:
|
|
|
40373
41080
|
tracecli environment create staging --app <appId> --url https://staging.acme.com
|
|
40374
41081
|
tracecli environment create production --app <appId> --url https://acme.com --production`
|
|
40375
41082
|
).action(async (name, options) => {
|
|
40376
|
-
await
|
|
41083
|
+
await runCreate4(name, options);
|
|
40377
41084
|
});
|
|
40378
41085
|
}
|
|
40379
|
-
function
|
|
41086
|
+
function createListCommand5() {
|
|
40380
41087
|
return new Command("list").description("List environments \u2014 an application's, or every one in the organization").option("--app <applicationId>", "Parent application UUID (omit to list the whole org)").option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").option("--no-pager", "Disable the interactive pager for table output").addHelpText(
|
|
40381
41088
|
"after",
|
|
40382
41089
|
`
|
|
@@ -40388,7 +41095,7 @@ Examples:
|
|
|
40388
41095
|
tracecli environment list --app <appId>
|
|
40389
41096
|
tracecli environment list --output tsv | cut -f2,3,4`
|
|
40390
41097
|
).action(async (options) => {
|
|
40391
|
-
await
|
|
41098
|
+
await runList4(options);
|
|
40392
41099
|
});
|
|
40393
41100
|
}
|
|
40394
41101
|
function createGetCommand3() {
|
|
@@ -40407,18 +41114,18 @@ Examples:
|
|
|
40407
41114
|
await runUpdate3(environmentId, options);
|
|
40408
41115
|
});
|
|
40409
41116
|
}
|
|
40410
|
-
function
|
|
41117
|
+
function createDeleteCommand4() {
|
|
40411
41118
|
return new Command("delete").description("Delete an environment").argument("<environmentId>", "Environment UUID").requiredOption("--app <applicationId>", "Parent application UUID").option("-y, --yes", "Skip the confirmation prompt (required in non-interactive shells)").action(async (environmentId, options) => {
|
|
40412
|
-
await
|
|
41119
|
+
await runDelete4(environmentId, options);
|
|
40413
41120
|
});
|
|
40414
41121
|
}
|
|
40415
41122
|
function createEnvironmentCommand() {
|
|
40416
41123
|
const environment = new Command("environment").alias("env").description("Manage application environments");
|
|
40417
|
-
environment.addCommand(
|
|
40418
|
-
environment.addCommand(
|
|
41124
|
+
environment.addCommand(createCreateCommand4());
|
|
41125
|
+
environment.addCommand(createListCommand5());
|
|
40419
41126
|
environment.addCommand(createGetCommand3());
|
|
40420
41127
|
environment.addCommand(createUpdateCommand3());
|
|
40421
|
-
environment.addCommand(
|
|
41128
|
+
environment.addCommand(createDeleteCommand4());
|
|
40422
41129
|
return environment;
|
|
40423
41130
|
}
|
|
40424
41131
|
|
|
@@ -40450,7 +41157,223 @@ var CLI_PACKAGE_NAME = packageMetadata.name;
|
|
|
40450
41157
|
var CLI_VERSION = packageMetadata.version;
|
|
40451
41158
|
|
|
40452
41159
|
// src/pentest/commands.ts
|
|
40453
|
-
import { readFileSync as
|
|
41160
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
41161
|
+
|
|
41162
|
+
// src/pentest/evidence.ts
|
|
41163
|
+
import { readFileSync as readFileSync4, statSync } from "fs";
|
|
41164
|
+
import { basename } from "path";
|
|
41165
|
+
|
|
41166
|
+
// src/pentest/resolve.ts
|
|
41167
|
+
var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
41168
|
+
async function resolvePentestId(organizationId, identifier) {
|
|
41169
|
+
if (UUID_PATTERN2.test(identifier)) {
|
|
41170
|
+
return identifier;
|
|
41171
|
+
}
|
|
41172
|
+
const numericMatch = identifier.match(/^(?:PT-)?(\d+)$/i);
|
|
41173
|
+
if (!numericMatch?.[1]) {
|
|
41174
|
+
console.error(
|
|
41175
|
+
`Invalid pentest identifier '${identifier}'. Use a display ID (e.g. PT-3) or UUID.`
|
|
41176
|
+
);
|
|
41177
|
+
process.exit(1);
|
|
41178
|
+
}
|
|
41179
|
+
const displayId = Number.parseInt(numericMatch[1], 10);
|
|
41180
|
+
const result = await authenticatedRequest(
|
|
41181
|
+
(client) => client.pentest.listPentests({
|
|
41182
|
+
params: { organizationId }
|
|
41183
|
+
})
|
|
41184
|
+
);
|
|
41185
|
+
if (result.status === 401) {
|
|
41186
|
+
console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
|
|
41187
|
+
process.exit(1);
|
|
41188
|
+
}
|
|
41189
|
+
if (result.status !== 200) {
|
|
41190
|
+
console.error(`Failed to list pentests (status ${result.status}).`);
|
|
41191
|
+
process.exit(1);
|
|
41192
|
+
}
|
|
41193
|
+
const pentest = result.body.find((p2) => p2.displayId === displayId);
|
|
41194
|
+
if (!pentest) {
|
|
41195
|
+
console.error(
|
|
41196
|
+
`Pentest with display ID ${displayId} not found.
|
|
41197
|
+
Run \`tracecli pentest list\` to see available pentests.`
|
|
41198
|
+
);
|
|
41199
|
+
process.exit(1);
|
|
41200
|
+
}
|
|
41201
|
+
return pentest.pentestId;
|
|
41202
|
+
}
|
|
41203
|
+
|
|
41204
|
+
// src/pentest/evidence.ts
|
|
41205
|
+
var SECTION_LIST = ValidationEvidenceSectionValues.join(", ");
|
|
41206
|
+
var KIND_LIST = PentestExploitArtifactKindValues.join(", ");
|
|
41207
|
+
function isSection(value) {
|
|
41208
|
+
return ValidationEvidenceSectionValues.includes(value);
|
|
41209
|
+
}
|
|
41210
|
+
function isKind(value) {
|
|
41211
|
+
return PentestExploitArtifactKindValues.includes(value);
|
|
41212
|
+
}
|
|
41213
|
+
function formatBytes(bytes) {
|
|
41214
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
41215
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
|
|
41216
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
41217
|
+
}
|
|
41218
|
+
async function resolveFindingId(organizationId, pentestId, identifier) {
|
|
41219
|
+
if (isUuid(identifier)) {
|
|
41220
|
+
return identifier;
|
|
41221
|
+
}
|
|
41222
|
+
const numericMatch = identifier.match(/^(?:PTF-)?(\d+)$/i);
|
|
41223
|
+
if (!numericMatch?.[1]) {
|
|
41224
|
+
console.error(
|
|
41225
|
+
colorError(
|
|
41226
|
+
`Invalid finding identifier '${sanitizeDisplay(identifier)}'. Use a finding number (e.g. PTF-7) or UUID.`
|
|
41227
|
+
)
|
|
41228
|
+
);
|
|
41229
|
+
process.exit(1);
|
|
41230
|
+
}
|
|
41231
|
+
const displayId = Number.parseInt(numericMatch[1], 10);
|
|
41232
|
+
const result = await authenticatedRequest(
|
|
41233
|
+
(client) => client.pentestFinding.listFindings({ params: { organizationId, pentestId } })
|
|
41234
|
+
);
|
|
41235
|
+
if (result.status === UNAUTHORIZED_STATUS2) {
|
|
41236
|
+
exitAuthFailed();
|
|
41237
|
+
}
|
|
41238
|
+
if (result.status !== 200) {
|
|
41239
|
+
console.error(colorError(`Failed to list findings (status ${result.status}).`));
|
|
41240
|
+
process.exit(1);
|
|
41241
|
+
}
|
|
41242
|
+
const match = result.body.find((f) => f.displayId === displayId);
|
|
41243
|
+
if (!match || !("pentestFindingId" in match)) {
|
|
41244
|
+
console.error(
|
|
41245
|
+
colorError(
|
|
41246
|
+
`No finding PTF-${displayId} in this pentest. Unpublished findings have no number yet \u2014 pass the finding UUID instead (\`tracecli pentest findings list --pentest <id> --output json\`).`
|
|
41247
|
+
)
|
|
41248
|
+
);
|
|
41249
|
+
process.exit(1);
|
|
41250
|
+
}
|
|
41251
|
+
return match.pentestFindingId;
|
|
41252
|
+
}
|
|
41253
|
+
async function runAttachEvidence(options) {
|
|
41254
|
+
if (options.section !== void 0 && !isSection(options.section)) {
|
|
41255
|
+
console.error(colorError(`Invalid --section '${sanitizeDisplay(options.section)}'.`));
|
|
41256
|
+
console.error(`Valid sections: ${SECTION_LIST}`);
|
|
41257
|
+
process.exit(1);
|
|
41258
|
+
}
|
|
41259
|
+
if (options.kind !== void 0 && !isKind(options.kind)) {
|
|
41260
|
+
console.error(colorError(`Invalid --kind '${sanitizeDisplay(options.kind)}'.`));
|
|
41261
|
+
console.error(`Valid kinds: ${KIND_LIST}`);
|
|
41262
|
+
process.exit(1);
|
|
41263
|
+
}
|
|
41264
|
+
let sizeBytes;
|
|
41265
|
+
try {
|
|
41266
|
+
const stats = statSync(options.file);
|
|
41267
|
+
if (!stats.isFile()) {
|
|
41268
|
+
console.error(colorError(`--file '${sanitizeDisplay(options.file)}' is not a regular file.`));
|
|
41269
|
+
process.exit(1);
|
|
41270
|
+
}
|
|
41271
|
+
sizeBytes = stats.size;
|
|
41272
|
+
} catch {
|
|
41273
|
+
console.error(colorError(`Cannot read --file '${sanitizeDisplay(options.file)}'.`));
|
|
41274
|
+
process.exit(1);
|
|
41275
|
+
}
|
|
41276
|
+
if (sizeBytes === 0) {
|
|
41277
|
+
console.error(colorError(`--file '${sanitizeDisplay(options.file)}' is empty.`));
|
|
41278
|
+
process.exit(1);
|
|
41279
|
+
}
|
|
41280
|
+
if (sizeBytes > MAX_STAFF_EVIDENCE_UPLOAD_BYTES) {
|
|
41281
|
+
console.error(
|
|
41282
|
+
colorError(
|
|
41283
|
+
`File is ${formatBytes(sizeBytes)}; the limit for one exhibit is ${formatBytes(MAX_STAFF_EVIDENCE_UPLOAD_BYTES)}.`
|
|
41284
|
+
)
|
|
41285
|
+
);
|
|
41286
|
+
process.exit(1);
|
|
41287
|
+
}
|
|
41288
|
+
const organizationId = await resolveOrganizationId();
|
|
41289
|
+
const pentestId = await resolvePentestId(organizationId, options.pentest);
|
|
41290
|
+
const pentestFindingId = await resolveFindingId(organizationId, pentestId, options.finding);
|
|
41291
|
+
const params = { organizationId, pentestId, pentestFindingId };
|
|
41292
|
+
const filename = basename(options.file);
|
|
41293
|
+
const slot = await authenticatedRequest(
|
|
41294
|
+
(client) => client.pentestFinding.createFindingEvidenceUpload({
|
|
41295
|
+
params,
|
|
41296
|
+
body: { filename, sizeBytes }
|
|
41297
|
+
})
|
|
41298
|
+
);
|
|
41299
|
+
if (slot.status === UNAUTHORIZED_STATUS2) {
|
|
41300
|
+
exitAuthFailed();
|
|
41301
|
+
}
|
|
41302
|
+
if (slot.status !== 201) {
|
|
41303
|
+
const { message } = readErrorFields(slot.body);
|
|
41304
|
+
console.error(
|
|
41305
|
+
colorError(message ?? `Failed to start the evidence upload (status ${slot.status}).`)
|
|
41306
|
+
);
|
|
41307
|
+
process.exit(1);
|
|
41308
|
+
}
|
|
41309
|
+
const body = readFileSync4(options.file);
|
|
41310
|
+
const put = await fetch(slot.body.uploadUrl, { method: "PUT", body: new Uint8Array(body) });
|
|
41311
|
+
if (!put.ok) {
|
|
41312
|
+
console.error(
|
|
41313
|
+
colorError(
|
|
41314
|
+
`Upload to storage failed (status ${put.status}). The upload link is short-lived \u2014 re-run the command.`
|
|
41315
|
+
)
|
|
41316
|
+
);
|
|
41317
|
+
process.exit(1);
|
|
41318
|
+
}
|
|
41319
|
+
const attached = await authenticatedRequest(
|
|
41320
|
+
(client) => client.pentestFinding.attachFindingEvidence({
|
|
41321
|
+
params,
|
|
41322
|
+
body: {
|
|
41323
|
+
key: slot.body.key,
|
|
41324
|
+
...options.caption !== void 0 ? { caption: options.caption } : {},
|
|
41325
|
+
...options.section !== void 0 && isSection(options.section) ? { section: options.section } : {},
|
|
41326
|
+
...options.kind !== void 0 && isKind(options.kind) ? { kind: options.kind } : {},
|
|
41327
|
+
...options.customerFacing ? { customerFacing: true } : {}
|
|
41328
|
+
}
|
|
41329
|
+
})
|
|
41330
|
+
);
|
|
41331
|
+
if (attached.status === UNAUTHORIZED_STATUS2) {
|
|
41332
|
+
exitAuthFailed();
|
|
41333
|
+
}
|
|
41334
|
+
if (attached.status !== 201) {
|
|
41335
|
+
const { message } = readErrorFields(attached.body);
|
|
41336
|
+
console.error(
|
|
41337
|
+
colorError(message ?? `Failed to attach the evidence (status ${attached.status}).`)
|
|
41338
|
+
);
|
|
41339
|
+
process.exit(1);
|
|
41340
|
+
}
|
|
41341
|
+
if (options.output === "json") {
|
|
41342
|
+
console.log(JSON.stringify(attached.body, null, 2));
|
|
41343
|
+
return;
|
|
41344
|
+
}
|
|
41345
|
+
const visibility = attached.body.customerFacing ? "customer-facing" : "staff-internal";
|
|
41346
|
+
const placement = attached.body.section ? ` \xB7 ${attached.body.section}` : "";
|
|
41347
|
+
console.log(
|
|
41348
|
+
colorSuccess(
|
|
41349
|
+
`Attached ${attached.body.kind} \xB7 ${formatBytes(attached.body.sizeBytes)} \xB7 ${visibility}${placement}`
|
|
41350
|
+
)
|
|
41351
|
+
);
|
|
41352
|
+
console.log(` artifact ${attached.body.artifactId}`);
|
|
41353
|
+
if (attached.body.kind === "HAR") {
|
|
41354
|
+
console.log(" HAR captures stay internal \u2014 they can carry a live session token.");
|
|
41355
|
+
} else if (!attached.body.customerFacing) {
|
|
41356
|
+
console.log(" Publish it from the finding\u2019s evidence panel in the staff console.");
|
|
41357
|
+
}
|
|
41358
|
+
}
|
|
41359
|
+
function createAttachEvidenceCommand() {
|
|
41360
|
+
return new Command("attach-evidence").description("Attach a screenshot, recording, or capture to a pentest finding (staff)").requiredOption("--pentest <id>", "Pentest display ID (e.g. PT-3) or UUID").requiredOption("--finding <id>", "Finding number (e.g. PTF-7) or UUID").requiredOption("--file <path>", "Path to the evidence file").option("--caption <text>", "What the exhibit shows; rendered as its label").option("--section <section>", `Report section it backs (${SECTION_LIST})`).option("--kind <kind>", `Override the derived exhibit kind (${KIND_LIST})`).option("--customer-facing", "Publish to the customer (not allowed for HAR or video)").option("-o, --output <format>", "Output format: text, json (default: text)", "text").addHelpText(
|
|
41361
|
+
"after",
|
|
41362
|
+
`
|
|
41363
|
+
The file uploads straight to storage, so recordings of any reasonable size work.
|
|
41364
|
+
Videos and HAR captures always land staff-internal \u2014 publish a video with the
|
|
41365
|
+
toggle in the staff console's evidence panel after reviewing it for redaction.
|
|
41366
|
+
|
|
41367
|
+
Examples:
|
|
41368
|
+
tracecli pentest findings attach-evidence --pentest PT-3 --finding 7 --file ./poc.png
|
|
41369
|
+
tracecli pentest findings attach-evidence --pentest PT-3 --finding PTF-7 --file ./poc.mov \\
|
|
41370
|
+
--caption "Cookie survives logout, replayed 40s later" --section proofOfConcept
|
|
41371
|
+
tracecli pentest findings attach-evidence --pentest PT-3 --finding 7 --file ./roster.json \\
|
|
41372
|
+
--caption "Full member roster returned to a non-member" --customer-facing --output json`
|
|
41373
|
+
).action(async (options) => {
|
|
41374
|
+
await runAttachEvidence(options);
|
|
41375
|
+
});
|
|
41376
|
+
}
|
|
40454
41377
|
|
|
40455
41378
|
// src/pentest/questionnaire.ts
|
|
40456
41379
|
function buildUpsertQuestionnaireBody(answers) {
|
|
@@ -40533,9 +41456,9 @@ function formatAnswerValue(key, answers) {
|
|
|
40533
41456
|
}
|
|
40534
41457
|
}
|
|
40535
41458
|
function formatQuestionnaireShow(input) {
|
|
40536
|
-
const
|
|
40537
|
-
|
|
40538
|
-
];
|
|
41459
|
+
const submitted = input.submitted === true;
|
|
41460
|
+
const editableLine = input.editable ? "yes (scoping window open)" : submitted ? "no (submitted)" : "no (editing closed after scoping)";
|
|
41461
|
+
const lines = [`Editable: ${editableLine}`, `Submitted: ${submitted ? "yes" : "no"}`];
|
|
40539
41462
|
if (input.answers === null || Object.keys(input.answers).length === 0) {
|
|
40540
41463
|
lines.push("Answers: (none)");
|
|
40541
41464
|
return lines.join("\n");
|
|
@@ -40595,43 +41518,7 @@ function formatFindingSeverity(severity) {
|
|
|
40595
41518
|
return severity;
|
|
40596
41519
|
}
|
|
40597
41520
|
}
|
|
40598
|
-
|
|
40599
|
-
async function resolvePentestId(organizationId, identifier) {
|
|
40600
|
-
if (UUID_PATTERN2.test(identifier)) {
|
|
40601
|
-
return identifier;
|
|
40602
|
-
}
|
|
40603
|
-
const numericMatch = identifier.match(/^(?:PT-)?(\d+)$/i);
|
|
40604
|
-
if (!numericMatch?.[1]) {
|
|
40605
|
-
console.error(
|
|
40606
|
-
`Invalid pentest identifier '${identifier}'. Use a display ID (e.g. PT-3) or UUID.`
|
|
40607
|
-
);
|
|
40608
|
-
process.exit(1);
|
|
40609
|
-
}
|
|
40610
|
-
const displayId = Number.parseInt(numericMatch[1], 10);
|
|
40611
|
-
const result = await authenticatedRequest(
|
|
40612
|
-
(client) => client.pentest.listPentests({
|
|
40613
|
-
params: { organizationId }
|
|
40614
|
-
})
|
|
40615
|
-
);
|
|
40616
|
-
if (result.status === 401) {
|
|
40617
|
-
console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
|
|
40618
|
-
process.exit(1);
|
|
40619
|
-
}
|
|
40620
|
-
if (result.status !== 200) {
|
|
40621
|
-
console.error(`Failed to list pentests (status ${result.status}).`);
|
|
40622
|
-
process.exit(1);
|
|
40623
|
-
}
|
|
40624
|
-
const pentest = result.body.find((p2) => p2.displayId === displayId);
|
|
40625
|
-
if (!pentest) {
|
|
40626
|
-
console.error(
|
|
40627
|
-
`Pentest with display ID ${displayId} not found.
|
|
40628
|
-
Run \`tracecli pentest list\` to see available pentests.`
|
|
40629
|
-
);
|
|
40630
|
-
process.exit(1);
|
|
40631
|
-
}
|
|
40632
|
-
return pentest.pentestId;
|
|
40633
|
-
}
|
|
40634
|
-
function createListCommand5() {
|
|
41521
|
+
function createListCommand6() {
|
|
40635
41522
|
return new Command("list").description("List pentests for your organization").option(
|
|
40636
41523
|
"--status <status>",
|
|
40637
41524
|
"Filter by status (SCOPING, IN_PROGRESS, REMEDIATION, CLOSED)",
|
|
@@ -40881,6 +41768,7 @@ function renderPentestFindingLines(finding) {
|
|
|
40881
41768
|
function createFindingsCommand() {
|
|
40882
41769
|
const findings = new Command("findings").description("Manage pentest findings");
|
|
40883
41770
|
findings.addCommand(createFindingsListCommand());
|
|
41771
|
+
findings.addCommand(createAttachEvidenceCommand());
|
|
40884
41772
|
return findings;
|
|
40885
41773
|
}
|
|
40886
41774
|
var PRIORITY_SET = new Set(CustomerPriorityCategoryValues);
|
|
@@ -41151,7 +42039,7 @@ async function fetchQuestionnaire(organizationId, pentestId, notFoundLabel) {
|
|
|
41151
42039
|
if (result.status !== SUCCESS_STATUS) {
|
|
41152
42040
|
failQuestionnaire(result.status, result.body, "read", notFoundLabel);
|
|
41153
42041
|
}
|
|
41154
|
-
return result.body;
|
|
42042
|
+
return toQuestionnaireGetBody(result.body);
|
|
41155
42043
|
}
|
|
41156
42044
|
async function putQuestionnaire(organizationId, pentestId, answers, notFoundLabel) {
|
|
41157
42045
|
const body = buildUpsertQuestionnaireBody(answers);
|
|
@@ -41164,7 +42052,35 @@ async function putQuestionnaire(organizationId, pentestId, answers, notFoundLabe
|
|
|
41164
42052
|
if (result.status !== SUCCESS_STATUS) {
|
|
41165
42053
|
failQuestionnaire(result.status, result.body, "write", notFoundLabel);
|
|
41166
42054
|
}
|
|
41167
|
-
return result.body;
|
|
42055
|
+
return toQuestionnaireGetBody(result.body);
|
|
42056
|
+
}
|
|
42057
|
+
async function submitQuestionnaire(organizationId, pentestId, answers, notFoundLabel) {
|
|
42058
|
+
const result = await authenticatedRequest(
|
|
42059
|
+
(client) => client.pentest.submitCustomerPentestQuestionnaire({
|
|
42060
|
+
params: { organizationId, pentestId },
|
|
42061
|
+
body: answers === void 0 ? {} : { answers }
|
|
42062
|
+
})
|
|
42063
|
+
);
|
|
42064
|
+
if (result.status !== SUCCESS_STATUS) {
|
|
42065
|
+
failQuestionnaire(result.status, result.body, "write", notFoundLabel);
|
|
42066
|
+
}
|
|
42067
|
+
return toQuestionnaireGetBody(result.body);
|
|
42068
|
+
}
|
|
42069
|
+
function toQuestionnaireGetBody(body) {
|
|
42070
|
+
return {
|
|
42071
|
+
pentestId: body.pentestId,
|
|
42072
|
+
editable: body.editable,
|
|
42073
|
+
answers: body.answers,
|
|
42074
|
+
updatedAt: body.updatedAt,
|
|
42075
|
+
...body.submittedAt !== void 0 ? { submittedAt: body.submittedAt } : {}
|
|
42076
|
+
};
|
|
42077
|
+
}
|
|
42078
|
+
function questionnaireShowInput(body) {
|
|
42079
|
+
return {
|
|
42080
|
+
answers: body.answers,
|
|
42081
|
+
editable: body.editable,
|
|
42082
|
+
submitted: body.submittedAt != null
|
|
42083
|
+
};
|
|
41168
42084
|
}
|
|
41169
42085
|
function exitCancelled() {
|
|
41170
42086
|
me("Cancelled.");
|
|
@@ -41230,15 +42146,20 @@ async function promptQuestionnaireAnswers(existing) {
|
|
|
41230
42146
|
async function runQuestionnaire(pentestIdentifier, options) {
|
|
41231
42147
|
const show = options.show === true;
|
|
41232
42148
|
const filePath = options.file;
|
|
42149
|
+
const submit = options.submit === true;
|
|
41233
42150
|
if (show && filePath !== void 0) {
|
|
41234
42151
|
console.error(colorError("Pass only one of --show / --file."));
|
|
41235
42152
|
process.exit(1);
|
|
41236
42153
|
}
|
|
42154
|
+
if (show && submit) {
|
|
42155
|
+
console.error(colorError("Pass only one of --show / --submit."));
|
|
42156
|
+
process.exit(1);
|
|
42157
|
+
}
|
|
41237
42158
|
const isInteractiveTty = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
41238
|
-
if (!show && filePath === void 0 && !isInteractiveTty) {
|
|
42159
|
+
if (!show && filePath === void 0 && !submit && !isInteractiveTty) {
|
|
41239
42160
|
console.error(
|
|
41240
42161
|
colorError(
|
|
41241
|
-
"Interactive questionnaire requires a TTY. Use --show to print answers,
|
|
42162
|
+
"Interactive questionnaire requires a TTY. Use --show to print answers, --file <path> to upload an answers JSON object, or --submit to freeze the current answers."
|
|
41242
42163
|
)
|
|
41243
42164
|
);
|
|
41244
42165
|
process.exit(2);
|
|
@@ -41247,18 +42168,13 @@ async function runQuestionnaire(pentestIdentifier, options) {
|
|
|
41247
42168
|
const pentestId = await resolvePentestId(organizationId, pentestIdentifier);
|
|
41248
42169
|
if (show) {
|
|
41249
42170
|
const current2 = await fetchQuestionnaire(organizationId, pentestId, pentestIdentifier);
|
|
41250
|
-
console.log(
|
|
41251
|
-
formatQuestionnaireShow({
|
|
41252
|
-
answers: current2.answers,
|
|
41253
|
-
editable: current2.editable
|
|
41254
|
-
})
|
|
41255
|
-
);
|
|
42171
|
+
console.log(formatQuestionnaireShow(questionnaireShowInput(current2)));
|
|
41256
42172
|
return;
|
|
41257
42173
|
}
|
|
41258
42174
|
if (filePath !== void 0) {
|
|
41259
42175
|
let raw;
|
|
41260
42176
|
try {
|
|
41261
|
-
raw =
|
|
42177
|
+
raw = readFileSync5(filePath, "utf8");
|
|
41262
42178
|
} catch {
|
|
41263
42179
|
console.error(colorError(`Could not read answers file: ${filePath}`));
|
|
41264
42180
|
process.exit(1);
|
|
@@ -41268,26 +42184,31 @@ async function runQuestionnaire(pentestIdentifier, options) {
|
|
|
41268
42184
|
console.error(colorError(parsed.error));
|
|
41269
42185
|
process.exit(1);
|
|
41270
42186
|
}
|
|
41271
|
-
const saved2 = await putQuestionnaire(
|
|
42187
|
+
const saved2 = submit ? await submitQuestionnaire(organizationId, pentestId, parsed.answers, pentestIdentifier) : await putQuestionnaire(organizationId, pentestId, parsed.answers, pentestIdentifier);
|
|
42188
|
+
console.log(
|
|
42189
|
+
colorSuccess(
|
|
42190
|
+
submit ? "Submitted questionnaire. Answers are locked." : "Saved questionnaire answers."
|
|
42191
|
+
)
|
|
42192
|
+
);
|
|
42193
|
+
console.log(formatQuestionnaireShow(questionnaireShowInput(saved2)));
|
|
42194
|
+
return;
|
|
42195
|
+
}
|
|
42196
|
+
if (submit) {
|
|
42197
|
+
const submitted = await submitQuestionnaire(
|
|
41272
42198
|
organizationId,
|
|
41273
42199
|
pentestId,
|
|
41274
|
-
|
|
42200
|
+
void 0,
|
|
41275
42201
|
pentestIdentifier
|
|
41276
42202
|
);
|
|
41277
|
-
console.log(colorSuccess("
|
|
41278
|
-
console.log(
|
|
41279
|
-
formatQuestionnaireShow({
|
|
41280
|
-
answers: saved2.answers,
|
|
41281
|
-
editable: saved2.editable
|
|
41282
|
-
})
|
|
41283
|
-
);
|
|
42203
|
+
console.log(colorSuccess("Submitted questionnaire. Answers are locked."));
|
|
42204
|
+
console.log(formatQuestionnaireShow(questionnaireShowInput(submitted)));
|
|
41284
42205
|
return;
|
|
41285
42206
|
}
|
|
41286
42207
|
const current = await fetchQuestionnaire(organizationId, pentestId, pentestIdentifier);
|
|
41287
42208
|
if (!current.editable) {
|
|
41288
42209
|
console.error(
|
|
41289
42210
|
colorError(
|
|
41290
|
-
"Questionnaire editing is closed after scoping starts. Use --show to view the saved answers."
|
|
42211
|
+
current.submittedAt != null ? "Questionnaire has already been submitted. Use --show to view the saved answers." : "Questionnaire editing is closed after scoping starts. Use --show to view the saved answers."
|
|
41291
42212
|
)
|
|
41292
42213
|
);
|
|
41293
42214
|
process.exit(1);
|
|
@@ -41295,35 +42216,33 @@ async function runQuestionnaire(pentestIdentifier, options) {
|
|
|
41295
42216
|
const merged = await promptQuestionnaireAnswers(current.answers);
|
|
41296
42217
|
const saved = await putQuestionnaire(organizationId, pentestId, merged, pentestIdentifier);
|
|
41297
42218
|
console.log(colorSuccess("Saved questionnaire answers."));
|
|
41298
|
-
console.log(
|
|
41299
|
-
formatQuestionnaireShow({
|
|
41300
|
-
answers: saved.answers,
|
|
41301
|
-
editable: saved.editable
|
|
41302
|
-
})
|
|
41303
|
-
);
|
|
42219
|
+
console.log(formatQuestionnaireShow(questionnaireShowInput(saved)));
|
|
41304
42220
|
}
|
|
41305
42221
|
function createQuestionnaireCommand() {
|
|
41306
42222
|
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(
|
|
41307
42223
|
"--file <path>",
|
|
41308
42224
|
"Upload answers from a JSON file (answers object only \u2014 not { answers }; whole-object replace)"
|
|
41309
|
-
).addHelpText(
|
|
42225
|
+
).option("--submit", "Freeze the questionnaire after saving (or freeze the current answers)").addHelpText(
|
|
41310
42226
|
"after",
|
|
41311
42227
|
`
|
|
41312
42228
|
Optional scoping questionnaire for a new pentest (editable while stage is DRAFT
|
|
41313
|
-
or READY_TO_START). Reads accept a browser session or API key;
|
|
41314
|
-
organization admin (or Trace staff) signed in via \`tracecli
|
|
41315
|
-
keys are rejected.
|
|
42229
|
+
or READY_TO_START, until submitted). Reads accept a browser session or API key;
|
|
42230
|
+
writes require an organization admin (or Trace staff) signed in via \`tracecli
|
|
42231
|
+
auth login\` \u2014 API keys are rejected.
|
|
41316
42232
|
|
|
41317
42233
|
Modes:
|
|
41318
42234
|
--show GET and print key: value with shared customer-facing labels
|
|
41319
42235
|
--file <path> PUT the file's answers object (CLI wraps { answers } for the API)
|
|
42236
|
+
--submit Freeze answers (combine with --file or TTY fill, or alone to freeze current)
|
|
41320
42237
|
(TTY default) load-merge-write: GET, prompt each question, confirm, PUT
|
|
41321
42238
|
|
|
41322
|
-
Non-interactive shells must pass --show or --
|
|
42239
|
+
Non-interactive shells must pass --show, --file, or --submit (exit 2 otherwise).
|
|
41323
42240
|
|
|
41324
42241
|
Examples:
|
|
41325
42242
|
tracecli pentest questionnaire PT-1 --show
|
|
41326
42243
|
tracecli pentest questionnaire PT-1 --file answers.json
|
|
42244
|
+
tracecli pentest questionnaire PT-1 --file answers.json --submit
|
|
42245
|
+
tracecli pentest questionnaire PT-1 --submit
|
|
41327
42246
|
tracecli pentest questionnaire PT-1`
|
|
41328
42247
|
).action(async (pentestId, options) => {
|
|
41329
42248
|
await runQuestionnaire(pentestId, options);
|
|
@@ -41331,7 +42250,7 @@ Examples:
|
|
|
41331
42250
|
}
|
|
41332
42251
|
function createPentestCommand() {
|
|
41333
42252
|
const pentest = new Command("pentest").description("Manage pentests");
|
|
41334
|
-
pentest.addCommand(
|
|
42253
|
+
pentest.addCommand(createListCommand6());
|
|
41335
42254
|
pentest.addCommand(createUpdateCommand4());
|
|
41336
42255
|
pentest.addCommand(createQuestionnaireCommand());
|
|
41337
42256
|
pentest.addCommand(createFindingsCommand());
|
|
@@ -41339,7 +42258,7 @@ function createPentestCommand() {
|
|
|
41339
42258
|
}
|
|
41340
42259
|
|
|
41341
42260
|
// src/update/commands.ts
|
|
41342
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as
|
|
42261
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
41343
42262
|
import { dirname as dirname2, join as join5 } from "path";
|
|
41344
42263
|
import { createInterface as createInterface4 } from "readline/promises";
|
|
41345
42264
|
var UPDATE_CACHE_FILE = "update-check.json";
|
|
@@ -41357,7 +42276,7 @@ function readUpdateCheckCache() {
|
|
|
41357
42276
|
return null;
|
|
41358
42277
|
}
|
|
41359
42278
|
try {
|
|
41360
|
-
const rawCache =
|
|
42279
|
+
const rawCache = readFileSync6(cachePath, "utf-8");
|
|
41361
42280
|
const parsed = JSON.parse(rawCache);
|
|
41362
42281
|
if (typeof parsed !== "object" || parsed === null) {
|
|
41363
42282
|
return null;
|
|
@@ -41956,7 +42875,7 @@ Run \`tracecli vulnerabilities list\` to see available vulnerabilities.`
|
|
|
41956
42875
|
printVulnerabilityDetail(result.body);
|
|
41957
42876
|
});
|
|
41958
42877
|
}
|
|
41959
|
-
function
|
|
42878
|
+
function createListCommand7() {
|
|
41960
42879
|
return new Command("list").description("List vulnerabilities for your organization").option("--repo <repo>", "Filter by repository name or owner/repo").option(
|
|
41961
42880
|
"--severity <severity>",
|
|
41962
42881
|
"Filter by severity (CRITICAL, HIGH, MEDIUM, LOW)",
|
|
@@ -42090,7 +43009,7 @@ Examples:
|
|
|
42090
43009
|
function createVulnerabilitiesCommand() {
|
|
42091
43010
|
const vulnerabilities = new Command("vulnerabilities").description("Manage vulnerabilities");
|
|
42092
43011
|
vulnerabilities.addCommand(createGetCommand4());
|
|
42093
|
-
vulnerabilities.addCommand(
|
|
43012
|
+
vulnerabilities.addCommand(createListCommand7());
|
|
42094
43013
|
return vulnerabilities;
|
|
42095
43014
|
}
|
|
42096
43015
|
|
|
@@ -42111,6 +43030,7 @@ program2.addCommand(createEnvironmentCommand());
|
|
|
42111
43030
|
program2.addCommand(createCredentialCommand());
|
|
42112
43031
|
program2.addCommand(createRepoCommand());
|
|
42113
43032
|
program2.addCommand(createVulnerabilitiesCommand());
|
|
43033
|
+
program2.addCommand(createCodeSizeCommand());
|
|
42114
43034
|
program2.addCommand(createPentestCommand());
|
|
42115
43035
|
program2.addCommand(createCompletionCommand(program2));
|
|
42116
43036
|
program2.addCommand(createUpgradeCommand());
|