@postman-cse/onboarding-bootstrap 0.14.2 → 0.15.2
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/action.yml +4 -0
- package/dist/action.cjs +454 -90
- package/dist/cli.cjs +454 -90
- package/dist/index.cjs +454 -90
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -45095,6 +45095,12 @@ var customerPreviewActionContract = {
|
|
|
45095
45095
|
description: "Postman access token used for governance and workspace mutations.",
|
|
45096
45096
|
required: false
|
|
45097
45097
|
},
|
|
45098
|
+
"credential-preflight": {
|
|
45099
|
+
description: "Credential identity preflight policy. warn (default) logs a note and continues when postman-api-key and postman-access-token resolve to different parent orgs; enforce fails the run on that condition before any workspace is created; off skips the identity probes entirely (the reactive error guidance still applies). Promotion of the default to enforce is planned once the live e2e legs prove both directions.",
|
|
45100
|
+
required: false,
|
|
45101
|
+
default: "warn",
|
|
45102
|
+
allowedValues: ["enforce", "warn", "off"]
|
|
45103
|
+
},
|
|
45098
45104
|
"integration-backend": {
|
|
45099
45105
|
description: "Integration backend for downstream workspace connectivity.",
|
|
45100
45106
|
required: false,
|
|
@@ -46118,13 +46124,15 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
46118
46124
|
apiBaseUrl: "https://api.getpostman.com",
|
|
46119
46125
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
46120
46126
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
46121
|
-
gatewayBaseUrl: "https://gateway.postman.com"
|
|
46127
|
+
gatewayBaseUrl: "https://gateway.postman.com",
|
|
46128
|
+
iapubBaseUrl: "https://iapub.postman.co"
|
|
46122
46129
|
},
|
|
46123
46130
|
beta: {
|
|
46124
46131
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
46125
46132
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
46126
46133
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
46127
|
-
gatewayBaseUrl: "https://gateway.postman-beta.com"
|
|
46134
|
+
gatewayBaseUrl: "https://gateway.postman-beta.com",
|
|
46135
|
+
iapubBaseUrl: "https://iapub.postman.co"
|
|
46128
46136
|
}
|
|
46129
46137
|
};
|
|
46130
46138
|
function parsePostmanStack(value) {
|
|
@@ -46138,6 +46146,313 @@ function resolvePostmanEndpointProfile(stack) {
|
|
|
46138
46146
|
return POSTMAN_ENDPOINT_PROFILES[stack];
|
|
46139
46147
|
}
|
|
46140
46148
|
|
|
46149
|
+
// src/lib/postman/credential-identity.ts
|
|
46150
|
+
var sessionPath = "/api/sessions/current";
|
|
46151
|
+
var pmakMemo = /* @__PURE__ */ new Map();
|
|
46152
|
+
var sessionMemo = /* @__PURE__ */ new Map();
|
|
46153
|
+
var memoizedSessionIdentity;
|
|
46154
|
+
function getMemoizedSessionIdentity() {
|
|
46155
|
+
return memoizedSessionIdentity;
|
|
46156
|
+
}
|
|
46157
|
+
function asRecord(value) {
|
|
46158
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
46159
|
+
return void 0;
|
|
46160
|
+
}
|
|
46161
|
+
return value;
|
|
46162
|
+
}
|
|
46163
|
+
function coerceId(raw) {
|
|
46164
|
+
return raw ? String(raw) : void 0;
|
|
46165
|
+
}
|
|
46166
|
+
function coerceText(raw) {
|
|
46167
|
+
if (typeof raw !== "string") {
|
|
46168
|
+
return void 0;
|
|
46169
|
+
}
|
|
46170
|
+
const trimmed = raw.trim();
|
|
46171
|
+
return trimmed ? trimmed : void 0;
|
|
46172
|
+
}
|
|
46173
|
+
function normalizeBaseUrl(raw) {
|
|
46174
|
+
return String(raw || "").replace(/\/+$/, "");
|
|
46175
|
+
}
|
|
46176
|
+
async function resolvePmakIdentity(opts) {
|
|
46177
|
+
const apiKey = String(opts.apiKey || "").trim();
|
|
46178
|
+
if (!apiKey) {
|
|
46179
|
+
return void 0;
|
|
46180
|
+
}
|
|
46181
|
+
const baseUrl = normalizeBaseUrl(opts.apiBaseUrl);
|
|
46182
|
+
const memoKey = `${baseUrl}::${apiKey}`;
|
|
46183
|
+
let pending = pmakMemo.get(memoKey);
|
|
46184
|
+
if (!pending) {
|
|
46185
|
+
pending = probePmakIdentity(baseUrl, apiKey, opts.fetchImpl ?? fetch);
|
|
46186
|
+
pmakMemo.set(memoKey, pending);
|
|
46187
|
+
}
|
|
46188
|
+
return pending;
|
|
46189
|
+
}
|
|
46190
|
+
async function probePmakIdentity(baseUrl, apiKey, fetchImpl) {
|
|
46191
|
+
try {
|
|
46192
|
+
const response = await fetchImpl(`${baseUrl}/me`, {
|
|
46193
|
+
method: "GET",
|
|
46194
|
+
headers: { "X-Api-Key": apiKey }
|
|
46195
|
+
});
|
|
46196
|
+
if (!response.ok) {
|
|
46197
|
+
return void 0;
|
|
46198
|
+
}
|
|
46199
|
+
const payload = asRecord(await response.json());
|
|
46200
|
+
const user = asRecord(payload?.user);
|
|
46201
|
+
if (!user) {
|
|
46202
|
+
return void 0;
|
|
46203
|
+
}
|
|
46204
|
+
return {
|
|
46205
|
+
source: "pmak/me",
|
|
46206
|
+
userId: coerceId(user.id),
|
|
46207
|
+
fullName: coerceText(user.fullName) ?? coerceText(user.username),
|
|
46208
|
+
teamId: coerceId(user.teamId),
|
|
46209
|
+
teamName: coerceText(user.teamName),
|
|
46210
|
+
teamDomain: coerceText(user.teamDomain)
|
|
46211
|
+
};
|
|
46212
|
+
} catch {
|
|
46213
|
+
return void 0;
|
|
46214
|
+
}
|
|
46215
|
+
}
|
|
46216
|
+
async function resolveSessionIdentity(opts) {
|
|
46217
|
+
const accessToken = String(opts.accessToken || "").trim();
|
|
46218
|
+
if (!accessToken) {
|
|
46219
|
+
return void 0;
|
|
46220
|
+
}
|
|
46221
|
+
const baseUrl = normalizeBaseUrl(opts.iapubBaseUrl);
|
|
46222
|
+
const memoKey = `${baseUrl}::${accessToken}`;
|
|
46223
|
+
let pending = sessionMemo.get(memoKey);
|
|
46224
|
+
if (!pending) {
|
|
46225
|
+
pending = probeSessionIdentity(baseUrl, accessToken, opts.fetchImpl ?? fetch);
|
|
46226
|
+
sessionMemo.set(memoKey, pending);
|
|
46227
|
+
}
|
|
46228
|
+
return pending;
|
|
46229
|
+
}
|
|
46230
|
+
async function probeSessionIdentity(baseUrl, accessToken, fetchImpl) {
|
|
46231
|
+
try {
|
|
46232
|
+
const response = await fetchImpl(`${baseUrl}${sessionPath}`, {
|
|
46233
|
+
method: "GET",
|
|
46234
|
+
headers: { "x-access-token": accessToken }
|
|
46235
|
+
});
|
|
46236
|
+
if (!response.ok) {
|
|
46237
|
+
return void 0;
|
|
46238
|
+
}
|
|
46239
|
+
const payload = asRecord(await response.json());
|
|
46240
|
+
if (!payload) {
|
|
46241
|
+
return void 0;
|
|
46242
|
+
}
|
|
46243
|
+
const root = asRecord(payload.session) ?? payload;
|
|
46244
|
+
const identity = asRecord(root.identity);
|
|
46245
|
+
const data = asRecord(root.data);
|
|
46246
|
+
const user = asRecord(data?.user);
|
|
46247
|
+
const roleEntries = Array.isArray(user?.roles) ? user.roles.map((entry) => coerceText(entry) ?? coerceId(entry)).filter((entry) => Boolean(entry)) : [];
|
|
46248
|
+
const singleRole = coerceText(user?.role);
|
|
46249
|
+
const roles = roleEntries.length > 0 ? roleEntries : singleRole ? [singleRole] : void 0;
|
|
46250
|
+
const resolved = {
|
|
46251
|
+
source: "iapub/sessions",
|
|
46252
|
+
userId: coerceId(identity?.user) ?? coerceId(user?.id),
|
|
46253
|
+
fullName: coerceText(user?.fullName) ?? coerceText(user?.name) ?? coerceText(user?.username),
|
|
46254
|
+
teamId: coerceId(identity?.team),
|
|
46255
|
+
teamName: coerceText(user?.teamName),
|
|
46256
|
+
teamDomain: coerceText(identity?.domain),
|
|
46257
|
+
...roles ? { roles } : {},
|
|
46258
|
+
consumerType: coerceText(root.consumerType) ?? coerceText(data?.consumerType) ?? coerceText(user?.consumerType)
|
|
46259
|
+
};
|
|
46260
|
+
memoizedSessionIdentity = resolved;
|
|
46261
|
+
return resolved;
|
|
46262
|
+
} catch {
|
|
46263
|
+
return void 0;
|
|
46264
|
+
}
|
|
46265
|
+
}
|
|
46266
|
+
function describeTeam(id) {
|
|
46267
|
+
const label = id?.teamName ?? id?.teamDomain;
|
|
46268
|
+
return `team ${id?.teamId ?? "unresolved"}${label ? ` (${label})` : ""}`;
|
|
46269
|
+
}
|
|
46270
|
+
function formatIdentityLine(id, mask) {
|
|
46271
|
+
const teamPart = id.teamId ? describeTeam(id) : "team unresolved";
|
|
46272
|
+
const domainPart = id.teamDomain ? `, domain ${id.teamDomain}` : "";
|
|
46273
|
+
if (id.source === "pmak/me") {
|
|
46274
|
+
const userPart = id.userId ? `user ${id.userId}${id.fullName ? ` (${id.fullName})` : ""}, ` : "";
|
|
46275
|
+
return mask(`postman: PMAK identity - ${userPart}${teamPart}${domainPart}`);
|
|
46276
|
+
}
|
|
46277
|
+
return mask(
|
|
46278
|
+
`postman: access-token session identity - ${teamPart}${domainPart} [source: iapub/sessions]`
|
|
46279
|
+
);
|
|
46280
|
+
}
|
|
46281
|
+
function crossCheckIdentities(args) {
|
|
46282
|
+
if (args.mode === "off") {
|
|
46283
|
+
return { ok: true, level: "ok", message: "" };
|
|
46284
|
+
}
|
|
46285
|
+
const pmakTeamId = args.pmak?.teamId;
|
|
46286
|
+
const sessionTeamId = args.session?.teamId;
|
|
46287
|
+
if (pmakTeamId && sessionTeamId && pmakTeamId !== sessionTeamId) {
|
|
46288
|
+
const level = args.mode === "enforce" ? "fail" : "note";
|
|
46289
|
+
const lead = level === "fail" ? "credential preflight FAILED" : "credential preflight note";
|
|
46290
|
+
const fix = level === "fail" ? "Use one credential pair from a single parent org: re-mint the access token from the same parent org as postman-api-key (postman-resolve-service-token-action, or POST https://api.getpostman.com/service-account-tokens with that team's PMAK), or set postman-api-key to the matching parent org." : "Use one credential pair from a single parent org. Set credential-preflight: enforce to fail the run on this condition.";
|
|
46291
|
+
return {
|
|
46292
|
+
ok: false,
|
|
46293
|
+
level,
|
|
46294
|
+
message: args.mask(
|
|
46295
|
+
`postman: ${lead} - PMAK belongs to ${describeTeam(args.pmak)} but the access token's session belongs to a different parent org, ${describeTeam(args.session)}. Assets would be created against one team while Bifrost linking and governance act under the other, producing duplicate-link 400s and workspaces not visible to the other credential. ` + fix
|
|
46296
|
+
)
|
|
46297
|
+
};
|
|
46298
|
+
}
|
|
46299
|
+
if (pmakTeamId && sessionTeamId) {
|
|
46300
|
+
const scope = args.workspaceTeamId || args.explicitTeamId ? "parent org team" : "team";
|
|
46301
|
+
const label = args.pmak?.teamName ?? args.pmak?.teamDomain ?? args.session?.teamName ?? args.session?.teamDomain;
|
|
46302
|
+
return {
|
|
46303
|
+
ok: true,
|
|
46304
|
+
level: "ok",
|
|
46305
|
+
message: args.mask(
|
|
46306
|
+
`postman: credential preflight OK - PMAK and access token both resolve to ${scope} ${pmakTeamId}${label ? ` (${label})` : ""}`
|
|
46307
|
+
)
|
|
46308
|
+
};
|
|
46309
|
+
}
|
|
46310
|
+
const missing = [
|
|
46311
|
+
!pmakTeamId ? "PMAK identity" : void 0,
|
|
46312
|
+
!sessionTeamId ? "access-token session identity" : void 0
|
|
46313
|
+
].filter(Boolean).join(" and ");
|
|
46314
|
+
return {
|
|
46315
|
+
ok: false,
|
|
46316
|
+
level: "note",
|
|
46317
|
+
message: args.mask(
|
|
46318
|
+
`postman: credential preflight note - cross-check skipped because the ${missing} did not resolve a team id; continuing with reactive error guidance only`
|
|
46319
|
+
)
|
|
46320
|
+
};
|
|
46321
|
+
}
|
|
46322
|
+
async function runCredentialPreflight(args) {
|
|
46323
|
+
if (args.mode === "off") {
|
|
46324
|
+
return;
|
|
46325
|
+
}
|
|
46326
|
+
const mask = args.mask;
|
|
46327
|
+
const apiKey = String(args.postmanApiKey || "").trim();
|
|
46328
|
+
const accessToken = String(args.postmanAccessToken || "").trim();
|
|
46329
|
+
let pmak;
|
|
46330
|
+
if (apiKey) {
|
|
46331
|
+
try {
|
|
46332
|
+
pmak = await resolvePmakIdentity({
|
|
46333
|
+
apiBaseUrl: args.apiBaseUrl,
|
|
46334
|
+
apiKey,
|
|
46335
|
+
fetchImpl: args.fetchImpl
|
|
46336
|
+
});
|
|
46337
|
+
} catch (error) {
|
|
46338
|
+
args.log.warning(
|
|
46339
|
+
mask(
|
|
46340
|
+
`postman: credential preflight could not resolve PMAK identity: ${error instanceof Error ? error.message : String(error)}`
|
|
46341
|
+
)
|
|
46342
|
+
);
|
|
46343
|
+
}
|
|
46344
|
+
if (pmak) {
|
|
46345
|
+
args.log.info(formatIdentityLine(pmak, mask));
|
|
46346
|
+
} else {
|
|
46347
|
+
args.log.warning(
|
|
46348
|
+
mask("postman: credential preflight could not resolve PMAK identity from GET /me; continuing")
|
|
46349
|
+
);
|
|
46350
|
+
}
|
|
46351
|
+
}
|
|
46352
|
+
if (!accessToken) {
|
|
46353
|
+
args.log.info(mask("postman: Bifrost diagnostics limited: no access token"));
|
|
46354
|
+
return;
|
|
46355
|
+
}
|
|
46356
|
+
let session;
|
|
46357
|
+
try {
|
|
46358
|
+
session = await resolveSessionIdentity({
|
|
46359
|
+
iapubBaseUrl: args.iapubBaseUrl,
|
|
46360
|
+
accessToken,
|
|
46361
|
+
fetchImpl: args.fetchImpl
|
|
46362
|
+
});
|
|
46363
|
+
} catch (error) {
|
|
46364
|
+
args.log.warning(
|
|
46365
|
+
mask(
|
|
46366
|
+
`postman: credential preflight could not resolve access-token session identity: ${error instanceof Error ? error.message : String(error)}`
|
|
46367
|
+
)
|
|
46368
|
+
);
|
|
46369
|
+
}
|
|
46370
|
+
if (session) {
|
|
46371
|
+
args.log.info(formatIdentityLine(session, mask));
|
|
46372
|
+
} else {
|
|
46373
|
+
args.log.warning(
|
|
46374
|
+
mask(
|
|
46375
|
+
"postman: credential preflight could not resolve the access-token session identity from iapub; continuing with reactive error guidance only"
|
|
46376
|
+
)
|
|
46377
|
+
);
|
|
46378
|
+
}
|
|
46379
|
+
const result = crossCheckIdentities({
|
|
46380
|
+
pmak,
|
|
46381
|
+
session,
|
|
46382
|
+
workspaceTeamId: args.workspaceTeamId,
|
|
46383
|
+
explicitTeamId: args.explicitTeamId,
|
|
46384
|
+
mode: args.mode,
|
|
46385
|
+
mask
|
|
46386
|
+
});
|
|
46387
|
+
if (!result.message) {
|
|
46388
|
+
return;
|
|
46389
|
+
}
|
|
46390
|
+
if (result.level === "fail") {
|
|
46391
|
+
throw new Error(result.message);
|
|
46392
|
+
}
|
|
46393
|
+
if (result.level === "note") {
|
|
46394
|
+
args.log.warning(result.message);
|
|
46395
|
+
return;
|
|
46396
|
+
}
|
|
46397
|
+
args.log.info(result.message);
|
|
46398
|
+
}
|
|
46399
|
+
|
|
46400
|
+
// src/lib/postman/error-advice.ts
|
|
46401
|
+
var WORKSPACE_PERSONAL_ONLY_ADVICE = "Workspace creation failed: This may be an Org-mode account that requires a workspace-team-id input. The Postman API does not allow creating team workspaces at the organization level. Use the workspace-team-id input to specify which sub-team should own this workspace.";
|
|
46402
|
+
function workspaceTeamIdUnauthorizedAdvice(targetTeamId) {
|
|
46403
|
+
return `The workspace-team-id input (${targetTeamId}) was rejected as unauthorized by the Postman API. In org-mode accounts it must be the numeric id of a sub-team this API key can access; GET https://api.getpostman.com/teams lists the available sub-teams. Fix the workspace-team-id value and re-run.`;
|
|
46404
|
+
}
|
|
46405
|
+
function adviseFromWorkspaceCreateError(err, targetTeamId) {
|
|
46406
|
+
if (err.message.includes("Only personal workspaces")) {
|
|
46407
|
+
return new Error(WORKSPACE_PERSONAL_ONLY_ADVICE, { cause: err });
|
|
46408
|
+
}
|
|
46409
|
+
if (targetTeamId != null && err.message.includes("You are not authorized to perform this action")) {
|
|
46410
|
+
return new Error(workspaceTeamIdUnauthorizedAdvice(targetTeamId), { cause: err });
|
|
46411
|
+
}
|
|
46412
|
+
return void 0;
|
|
46413
|
+
}
|
|
46414
|
+
function expiryAdvice(code) {
|
|
46415
|
+
return `postman: Bifrost rejected the access token (${code}). Service-account access tokens expire after about 1 to 1.5 hours; this run likely outlived its token. Re-mint a fresh token (postman-resolve-service-token-action, or POST https://api.getpostman.com/service-account-tokens) and re-run. If it was just minted, confirm postman-access-token is the token for the same parent org as postman-api-key.`;
|
|
46416
|
+
}
|
|
46417
|
+
function forbiddenAdvice(ctx) {
|
|
46418
|
+
const sessionDetail = ctx.sessionTeamId ? ` while the access token is valid (it resolved to team ${ctx.sessionTeamId}${ctx.sessionRoles && ctx.sessionRoles.length > 0 ? `, roles [${ctx.sessionRoles.join(", ")}]` : ""}${ctx.sessionConsumerType ? `, consumerType ${ctx.sessionConsumerType}` : ""} at preflight)` : "";
|
|
46419
|
+
const scopedTeamId = ctx.workspaceTeamId || ctx.explicitTeamId;
|
|
46420
|
+
const teamClause = scopedTeamId ? `, or workspace-team-id ${scopedTeamId} names a sub-team it cannot act in` : ", or the workspace-team-id / POSTMAN_TEAM_ID in use names a sub-team it cannot act in";
|
|
46421
|
+
return `postman: Bifrost refused ${ctx.operation || "this operation"} with 403${sessionDetail}. The token's identity lacks permission for this endpoint${teamClause}. Verify the token's role and that workspace-team-id / POSTMAN_TEAM_ID matches a sub-team from GET https://api.getpostman.com/teams.`;
|
|
46422
|
+
}
|
|
46423
|
+
function buildAdvice(status, body, ctx) {
|
|
46424
|
+
if (body.includes("UNAUTHENTICATED")) {
|
|
46425
|
+
return expiryAdvice("UNAUTHENTICATED");
|
|
46426
|
+
}
|
|
46427
|
+
if (body.includes("authenticationError")) {
|
|
46428
|
+
return expiryAdvice("authenticationError");
|
|
46429
|
+
}
|
|
46430
|
+
if (body.includes("Only personal workspaces")) {
|
|
46431
|
+
return WORKSPACE_PERSONAL_ONLY_ADVICE;
|
|
46432
|
+
}
|
|
46433
|
+
if (body.includes("projectAlreadyConnected")) {
|
|
46434
|
+
return `postman: ${ctx.operation || "this operation"} reports projectAlreadyConnected with no workspace id in the error body. The repository is already linked to a workspace this credential cannot see, usually one created by a different credential pair or sub-team. Delete the stale link or its workspace, then re-run with one credential pair from a single parent org.`;
|
|
46435
|
+
}
|
|
46436
|
+
if (body.includes("invalidParamError") && body.includes("already exists")) {
|
|
46437
|
+
return `postman: ${ctx.operation || "this operation"} hit a duplicate resource error (invalidParamError: already exists). A matching resource already exists, possibly under another credential pair or sub-team where this credential cannot see it. Identify which workspace holds the existing resource and re-run with one credential pair from a single parent org.`;
|
|
46438
|
+
}
|
|
46439
|
+
if (body.includes("Team feature is not available for your organization")) {
|
|
46440
|
+
return `postman: ${ctx.operation || "this operation"} failed because the team feature is not available for this organization. The credential belongs to an account whose plan lacks team features; use credentials from the intended team and confirm the plan supports this operation.`;
|
|
46441
|
+
}
|
|
46442
|
+
if (body.includes("You are not authorized to perform this action") || status === 403 && ctx.hasAccessToken) {
|
|
46443
|
+
return forbiddenAdvice(ctx);
|
|
46444
|
+
}
|
|
46445
|
+
return void 0;
|
|
46446
|
+
}
|
|
46447
|
+
function adviseFromHttpError(err, ctx) {
|
|
46448
|
+
const body = err.responseBody || err.message || "";
|
|
46449
|
+
const advice = buildAdvice(err.status, body, ctx);
|
|
46450
|
+
if (!advice) {
|
|
46451
|
+
return void 0;
|
|
46452
|
+
}
|
|
46453
|
+
return new Error(ctx.mask(advice), { cause: err });
|
|
46454
|
+
}
|
|
46455
|
+
|
|
46141
46456
|
// src/lib/retry.ts
|
|
46142
46457
|
function sleep(delayMs) {
|
|
46143
46458
|
return new Promise((resolve3) => {
|
|
@@ -46186,7 +46501,7 @@ async function retry(operation, options = {}) {
|
|
|
46186
46501
|
}
|
|
46187
46502
|
|
|
46188
46503
|
// src/lib/postman/postman-assets-client.ts
|
|
46189
|
-
function
|
|
46504
|
+
function asRecord2(value) {
|
|
46190
46505
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
46191
46506
|
return null;
|
|
46192
46507
|
}
|
|
@@ -46194,8 +46509,8 @@ function asRecord(value) {
|
|
|
46194
46509
|
}
|
|
46195
46510
|
function extractWorkspacesPage(data) {
|
|
46196
46511
|
const workspaces = Array.isArray(data?.workspaces) ? data.workspaces : [];
|
|
46197
|
-
const meta =
|
|
46198
|
-
const pagination =
|
|
46512
|
+
const meta = asRecord2(data?.meta);
|
|
46513
|
+
const pagination = asRecord2(data?.pagination);
|
|
46199
46514
|
const nextCursor = String(
|
|
46200
46515
|
data?.nextCursor ?? data?.next_cursor ?? meta?.nextCursor ?? meta?.next_cursor ?? pagination?.nextCursor ?? pagination?.next_cursor ?? ""
|
|
46201
46516
|
).trim() || void 0;
|
|
@@ -46287,7 +46602,7 @@ var PostmanAssetsClient = class {
|
|
|
46287
46602
|
async getTeams() {
|
|
46288
46603
|
const data = await this.request("/teams");
|
|
46289
46604
|
const teams = data?.data ?? [];
|
|
46290
|
-
return Array.isArray(teams) ? teams.map((entry) =>
|
|
46605
|
+
return Array.isArray(teams) ? teams.map((entry) => asRecord2(entry)).filter((team) => Boolean(team?.id && team?.name)).map((team) => ({
|
|
46291
46606
|
id: Number(team.id),
|
|
46292
46607
|
name: String(team.name),
|
|
46293
46608
|
handle: String(team.handle || ""),
|
|
@@ -46339,34 +46654,28 @@ var PostmanAssetsClient = class {
|
|
|
46339
46654
|
body: JSON.stringify(payload)
|
|
46340
46655
|
});
|
|
46341
46656
|
} catch (err) {
|
|
46342
|
-
if (err instanceof Error
|
|
46343
|
-
|
|
46344
|
-
|
|
46345
|
-
|
|
46346
|
-
|
|
46347
|
-
}
|
|
46348
|
-
if (targetTeamId != null && err instanceof Error && err.message.includes("You are not authorized to perform this action")) {
|
|
46349
|
-
throw new Error(
|
|
46350
|
-
`The workspace-team-id input (${targetTeamId}) was rejected as unauthorized by the Postman API. In org-mode accounts it must be the numeric id of a sub-team this API key can access; GET https://api.getpostman.com/teams lists the available sub-teams. Fix the workspace-team-id value and re-run.`,
|
|
46351
|
-
{ cause: err }
|
|
46352
|
-
);
|
|
46657
|
+
if (err instanceof Error) {
|
|
46658
|
+
const advised = adviseFromWorkspaceCreateError(err, targetTeamId);
|
|
46659
|
+
if (advised) {
|
|
46660
|
+
throw advised;
|
|
46661
|
+
}
|
|
46353
46662
|
}
|
|
46354
46663
|
throw err;
|
|
46355
46664
|
}
|
|
46356
|
-
const createdWorkspace =
|
|
46665
|
+
const createdWorkspace = asRecord2(created?.workspace);
|
|
46357
46666
|
const workspaceId = String(createdWorkspace?.id || "").trim();
|
|
46358
46667
|
if (!workspaceId) {
|
|
46359
46668
|
throw new Error("Workspace create did not return an id");
|
|
46360
46669
|
}
|
|
46361
46670
|
const workspace = await this.request(`/workspaces/${workspaceId}`);
|
|
46362
|
-
let visibility =
|
|
46671
|
+
let visibility = asRecord2(workspace?.workspace)?.visibility;
|
|
46363
46672
|
if (visibility !== "team") {
|
|
46364
46673
|
await this.request(`/workspaces/${workspaceId}`, {
|
|
46365
46674
|
method: "PUT",
|
|
46366
46675
|
body: JSON.stringify(payload)
|
|
46367
46676
|
});
|
|
46368
46677
|
const reread = await this.request(`/workspaces/${workspaceId}`);
|
|
46369
|
-
visibility =
|
|
46678
|
+
visibility = asRecord2(reread?.workspace)?.visibility;
|
|
46370
46679
|
}
|
|
46371
46680
|
if (typeof visibility === "string" && visibility !== "team") {
|
|
46372
46681
|
let cleanedUp = false;
|
|
@@ -46395,7 +46704,7 @@ var PostmanAssetsClient = class {
|
|
|
46395
46704
|
async getWorkspaceVisibility(workspaceId) {
|
|
46396
46705
|
try {
|
|
46397
46706
|
const workspace = await this.request(`/workspaces/${workspaceId}`);
|
|
46398
|
-
const visibility =
|
|
46707
|
+
const visibility = asRecord2(workspace?.workspace)?.visibility;
|
|
46399
46708
|
return typeof visibility === "string" ? visibility : null;
|
|
46400
46709
|
} catch {
|
|
46401
46710
|
return null;
|
|
@@ -46417,7 +46726,7 @@ var PostmanAssetsClient = class {
|
|
|
46417
46726
|
nextCursor = page.nextCursor;
|
|
46418
46727
|
}
|
|
46419
46728
|
} while (nextCursor);
|
|
46420
|
-
return allWorkspaces.map((entry) =>
|
|
46729
|
+
return allWorkspaces.map((entry) => asRecord2(entry)).filter((workspace) => Boolean(workspace?.id && workspace?.name)).map((workspace) => ({
|
|
46421
46730
|
id: String(workspace.id),
|
|
46422
46731
|
name: String(workspace.name),
|
|
46423
46732
|
type: String(workspace.type ?? "team")
|
|
@@ -46465,7 +46774,7 @@ var PostmanAssetsClient = class {
|
|
|
46465
46774
|
async inviteRequesterToWorkspace(workspaceId, email) {
|
|
46466
46775
|
const users = await this.request("/users");
|
|
46467
46776
|
const userList = Array.isArray(users?.data) ? users.data : [];
|
|
46468
|
-
const user = userList.map((entry) =>
|
|
46777
|
+
const user = userList.map((entry) => asRecord2(entry)).find((entry) => entry?.email === email);
|
|
46469
46778
|
if (!user?.id) {
|
|
46470
46779
|
return;
|
|
46471
46780
|
}
|
|
@@ -46553,12 +46862,12 @@ var PostmanAssetsClient = class {
|
|
|
46553
46862
|
}
|
|
46554
46863
|
};
|
|
46555
46864
|
const extractUid = (data) => {
|
|
46556
|
-
const root =
|
|
46557
|
-
const details =
|
|
46865
|
+
const root = asRecord2(data);
|
|
46866
|
+
const details = asRecord2(root?.details);
|
|
46558
46867
|
const resources = Array.isArray(details?.resources) ? details.resources : [];
|
|
46559
|
-
const firstResource =
|
|
46560
|
-
const collection =
|
|
46561
|
-
const resource =
|
|
46868
|
+
const firstResource = asRecord2(resources[0]);
|
|
46869
|
+
const collection = asRecord2(root?.collection);
|
|
46870
|
+
const resource = asRecord2(root?.resource);
|
|
46562
46871
|
return String(
|
|
46563
46872
|
firstResource?.id ?? collection?.id ?? collection?.uid ?? resource?.uid ?? resource?.id ?? ""
|
|
46564
46873
|
).trim() || void 0;
|
|
@@ -46592,9 +46901,9 @@ var PostmanAssetsClient = class {
|
|
|
46592
46901
|
if (directUid) {
|
|
46593
46902
|
return directUid;
|
|
46594
46903
|
}
|
|
46595
|
-
let taskUrl = String(generationResponse?.url ?? "") || String(generationResponse?.task_url ?? "") || String(generationResponse?.taskUrl ?? "") || String(
|
|
46904
|
+
let taskUrl = String(generationResponse?.url ?? "") || String(generationResponse?.task_url ?? "") || String(generationResponse?.taskUrl ?? "") || String(asRecord2(generationResponse?.links)?.task ?? "");
|
|
46596
46905
|
if (!taskUrl) {
|
|
46597
|
-
const task =
|
|
46906
|
+
const task = asRecord2(generationResponse?.task);
|
|
46598
46907
|
const taskId = generationResponse?.taskId || task?.id || generationResponse?.id;
|
|
46599
46908
|
if (!taskId) {
|
|
46600
46909
|
throw new Error(
|
|
@@ -46608,8 +46917,8 @@ var PostmanAssetsClient = class {
|
|
|
46608
46917
|
setTimeout(resolve3, 2e3);
|
|
46609
46918
|
});
|
|
46610
46919
|
const task = await this.request(taskUrl);
|
|
46611
|
-
const taskRecord =
|
|
46612
|
-
const taskNested =
|
|
46920
|
+
const taskRecord = asRecord2(task);
|
|
46921
|
+
const taskNested = asRecord2(taskRecord?.task);
|
|
46613
46922
|
const status = String(taskRecord?.status || taskNested?.status || "").toLowerCase();
|
|
46614
46923
|
if (status === "completed") {
|
|
46615
46924
|
const taskUid = extractUid(task);
|
|
@@ -46640,7 +46949,7 @@ var PostmanAssetsClient = class {
|
|
|
46640
46949
|
}
|
|
46641
46950
|
async injectTests(collectionUid, type2) {
|
|
46642
46951
|
const collectionResponse = await this.request(`/collections/${collectionUid}`);
|
|
46643
|
-
const collection =
|
|
46952
|
+
const collection = asRecord2(collectionResponse?.collection);
|
|
46644
46953
|
if (!collection) {
|
|
46645
46954
|
throw new Error(`Failed to fetch collection ${collectionUid}`);
|
|
46646
46955
|
}
|
|
@@ -46726,7 +47035,7 @@ var PostmanAssetsClient = class {
|
|
|
46726
47035
|
});
|
|
46727
47036
|
}
|
|
46728
47037
|
if (Array.isArray(itemNode.item)) {
|
|
46729
|
-
itemNode.item.map((entry) =>
|
|
47038
|
+
itemNode.item.map((entry) => asRecord2(entry)).filter((entry) => Boolean(entry)).forEach(injectScripts);
|
|
46730
47039
|
}
|
|
46731
47040
|
};
|
|
46732
47041
|
if (Array.isArray(collection.item)) {
|
|
@@ -46754,7 +47063,7 @@ var PostmanAssetsClient = class {
|
|
|
46754
47063
|
}
|
|
46755
47064
|
})
|
|
46756
47065
|
});
|
|
46757
|
-
const environment =
|
|
47066
|
+
const environment = asRecord2(response?.environment);
|
|
46758
47067
|
const uid = String(environment?.uid || "").trim();
|
|
46759
47068
|
if (!uid) {
|
|
46760
47069
|
throw new Error("Environment create did not return a UID");
|
|
@@ -46787,7 +47096,7 @@ var PostmanAssetsClient = class {
|
|
|
46787
47096
|
}
|
|
46788
47097
|
})
|
|
46789
47098
|
});
|
|
46790
|
-
const monitor =
|
|
47099
|
+
const monitor = asRecord2(response?.monitor);
|
|
46791
47100
|
const uid = String(monitor?.uid || "").trim();
|
|
46792
47101
|
if (!uid) {
|
|
46793
47102
|
throw new Error("Monitor create did not return a UID");
|
|
@@ -46806,8 +47115,8 @@ var PostmanAssetsClient = class {
|
|
|
46806
47115
|
}
|
|
46807
47116
|
})
|
|
46808
47117
|
});
|
|
46809
|
-
const mock =
|
|
46810
|
-
const mockConfig =
|
|
47118
|
+
const mock = asRecord2(response?.mock);
|
|
47119
|
+
const mockConfig = asRecord2(mock?.config);
|
|
46811
47120
|
const uid = String(mock?.uid || "").trim();
|
|
46812
47121
|
if (!uid) {
|
|
46813
47122
|
throw new Error("Mock create did not return a UID");
|
|
@@ -46878,6 +47187,18 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46878
47187
|
this.teamId = String(teamId || "").trim();
|
|
46879
47188
|
this.orgMode = orgMode;
|
|
46880
47189
|
}
|
|
47190
|
+
adviceContext(operation) {
|
|
47191
|
+
const session = getMemoizedSessionIdentity();
|
|
47192
|
+
return {
|
|
47193
|
+
operation,
|
|
47194
|
+
hasAccessToken: Boolean(this.accessToken),
|
|
47195
|
+
sessionTeamId: session?.teamId,
|
|
47196
|
+
sessionRoles: session?.roles,
|
|
47197
|
+
sessionConsumerType: session?.consumerType,
|
|
47198
|
+
explicitTeamId: this.teamId || void 0,
|
|
47199
|
+
mask: this.secretMasker
|
|
47200
|
+
};
|
|
47201
|
+
}
|
|
46881
47202
|
async proxyRequest(service, method, requestPath2, body, options = {}) {
|
|
46882
47203
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
46883
47204
|
const headers = {
|
|
@@ -46944,7 +47265,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46944
47265
|
{ appVersion, query: { tag: "governance" } }
|
|
46945
47266
|
);
|
|
46946
47267
|
if (!listResponse.ok) {
|
|
46947
|
-
|
|
47268
|
+
const httpErr = await HttpError.fromResponse(listResponse, {
|
|
46948
47269
|
method: "GET",
|
|
46949
47270
|
requestHeaders: {
|
|
46950
47271
|
"Content-Type": "application/json",
|
|
@@ -46955,6 +47276,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46955
47276
|
secretValues: [this.accessToken],
|
|
46956
47277
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
46957
47278
|
});
|
|
47279
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("governance assignment"));
|
|
47280
|
+
throw advised ?? httpErr;
|
|
46958
47281
|
}
|
|
46959
47282
|
const groups = await listResponse.json();
|
|
46960
47283
|
const group = (groups.workspaceGroups ?? groups.data)?.find(
|
|
@@ -46980,7 +47303,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46980
47303
|
{ appVersion }
|
|
46981
47304
|
);
|
|
46982
47305
|
if (!patchResponse.ok) {
|
|
46983
|
-
|
|
47306
|
+
const httpErr = await HttpError.fromResponse(patchResponse, {
|
|
46984
47307
|
method: "PATCH",
|
|
46985
47308
|
requestHeaders: {
|
|
46986
47309
|
"Content-Type": "application/json",
|
|
@@ -46991,6 +47314,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46991
47314
|
secretValues: [this.accessToken],
|
|
46992
47315
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
46993
47316
|
});
|
|
47317
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("governance assignment"));
|
|
47318
|
+
throw advised ?? httpErr;
|
|
46994
47319
|
}
|
|
46995
47320
|
}
|
|
46996
47321
|
async connectWorkspaceToRepository(workspaceId, repoUrl) {
|
|
@@ -47024,7 +47349,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47024
47349
|
);
|
|
47025
47350
|
}
|
|
47026
47351
|
}
|
|
47027
|
-
|
|
47352
|
+
const httpErr = await HttpError.fromResponse(response, {
|
|
47028
47353
|
method: "POST",
|
|
47029
47354
|
requestHeaders: {
|
|
47030
47355
|
"Content-Type": "application/json",
|
|
@@ -47034,6 +47359,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47034
47359
|
secretValues: [this.accessToken],
|
|
47035
47360
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
47036
47361
|
});
|
|
47362
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("workspace repository linking"));
|
|
47363
|
+
throw advised ?? httpErr;
|
|
47037
47364
|
}
|
|
47038
47365
|
async linkCollectionsToSpecification(specificationId, collections) {
|
|
47039
47366
|
if (collections.length === 0) {
|
|
@@ -47051,7 +47378,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47051
47378
|
if (response.ok) {
|
|
47052
47379
|
return;
|
|
47053
47380
|
}
|
|
47054
|
-
|
|
47381
|
+
const httpErr = await HttpError.fromResponse(response, {
|
|
47055
47382
|
method: "POST",
|
|
47056
47383
|
requestHeaders: {
|
|
47057
47384
|
"Content-Type": "application/json",
|
|
@@ -47061,6 +47388,11 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47061
47388
|
secretValues: [this.accessToken],
|
|
47062
47389
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
47063
47390
|
});
|
|
47391
|
+
const advised = adviseFromHttpError(
|
|
47392
|
+
httpErr,
|
|
47393
|
+
this.adviceContext("collection-to-specification linking")
|
|
47394
|
+
);
|
|
47395
|
+
throw advised ?? httpErr;
|
|
47064
47396
|
}
|
|
47065
47397
|
async syncCollection(specificationId, collectionId) {
|
|
47066
47398
|
const response = await this.proxyRequest(
|
|
@@ -47071,7 +47403,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47071
47403
|
if (response.ok) {
|
|
47072
47404
|
return;
|
|
47073
47405
|
}
|
|
47074
|
-
|
|
47406
|
+
const httpErr = await HttpError.fromResponse(response, {
|
|
47075
47407
|
method: "POST",
|
|
47076
47408
|
requestHeaders: {
|
|
47077
47409
|
"Content-Type": "application/json",
|
|
@@ -47081,6 +47413,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47081
47413
|
secretValues: [this.accessToken],
|
|
47082
47414
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
47083
47415
|
});
|
|
47416
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("collection sync"));
|
|
47417
|
+
throw advised ?? httpErr;
|
|
47084
47418
|
}
|
|
47085
47419
|
async getWorkspaceGitRepoUrl(workspaceId) {
|
|
47086
47420
|
const response = await this.proxyRequest(
|
|
@@ -47654,7 +47988,7 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
|
47654
47988
|
"discriminator",
|
|
47655
47989
|
"format"
|
|
47656
47990
|
]);
|
|
47657
|
-
function
|
|
47991
|
+
function asRecord3(value) {
|
|
47658
47992
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
47659
47993
|
return value;
|
|
47660
47994
|
}
|
|
@@ -47666,7 +48000,7 @@ function decodePointerSegment(segment) {
|
|
|
47666
48000
|
}
|
|
47667
48001
|
function resolvePointer(root, ref) {
|
|
47668
48002
|
if (!ref.startsWith("#/")) return void 0;
|
|
47669
|
-
return ref.slice(2).split("/").map(decodePointerSegment).reduce((node, segment) =>
|
|
48003
|
+
return ref.slice(2).split("/").map(decodePointerSegment).reduce((node, segment) => asRecord3(node)?.[segment], root);
|
|
47670
48004
|
}
|
|
47671
48005
|
function unsupported(message) {
|
|
47672
48006
|
return { unsupported: message };
|
|
@@ -47676,7 +48010,7 @@ function mergeRequiredWithoutWriteOnly(required, writeOnlyProperties) {
|
|
|
47676
48010
|
return values.length > 0 ? values : void 0;
|
|
47677
48011
|
}
|
|
47678
48012
|
function hasUnsupported(child) {
|
|
47679
|
-
return
|
|
48013
|
+
return asRecord3(child)?.unsupported;
|
|
47680
48014
|
}
|
|
47681
48015
|
function rootDialect(root, version, schemaRecord) {
|
|
47682
48016
|
if (version === "3.0") return DRAFT_07_SCHEMA_URI;
|
|
@@ -47696,7 +48030,7 @@ function normalizeSchema(root, schema2, options) {
|
|
|
47696
48030
|
const bad = normalized2.map(hasUnsupported).find(Boolean);
|
|
47697
48031
|
return bad ? unsupported(bad) : normalized2;
|
|
47698
48032
|
}
|
|
47699
|
-
const record =
|
|
48033
|
+
const record = asRecord3(schema2);
|
|
47700
48034
|
if (!record) return schema2;
|
|
47701
48035
|
const ref = typeof record.$ref === "string" ? record.$ref : "";
|
|
47702
48036
|
if (ref) {
|
|
@@ -47731,10 +48065,10 @@ function normalizeSchema(root, schema2, options) {
|
|
|
47731
48065
|
const nullable = sourceSchema.nullable === true && options.version === "3.0";
|
|
47732
48066
|
delete sourceSchema.nullable;
|
|
47733
48067
|
const writeOnlyProperties = /* @__PURE__ */ new Set();
|
|
47734
|
-
const rawProperties =
|
|
48068
|
+
const rawProperties = asRecord3(sourceSchema.properties);
|
|
47735
48069
|
if (rawProperties) {
|
|
47736
48070
|
for (const [propertyName, propertySchema] of Object.entries(rawProperties)) {
|
|
47737
|
-
if (
|
|
48071
|
+
if (asRecord3(propertySchema)?.writeOnly === true) writeOnlyProperties.add(propertyName);
|
|
47738
48072
|
}
|
|
47739
48073
|
}
|
|
47740
48074
|
const normalized = {};
|
|
@@ -47766,7 +48100,7 @@ function normalizeSchema(root, schema2, options) {
|
|
|
47766
48100
|
return unsupported("Tuple array items are unsupported in OpenAPI 3.0");
|
|
47767
48101
|
}
|
|
47768
48102
|
if (key === "properties") {
|
|
47769
|
-
const properties =
|
|
48103
|
+
const properties = asRecord3(value);
|
|
47770
48104
|
if (!properties) continue;
|
|
47771
48105
|
const nextProperties = {};
|
|
47772
48106
|
for (const [propertyName, propertySchema] of Object.entries(properties)) {
|
|
@@ -47809,7 +48143,7 @@ function normalizeSchema(root, schema2, options) {
|
|
|
47809
48143
|
}
|
|
47810
48144
|
function packSchema(root, schema2, version) {
|
|
47811
48145
|
try {
|
|
47812
|
-
const dialect = rootDialect(root, version,
|
|
48146
|
+
const dialect = rootDialect(root, version, asRecord3(schema2) ?? void 0);
|
|
47813
48147
|
const normalized = normalizeSchema(root, schema2, { version, rootSchema: true, dialect });
|
|
47814
48148
|
const message = hasUnsupported(normalized);
|
|
47815
48149
|
return message ? unsupported(message) : { schema: normalized };
|
|
@@ -47820,7 +48154,7 @@ function packSchema(root, schema2, version) {
|
|
|
47820
48154
|
|
|
47821
48155
|
// src/lib/spec/contract-index.ts
|
|
47822
48156
|
var HTTP_METHODS = /* @__PURE__ */ new Set(["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
|
|
47823
|
-
function
|
|
48157
|
+
function asRecord4(value) {
|
|
47824
48158
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
47825
48159
|
return value;
|
|
47826
48160
|
}
|
|
@@ -47837,12 +48171,12 @@ function detectOpenApiVersion(root) {
|
|
|
47837
48171
|
return match[1] === "1" ? "3.1" : "3.0";
|
|
47838
48172
|
}
|
|
47839
48173
|
function resolveInternalRef(root, value) {
|
|
47840
|
-
const record =
|
|
48174
|
+
const record = asRecord4(value);
|
|
47841
48175
|
if (!record) return null;
|
|
47842
48176
|
const ref = typeof record.$ref === "string" ? record.$ref : "";
|
|
47843
48177
|
if (!ref) return record;
|
|
47844
48178
|
if (!ref.startsWith("#/")) throw new Error(`CONTRACT_UNRESOLVED_REF: External ref remained after bundling: ${ref}`);
|
|
47845
|
-
const resolved =
|
|
48179
|
+
const resolved = asRecord4(resolvePointer(root, ref));
|
|
47846
48180
|
if (!resolved) throw new Error(`CONTRACT_UNRESOLVED_REF: Unresolved OpenAPI $ref: ${ref}`);
|
|
47847
48181
|
return resolved;
|
|
47848
48182
|
}
|
|
@@ -47862,11 +48196,11 @@ function normalizePath(path6) {
|
|
|
47862
48196
|
return trimmed.split("/").map((segment, index) => index === 0 ? "" : safeDecodeSegment(segment)).join("/") || "/";
|
|
47863
48197
|
}
|
|
47864
48198
|
function pathItemServers(pathItem) {
|
|
47865
|
-
return asArray2(pathItem.servers).map((entry) =>
|
|
48199
|
+
return asArray2(pathItem.servers).map((entry) => asRecord4(entry)).map((entry) => typeof entry?.url === "string" ? entry.url : "").filter(Boolean);
|
|
47866
48200
|
}
|
|
47867
48201
|
function operationServers(root, pathItem, operation) {
|
|
47868
48202
|
const rawServers = asArray2(operation.servers).length > 0 ? asArray2(operation.servers) : pathItemServers(pathItem).length > 0 ? asArray2(pathItem.servers) : asArray2(root.servers);
|
|
47869
|
-
const values = rawServers.map((entry) =>
|
|
48203
|
+
const values = rawServers.map((entry) => asRecord4(entry)).map((entry) => typeof entry?.url === "string" ? entry.url : "").filter(Boolean);
|
|
47870
48204
|
return values.length > 0 ? values : [""];
|
|
47871
48205
|
}
|
|
47872
48206
|
function serverPathPrefix(url) {
|
|
@@ -47887,10 +48221,10 @@ function normalizeResponseKey(status) {
|
|
|
47887
48221
|
return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
|
|
47888
48222
|
}
|
|
47889
48223
|
function collectSecurityApiKeys(root, operation) {
|
|
47890
|
-
const securitySchemes =
|
|
48224
|
+
const securitySchemes = asRecord4(asRecord4(root.components)?.securitySchemes);
|
|
47891
48225
|
const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
|
|
47892
48226
|
const names = /* @__PURE__ */ new Set();
|
|
47893
|
-
for (const requirement of requirements.map((entry) =>
|
|
48227
|
+
for (const requirement of requirements.map((entry) => asRecord4(entry)).filter(Boolean)) {
|
|
47894
48228
|
for (const schemeName of Object.keys(requirement)) {
|
|
47895
48229
|
const scheme = resolveInternalRef(root, securitySchemes?.[schemeName]);
|
|
47896
48230
|
if (scheme?.type === "apiKey" && typeof scheme.name === "string" && ["query", "header"].includes(String(scheme.in))) {
|
|
@@ -47908,10 +48242,10 @@ function securitySchemeKind(scheme) {
|
|
|
47908
48242
|
return type2;
|
|
47909
48243
|
}
|
|
47910
48244
|
function collectSecuritySchemeWarnings(root, operation) {
|
|
47911
|
-
const securitySchemes =
|
|
48245
|
+
const securitySchemes = asRecord4(asRecord4(root.components)?.securitySchemes);
|
|
47912
48246
|
const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
|
|
47913
48247
|
const warnings = /* @__PURE__ */ new Set();
|
|
47914
|
-
for (const requirement of requirements.map((entry) =>
|
|
48248
|
+
for (const requirement of requirements.map((entry) => asRecord4(entry)).filter(Boolean)) {
|
|
47915
48249
|
for (const schemeName of Object.keys(requirement)) {
|
|
47916
48250
|
const scheme = resolveInternalRef(root, securitySchemes?.[schemeName]);
|
|
47917
48251
|
warnings.add(
|
|
@@ -47947,24 +48281,24 @@ function collectParameters(root, pathItem, operation) {
|
|
|
47947
48281
|
function collectRequestBody(root, operation) {
|
|
47948
48282
|
const body = resolveInternalRef(root, operation.requestBody);
|
|
47949
48283
|
if (!body || body.required !== true) return void 0;
|
|
47950
|
-
const content =
|
|
48284
|
+
const content = asRecord4(body.content);
|
|
47951
48285
|
return {
|
|
47952
48286
|
required: true,
|
|
47953
48287
|
contentTypes: content ? Object.keys(content) : []
|
|
47954
48288
|
};
|
|
47955
48289
|
}
|
|
47956
48290
|
function responseContent(root, version, response) {
|
|
47957
|
-
const content =
|
|
48291
|
+
const content = asRecord4(response.content);
|
|
47958
48292
|
if (!content) return {};
|
|
47959
48293
|
const media = {};
|
|
47960
48294
|
for (const [contentType, mediaObject] of Object.entries(content)) {
|
|
47961
|
-
const schema2 =
|
|
48295
|
+
const schema2 = asRecord4(mediaObject)?.schema;
|
|
47962
48296
|
media[contentType] = schema2 === void 0 ? {} : packSchema(root, schema2, version);
|
|
47963
48297
|
}
|
|
47964
48298
|
return media;
|
|
47965
48299
|
}
|
|
47966
48300
|
function responseHeaders(root, version, response) {
|
|
47967
|
-
const headers =
|
|
48301
|
+
const headers = asRecord4(response.headers);
|
|
47968
48302
|
if (!headers) return [];
|
|
47969
48303
|
return Object.entries(headers).map(([name, rawHeader]) => {
|
|
47970
48304
|
const header = resolveInternalRef(root, rawHeader);
|
|
@@ -47979,10 +48313,10 @@ function buildContractIndex(root) {
|
|
|
47979
48313
|
if (root.swagger === "2.0") throw new Error("CONTRACT_UNSUPPORTED_OPENAPI_VERSION: Dynamic contract tests require OpenAPI 3.0 or 3.1 (found swagger 2.0)");
|
|
47980
48314
|
if (!("openapi" in root)) throw new Error("CONTRACT_UNSUPPORTED_OPENAPI_VERSION: Dynamic contract tests require OpenAPI 3.0 or 3.1 (missing openapi)");
|
|
47981
48315
|
const version = detectOpenApiVersion(root);
|
|
47982
|
-
const paths =
|
|
48316
|
+
const paths = asRecord4(root.paths);
|
|
47983
48317
|
const operations = [];
|
|
47984
48318
|
const warnings = [];
|
|
47985
|
-
if (
|
|
48319
|
+
if (asRecord4(root.webhooks)) warnings.push("CONTRACT_WEBHOOKS_NOT_VALIDATED: OpenAPI webhooks are not validated by dynamic contract tests");
|
|
47986
48320
|
if (paths) {
|
|
47987
48321
|
for (const [path6, rawPathItem] of Object.entries(paths)) {
|
|
47988
48322
|
const pathItem = resolveInternalRef(root, rawPathItem);
|
|
@@ -47993,7 +48327,7 @@ function buildContractIndex(root) {
|
|
|
47993
48327
|
const operation = resolveInternalRef(root, rawOperation);
|
|
47994
48328
|
if (!operation) continue;
|
|
47995
48329
|
if (operation.callbacks) warnings.push(`CONTRACT_CALLBACKS_NOT_VALIDATED: callbacks are not validated for ${lowerMethod.toUpperCase()} ${path6}`);
|
|
47996
|
-
const responses =
|
|
48330
|
+
const responses = asRecord4(operation.responses);
|
|
47997
48331
|
if (!responses || Object.keys(responses).length === 0) {
|
|
47998
48332
|
throw new Error(`CONTRACT_OPERATION_NO_RESPONSES: ${lowerMethod.toUpperCase()} ${path6} must define at least one response`);
|
|
47999
48333
|
}
|
|
@@ -48083,7 +48417,7 @@ var CONTRACT_SIZE_LIMITS = {
|
|
|
48083
48417
|
maxTestScriptBytes: 9e5,
|
|
48084
48418
|
maxCollectionUpdateBytes: 4e6
|
|
48085
48419
|
};
|
|
48086
|
-
function
|
|
48420
|
+
function asRecord5(value) {
|
|
48087
48421
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
48088
48422
|
return value;
|
|
48089
48423
|
}
|
|
@@ -48092,7 +48426,7 @@ function asArray3(value) {
|
|
|
48092
48426
|
}
|
|
48093
48427
|
function stringifyPathSegment(segment) {
|
|
48094
48428
|
if (typeof segment === "string") return segment;
|
|
48095
|
-
const record =
|
|
48429
|
+
const record = asRecord5(segment);
|
|
48096
48430
|
if (!record) return String(segment ?? "");
|
|
48097
48431
|
for (const key of ["value", "key", "name"]) {
|
|
48098
48432
|
if (typeof record[key] === "string" && record[key]) return String(record[key]);
|
|
@@ -48110,10 +48444,10 @@ function pathFromRaw(raw) {
|
|
|
48110
48444
|
}
|
|
48111
48445
|
}
|
|
48112
48446
|
function requestPath(request) {
|
|
48113
|
-
const record =
|
|
48447
|
+
const record = asRecord5(request);
|
|
48114
48448
|
const url = record?.url ?? request;
|
|
48115
48449
|
if (typeof url === "string") return pathFromRaw(url);
|
|
48116
|
-
const urlRecord =
|
|
48450
|
+
const urlRecord = asRecord5(url);
|
|
48117
48451
|
if (!urlRecord) return "/";
|
|
48118
48452
|
if (Array.isArray(urlRecord.path)) return normalizePath(`/${urlRecord.path.map(stringifyPathSegment).filter(Boolean).join("/")}`);
|
|
48119
48453
|
if (typeof urlRecord.path === "string") return normalizePath(urlRecord.path);
|
|
@@ -48145,7 +48479,7 @@ function matchCandidate(candidate, request) {
|
|
|
48145
48479
|
return { matched: true, staticCount, templateCount };
|
|
48146
48480
|
}
|
|
48147
48481
|
function matchOperation(index, request) {
|
|
48148
|
-
const record =
|
|
48482
|
+
const record = asRecord5(request);
|
|
48149
48483
|
const method = String(record?.method || "").toUpperCase();
|
|
48150
48484
|
const path6 = requestPath(request);
|
|
48151
48485
|
const candidates = index.operations.filter((operation) => operation.method === method).flatMap((operation) => operation.candidates.map((candidate) => ({ operation, score: matchCandidate(candidate, path6), serverFull: candidate !== normalizePath(operation.path) }))).filter((entry) => entry.score.matched).map((entry) => ({ operation: entry.operation, score: [entry.score.staticCount, entry.serverFull ? 2 : 1, -entry.score.templateCount] })).sort((a, b) => {
|
|
@@ -48296,17 +48630,17 @@ function createSecretsResolverItem() {
|
|
|
48296
48630
|
}
|
|
48297
48631
|
function isResolverItem(item) {
|
|
48298
48632
|
if (item.name !== "00 - Resolve Secrets") return false;
|
|
48299
|
-
const request =
|
|
48633
|
+
const request = asRecord5(item.request);
|
|
48300
48634
|
if (String(request?.method || "").toUpperCase() !== "POST") return false;
|
|
48301
|
-
const headers = asArray3(request?.header).map((entry) =>
|
|
48635
|
+
const headers = asArray3(request?.header).map((entry) => asRecord5(entry));
|
|
48302
48636
|
const target = headers.find((entry) => entry?.key === "X-Amz-Target");
|
|
48303
48637
|
return String(target?.value || "") === "secretsmanager.GetSecretValue" && !requestPath(request).includes("secretsmanager");
|
|
48304
48638
|
}
|
|
48305
48639
|
function requestQueryNames(request) {
|
|
48306
|
-
const url =
|
|
48640
|
+
const url = asRecord5(request.url);
|
|
48307
48641
|
const names = /* @__PURE__ */ new Set();
|
|
48308
48642
|
if (Array.isArray(url?.query)) {
|
|
48309
|
-
for (const entry of url.query.map((item) =>
|
|
48643
|
+
for (const entry of url.query.map((item) => asRecord5(item)).filter(Boolean)) {
|
|
48310
48644
|
if (entry.disabled !== true && typeof entry.key === "string") names.add(entry.key.toLowerCase());
|
|
48311
48645
|
}
|
|
48312
48646
|
}
|
|
@@ -48321,17 +48655,17 @@ function requestQueryNames(request) {
|
|
|
48321
48655
|
}
|
|
48322
48656
|
function requestHeaderNames(request) {
|
|
48323
48657
|
const names = /* @__PURE__ */ new Set();
|
|
48324
|
-
for (const entry of asArray3(request.header).map((item) =>
|
|
48658
|
+
for (const entry of asArray3(request.header).map((item) => asRecord5(item)).filter(Boolean)) {
|
|
48325
48659
|
if (entry.disabled !== true && typeof entry.key === "string") names.add(entry.key.toLowerCase());
|
|
48326
48660
|
}
|
|
48327
48661
|
return names;
|
|
48328
48662
|
}
|
|
48329
48663
|
function requestHeaderValue(request, name) {
|
|
48330
|
-
const match = asArray3(request.header).map((item) =>
|
|
48664
|
+
const match = asArray3(request.header).map((item) => asRecord5(item)).filter(Boolean).find((entry) => String(entry.key || "").toLowerCase() === name.toLowerCase() && entry.disabled !== true);
|
|
48331
48665
|
return typeof match?.value === "string" ? match.value : void 0;
|
|
48332
48666
|
}
|
|
48333
48667
|
function hasRequestBody(request) {
|
|
48334
|
-
const body =
|
|
48668
|
+
const body = asRecord5(request.body);
|
|
48335
48669
|
if (!body) return false;
|
|
48336
48670
|
if (typeof body.raw === "string" && body.raw.trim()) return true;
|
|
48337
48671
|
return ["urlencoded", "formdata", "graphql"].some((key) => Array.isArray(body[key]) ? body[key].length > 0 : Boolean(body[key]));
|
|
@@ -48382,21 +48716,21 @@ function validateScript(script) {
|
|
|
48382
48716
|
return void 0;
|
|
48383
48717
|
}
|
|
48384
48718
|
function scriptExecLines(script) {
|
|
48385
|
-
const record =
|
|
48719
|
+
const record = asRecord5(script);
|
|
48386
48720
|
if (!record) return [];
|
|
48387
48721
|
if (Array.isArray(record.exec)) return record.exec.map((line) => String(line));
|
|
48388
48722
|
if (typeof record.exec === "string") return [record.exec];
|
|
48389
48723
|
return [];
|
|
48390
48724
|
}
|
|
48391
48725
|
function scanExecutableScripts(node, warnings) {
|
|
48392
|
-
for (const event of asArray3(node.event).map((entry) =>
|
|
48726
|
+
for (const event of asArray3(node.event).map((entry) => asRecord5(entry)).filter(Boolean)) {
|
|
48393
48727
|
const lines = scriptExecLines(event.script);
|
|
48394
48728
|
if (lines.length === 0) continue;
|
|
48395
48729
|
const warning = validateScript(lines);
|
|
48396
48730
|
if (warning) warnings.push(warning);
|
|
48397
48731
|
}
|
|
48398
48732
|
for (const child of asArray3(node.item)) {
|
|
48399
|
-
const childRecord =
|
|
48733
|
+
const childRecord = asRecord5(child);
|
|
48400
48734
|
if (childRecord) scanExecutableScripts(childRecord, warnings);
|
|
48401
48735
|
}
|
|
48402
48736
|
}
|
|
@@ -48406,7 +48740,7 @@ function instrumentContractCollection(collection, index) {
|
|
|
48406
48740
|
const inject = (item) => {
|
|
48407
48741
|
if (isResolverItem(item)) return;
|
|
48408
48742
|
if (item.request) {
|
|
48409
|
-
const request =
|
|
48743
|
+
const request = asRecord5(item.request) ?? {};
|
|
48410
48744
|
const result = matchOperation(index, request);
|
|
48411
48745
|
let script;
|
|
48412
48746
|
if (result.operation) {
|
|
@@ -48420,15 +48754,15 @@ function instrumentContractCollection(collection, index) {
|
|
|
48420
48754
|
} else {
|
|
48421
48755
|
script = createMappingFailureScript(`No OpenAPI operation matched request ${result.method} ${result.path}`);
|
|
48422
48756
|
}
|
|
48423
|
-
const events = asArray3(item.event).filter((entry) =>
|
|
48757
|
+
const events = asArray3(item.event).filter((entry) => asRecord5(entry)?.listen !== "test");
|
|
48424
48758
|
item.event = [...events, { listen: "test", script: { type: "text/javascript", exec: script } }];
|
|
48425
48759
|
}
|
|
48426
48760
|
for (const child of asArray3(item.item)) {
|
|
48427
|
-
const childRecord =
|
|
48761
|
+
const childRecord = asRecord5(child);
|
|
48428
48762
|
if (childRecord) inject(childRecord);
|
|
48429
48763
|
}
|
|
48430
48764
|
};
|
|
48431
|
-
const items = asArray3(collection.item).map((entry) =>
|
|
48765
|
+
const items = asArray3(collection.item).map((entry) => asRecord5(entry)).filter((entry) => Boolean(entry)).filter((entry) => !isResolverItem(entry));
|
|
48432
48766
|
collection.item = items;
|
|
48433
48767
|
for (const item of items) inject(item);
|
|
48434
48768
|
const missing = index.operations.filter((operation) => !covered.has(operation.id));
|
|
@@ -60792,7 +61126,7 @@ function compileErrors(result) {
|
|
|
60792
61126
|
|
|
60793
61127
|
// src/lib/spec/openapi-loader.ts
|
|
60794
61128
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
60795
|
-
function
|
|
61129
|
+
function asRecord6(value) {
|
|
60796
61130
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
60797
61131
|
return value;
|
|
60798
61132
|
}
|
|
@@ -60807,7 +61141,7 @@ function parseOpenApiDocument(content) {
|
|
|
60807
61141
|
throw new Error("CONTRACT_SPEC_PARSE_FAILED: Spec content is not valid JSON or YAML");
|
|
60808
61142
|
}
|
|
60809
61143
|
}
|
|
60810
|
-
const doc =
|
|
61144
|
+
const doc = asRecord6(parsed);
|
|
60811
61145
|
if (!doc) throw new Error("CONTRACT_SPEC_PARSE_FAILED: Spec content must be a JSON or YAML object");
|
|
60812
61146
|
return doc;
|
|
60813
61147
|
}
|
|
@@ -60835,7 +61169,7 @@ function collectExternalRefs(node, baseUrl, refs) {
|
|
|
60835
61169
|
node.forEach((entry) => collectExternalRefs(entry, baseUrl, refs));
|
|
60836
61170
|
return;
|
|
60837
61171
|
}
|
|
60838
|
-
const record =
|
|
61172
|
+
const record = asRecord6(node);
|
|
60839
61173
|
if (!record) return;
|
|
60840
61174
|
const ref = typeof record.$ref === "string" ? record.$ref : "";
|
|
60841
61175
|
if (ref && !ref.startsWith("#")) {
|
|
@@ -61167,6 +61501,11 @@ function resolveInputs(env = process.env) {
|
|
|
61167
61501
|
governanceMappingJson: parseGovernanceMappingJson(getInput("governance-mapping-json", env)),
|
|
61168
61502
|
postmanApiKey: getInput("postman-api-key", env) ?? "",
|
|
61169
61503
|
postmanAccessToken: getInput("postman-access-token", env),
|
|
61504
|
+
credentialPreflight: parseEnumInput(
|
|
61505
|
+
"credential-preflight",
|
|
61506
|
+
getInput("credential-preflight", env),
|
|
61507
|
+
customerPreviewActionContract.inputs["credential-preflight"].default ?? "warn"
|
|
61508
|
+
),
|
|
61170
61509
|
integrationBackend,
|
|
61171
61510
|
folderStrategy: parseEnumInput("folder-strategy", getInput("folder-strategy", env), "Paths"),
|
|
61172
61511
|
nestedFolderHierarchy: parseBooleanInput("nested-folder-hierarchy", getInput("nested-folder-hierarchy", env), false),
|
|
@@ -61176,6 +61515,7 @@ function resolveInputs(env = process.env) {
|
|
|
61176
61515
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
61177
61516
|
postmanGatewayBase: endpointProfile.gatewayBaseUrl,
|
|
61178
61517
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
61518
|
+
postmanIapubBase: endpointProfile.iapubBaseUrl,
|
|
61179
61519
|
githubRefName: env.GITHUB_REF_NAME,
|
|
61180
61520
|
githubHeadRef: env.GITHUB_HEAD_REF,
|
|
61181
61521
|
githubRef: env.GITHUB_REF,
|
|
@@ -61712,8 +62052,20 @@ For CLI usage, pass --workspace-team-id <id> or export POSTMAN_WORKSPACE_TEAM_ID
|
|
|
61712
62052
|
governanceGroupName
|
|
61713
62053
|
);
|
|
61714
62054
|
} catch (error) {
|
|
62055
|
+
const session = getMemoizedSessionIdentity();
|
|
62056
|
+
const advised = error instanceof HttpError ? adviseFromHttpError(error, {
|
|
62057
|
+
operation: "governance assignment",
|
|
62058
|
+
hasAccessToken: Boolean(inputs.postmanAccessToken),
|
|
62059
|
+
sessionTeamId: session?.teamId,
|
|
62060
|
+
sessionRoles: session?.roles,
|
|
62061
|
+
sessionConsumerType: session?.consumerType,
|
|
62062
|
+
workspaceTeamId: inputs.workspaceTeamId,
|
|
62063
|
+
explicitTeamId: inputs.teamId || void 0,
|
|
62064
|
+
mask: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken])
|
|
62065
|
+
}) : void 0;
|
|
62066
|
+
const reported = advised ?? error;
|
|
61715
62067
|
dependencies.core.warning(
|
|
61716
|
-
`Failed to assign governance group: ${
|
|
62068
|
+
`Failed to assign governance group: ${reported instanceof Error ? reported.message : String(reported)}`
|
|
61717
62069
|
);
|
|
61718
62070
|
}
|
|
61719
62071
|
}
|
|
@@ -62375,6 +62727,7 @@ var cliInputNames = [
|
|
|
62375
62727
|
"spec-path",
|
|
62376
62728
|
"postman-api-key",
|
|
62377
62729
|
"postman-access-token",
|
|
62730
|
+
"credential-preflight",
|
|
62378
62731
|
"workspace-id",
|
|
62379
62732
|
"spec-id",
|
|
62380
62733
|
"baseline-collection-id",
|
|
@@ -62599,6 +62952,17 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
62599
62952
|
assertOutputFileAllowed2(config.resultJsonPath);
|
|
62600
62953
|
assertOutputFileAllowed2(config.dotenvPath);
|
|
62601
62954
|
const dependencies = createCliDependencies(inputs);
|
|
62955
|
+
await runCredentialPreflight({
|
|
62956
|
+
apiBaseUrl: inputs.postmanApiBase,
|
|
62957
|
+
iapubBaseUrl: inputs.postmanIapubBase,
|
|
62958
|
+
postmanApiKey: inputs.postmanApiKey,
|
|
62959
|
+
postmanAccessToken: inputs.postmanAccessToken,
|
|
62960
|
+
workspaceTeamId: inputs.workspaceTeamId,
|
|
62961
|
+
explicitTeamId: inputs.teamId || void 0,
|
|
62962
|
+
mode: inputs.credentialPreflight,
|
|
62963
|
+
mask: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken]),
|
|
62964
|
+
log: dependencies.core
|
|
62965
|
+
});
|
|
62602
62966
|
if ((inputs.domain || inputs.governanceGroup) && !dependencies.internalIntegration) {
|
|
62603
62967
|
dependencies.core.warning(
|
|
62604
62968
|
"Skipping governance assignment because postman-access-token is not configured"
|