@postman-cse/onboarding-bootstrap 0.14.1 → 0.15.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/action.yml +4 -0
- package/dist/action.cjs +452 -84
- package/dist/cli.cjs +127 -13
- package/dist/index.cjs +452 -84
- 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,68 @@ function resolvePostmanEndpointProfile(stack) {
|
|
|
46138
46146
|
return POSTMAN_ENDPOINT_PROFILES[stack];
|
|
46139
46147
|
}
|
|
46140
46148
|
|
|
46149
|
+
// src/lib/postman/credential-identity.ts
|
|
46150
|
+
var memoizedSessionIdentity;
|
|
46151
|
+
function getMemoizedSessionIdentity() {
|
|
46152
|
+
return memoizedSessionIdentity;
|
|
46153
|
+
}
|
|
46154
|
+
|
|
46155
|
+
// src/lib/postman/error-advice.ts
|
|
46156
|
+
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.";
|
|
46157
|
+
function workspaceTeamIdUnauthorizedAdvice(targetTeamId) {
|
|
46158
|
+
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.`;
|
|
46159
|
+
}
|
|
46160
|
+
function adviseFromWorkspaceCreateError(err, targetTeamId) {
|
|
46161
|
+
if (err.message.includes("Only personal workspaces")) {
|
|
46162
|
+
return new Error(WORKSPACE_PERSONAL_ONLY_ADVICE, { cause: err });
|
|
46163
|
+
}
|
|
46164
|
+
if (targetTeamId != null && err.message.includes("You are not authorized to perform this action")) {
|
|
46165
|
+
return new Error(workspaceTeamIdUnauthorizedAdvice(targetTeamId), { cause: err });
|
|
46166
|
+
}
|
|
46167
|
+
return void 0;
|
|
46168
|
+
}
|
|
46169
|
+
function expiryAdvice(code) {
|
|
46170
|
+
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.`;
|
|
46171
|
+
}
|
|
46172
|
+
function forbiddenAdvice(ctx) {
|
|
46173
|
+
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)` : "";
|
|
46174
|
+
const scopedTeamId = ctx.workspaceTeamId || ctx.explicitTeamId;
|
|
46175
|
+
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";
|
|
46176
|
+
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.`;
|
|
46177
|
+
}
|
|
46178
|
+
function buildAdvice(status, body, ctx) {
|
|
46179
|
+
if (body.includes("UNAUTHENTICATED")) {
|
|
46180
|
+
return expiryAdvice("UNAUTHENTICATED");
|
|
46181
|
+
}
|
|
46182
|
+
if (body.includes("authenticationError")) {
|
|
46183
|
+
return expiryAdvice("authenticationError");
|
|
46184
|
+
}
|
|
46185
|
+
if (body.includes("Only personal workspaces")) {
|
|
46186
|
+
return WORKSPACE_PERSONAL_ONLY_ADVICE;
|
|
46187
|
+
}
|
|
46188
|
+
if (body.includes("projectAlreadyConnected")) {
|
|
46189
|
+
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.`;
|
|
46190
|
+
}
|
|
46191
|
+
if (body.includes("invalidParamError") && body.includes("already exists")) {
|
|
46192
|
+
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.`;
|
|
46193
|
+
}
|
|
46194
|
+
if (body.includes("Team feature is not available for your organization")) {
|
|
46195
|
+
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.`;
|
|
46196
|
+
}
|
|
46197
|
+
if (body.includes("You are not authorized to perform this action") || status === 403 && ctx.hasAccessToken) {
|
|
46198
|
+
return forbiddenAdvice(ctx);
|
|
46199
|
+
}
|
|
46200
|
+
return void 0;
|
|
46201
|
+
}
|
|
46202
|
+
function adviseFromHttpError(err, ctx) {
|
|
46203
|
+
const body = err.responseBody || err.message || "";
|
|
46204
|
+
const advice = buildAdvice(err.status, body, ctx);
|
|
46205
|
+
if (!advice) {
|
|
46206
|
+
return void 0;
|
|
46207
|
+
}
|
|
46208
|
+
return new Error(ctx.mask(advice), { cause: err });
|
|
46209
|
+
}
|
|
46210
|
+
|
|
46141
46211
|
// src/lib/retry.ts
|
|
46142
46212
|
function sleep(delayMs) {
|
|
46143
46213
|
return new Promise((resolve3) => {
|
|
@@ -46339,11 +46409,11 @@ var PostmanAssetsClient = class {
|
|
|
46339
46409
|
body: JSON.stringify(payload)
|
|
46340
46410
|
});
|
|
46341
46411
|
} catch (err) {
|
|
46342
|
-
if (err instanceof Error
|
|
46343
|
-
|
|
46344
|
-
|
|
46345
|
-
|
|
46346
|
-
|
|
46412
|
+
if (err instanceof Error) {
|
|
46413
|
+
const advised = adviseFromWorkspaceCreateError(err, targetTeamId);
|
|
46414
|
+
if (advised) {
|
|
46415
|
+
throw advised;
|
|
46416
|
+
}
|
|
46347
46417
|
}
|
|
46348
46418
|
throw err;
|
|
46349
46419
|
}
|
|
@@ -46872,6 +46942,18 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46872
46942
|
this.teamId = String(teamId || "").trim();
|
|
46873
46943
|
this.orgMode = orgMode;
|
|
46874
46944
|
}
|
|
46945
|
+
adviceContext(operation) {
|
|
46946
|
+
const session = getMemoizedSessionIdentity();
|
|
46947
|
+
return {
|
|
46948
|
+
operation,
|
|
46949
|
+
hasAccessToken: Boolean(this.accessToken),
|
|
46950
|
+
sessionTeamId: session?.teamId,
|
|
46951
|
+
sessionRoles: session?.roles,
|
|
46952
|
+
sessionConsumerType: session?.consumerType,
|
|
46953
|
+
explicitTeamId: this.teamId || void 0,
|
|
46954
|
+
mask: this.secretMasker
|
|
46955
|
+
};
|
|
46956
|
+
}
|
|
46875
46957
|
async proxyRequest(service, method, requestPath2, body, options = {}) {
|
|
46876
46958
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
46877
46959
|
const headers = {
|
|
@@ -46938,7 +47020,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46938
47020
|
{ appVersion, query: { tag: "governance" } }
|
|
46939
47021
|
);
|
|
46940
47022
|
if (!listResponse.ok) {
|
|
46941
|
-
|
|
47023
|
+
const httpErr = await HttpError.fromResponse(listResponse, {
|
|
46942
47024
|
method: "GET",
|
|
46943
47025
|
requestHeaders: {
|
|
46944
47026
|
"Content-Type": "application/json",
|
|
@@ -46949,6 +47031,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46949
47031
|
secretValues: [this.accessToken],
|
|
46950
47032
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
46951
47033
|
});
|
|
47034
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("governance assignment"));
|
|
47035
|
+
throw advised ?? httpErr;
|
|
46952
47036
|
}
|
|
46953
47037
|
const groups = await listResponse.json();
|
|
46954
47038
|
const group = (groups.workspaceGroups ?? groups.data)?.find(
|
|
@@ -46974,7 +47058,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46974
47058
|
{ appVersion }
|
|
46975
47059
|
);
|
|
46976
47060
|
if (!patchResponse.ok) {
|
|
46977
|
-
|
|
47061
|
+
const httpErr = await HttpError.fromResponse(patchResponse, {
|
|
46978
47062
|
method: "PATCH",
|
|
46979
47063
|
requestHeaders: {
|
|
46980
47064
|
"Content-Type": "application/json",
|
|
@@ -46985,6 +47069,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
46985
47069
|
secretValues: [this.accessToken],
|
|
46986
47070
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
46987
47071
|
});
|
|
47072
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("governance assignment"));
|
|
47073
|
+
throw advised ?? httpErr;
|
|
46988
47074
|
}
|
|
46989
47075
|
}
|
|
46990
47076
|
async connectWorkspaceToRepository(workspaceId, repoUrl) {
|
|
@@ -47018,7 +47104,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47018
47104
|
);
|
|
47019
47105
|
}
|
|
47020
47106
|
}
|
|
47021
|
-
|
|
47107
|
+
const httpErr = await HttpError.fromResponse(response, {
|
|
47022
47108
|
method: "POST",
|
|
47023
47109
|
requestHeaders: {
|
|
47024
47110
|
"Content-Type": "application/json",
|
|
@@ -47028,6 +47114,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47028
47114
|
secretValues: [this.accessToken],
|
|
47029
47115
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
47030
47116
|
});
|
|
47117
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("workspace repository linking"));
|
|
47118
|
+
throw advised ?? httpErr;
|
|
47031
47119
|
}
|
|
47032
47120
|
async linkCollectionsToSpecification(specificationId, collections) {
|
|
47033
47121
|
if (collections.length === 0) {
|
|
@@ -47045,7 +47133,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47045
47133
|
if (response.ok) {
|
|
47046
47134
|
return;
|
|
47047
47135
|
}
|
|
47048
|
-
|
|
47136
|
+
const httpErr = await HttpError.fromResponse(response, {
|
|
47049
47137
|
method: "POST",
|
|
47050
47138
|
requestHeaders: {
|
|
47051
47139
|
"Content-Type": "application/json",
|
|
@@ -47055,6 +47143,11 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47055
47143
|
secretValues: [this.accessToken],
|
|
47056
47144
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
47057
47145
|
});
|
|
47146
|
+
const advised = adviseFromHttpError(
|
|
47147
|
+
httpErr,
|
|
47148
|
+
this.adviceContext("collection-to-specification linking")
|
|
47149
|
+
);
|
|
47150
|
+
throw advised ?? httpErr;
|
|
47058
47151
|
}
|
|
47059
47152
|
async syncCollection(specificationId, collectionId) {
|
|
47060
47153
|
const response = await this.proxyRequest(
|
|
@@ -47065,7 +47158,7 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47065
47158
|
if (response.ok) {
|
|
47066
47159
|
return;
|
|
47067
47160
|
}
|
|
47068
|
-
|
|
47161
|
+
const httpErr = await HttpError.fromResponse(response, {
|
|
47069
47162
|
method: "POST",
|
|
47070
47163
|
requestHeaders: {
|
|
47071
47164
|
"Content-Type": "application/json",
|
|
@@ -47075,6 +47168,8 @@ var BifrostInternalIntegrationAdapter = class _BifrostInternalIntegrationAdapter
|
|
|
47075
47168
|
secretValues: [this.accessToken],
|
|
47076
47169
|
url: `${this.bifrostBaseUrl}/ws/proxy`
|
|
47077
47170
|
});
|
|
47171
|
+
const advised = adviseFromHttpError(httpErr, this.adviceContext("collection sync"));
|
|
47172
|
+
throw advised ?? httpErr;
|
|
47078
47173
|
}
|
|
47079
47174
|
async getWorkspaceGitRepoUrl(workspaceId) {
|
|
47080
47175
|
const response = await this.proxyRequest(
|
|
@@ -61161,6 +61256,11 @@ function resolveInputs(env = process.env) {
|
|
|
61161
61256
|
governanceMappingJson: parseGovernanceMappingJson(getInput("governance-mapping-json", env)),
|
|
61162
61257
|
postmanApiKey: getInput("postman-api-key", env) ?? "",
|
|
61163
61258
|
postmanAccessToken: getInput("postman-access-token", env),
|
|
61259
|
+
credentialPreflight: parseEnumInput(
|
|
61260
|
+
"credential-preflight",
|
|
61261
|
+
getInput("credential-preflight", env),
|
|
61262
|
+
customerPreviewActionContract.inputs["credential-preflight"].default ?? "warn"
|
|
61263
|
+
),
|
|
61164
61264
|
integrationBackend,
|
|
61165
61265
|
folderStrategy: parseEnumInput("folder-strategy", getInput("folder-strategy", env), "Paths"),
|
|
61166
61266
|
nestedFolderHierarchy: parseBooleanInput("nested-folder-hierarchy", getInput("nested-folder-hierarchy", env), false),
|
|
@@ -61170,6 +61270,7 @@ function resolveInputs(env = process.env) {
|
|
|
61170
61270
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
61171
61271
|
postmanGatewayBase: endpointProfile.gatewayBaseUrl,
|
|
61172
61272
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
61273
|
+
postmanIapubBase: endpointProfile.iapubBaseUrl,
|
|
61173
61274
|
githubRefName: env.GITHUB_REF_NAME,
|
|
61174
61275
|
githubHeadRef: env.GITHUB_HEAD_REF,
|
|
61175
61276
|
githubRef: env.GITHUB_REF,
|
|
@@ -61706,8 +61807,20 @@ For CLI usage, pass --workspace-team-id <id> or export POSTMAN_WORKSPACE_TEAM_ID
|
|
|
61706
61807
|
governanceGroupName
|
|
61707
61808
|
);
|
|
61708
61809
|
} catch (error) {
|
|
61810
|
+
const session = getMemoizedSessionIdentity();
|
|
61811
|
+
const advised = error instanceof HttpError ? adviseFromHttpError(error, {
|
|
61812
|
+
operation: "governance assignment",
|
|
61813
|
+
hasAccessToken: Boolean(inputs.postmanAccessToken),
|
|
61814
|
+
sessionTeamId: session?.teamId,
|
|
61815
|
+
sessionRoles: session?.roles,
|
|
61816
|
+
sessionConsumerType: session?.consumerType,
|
|
61817
|
+
workspaceTeamId: inputs.workspaceTeamId,
|
|
61818
|
+
explicitTeamId: inputs.teamId || void 0,
|
|
61819
|
+
mask: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken])
|
|
61820
|
+
}) : void 0;
|
|
61821
|
+
const reported = advised ?? error;
|
|
61709
61822
|
dependencies.core.warning(
|
|
61710
|
-
`Failed to assign governance group: ${
|
|
61823
|
+
`Failed to assign governance group: ${reported instanceof Error ? reported.message : String(reported)}`
|
|
61711
61824
|
);
|
|
61712
61825
|
}
|
|
61713
61826
|
}
|
|
@@ -62369,6 +62482,7 @@ var cliInputNames = [
|
|
|
62369
62482
|
"spec-path",
|
|
62370
62483
|
"postman-api-key",
|
|
62371
62484
|
"postman-access-token",
|
|
62485
|
+
"credential-preflight",
|
|
62372
62486
|
"workspace-id",
|
|
62373
62487
|
"spec-id",
|
|
62374
62488
|
"baseline-collection-id",
|