@postman-cse/onboarding-repo-sync 2.1.10 → 2.1.13
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 -1
- package/dist/action.cjs +314 -79
- package/dist/cli.cjs +314 -79
- package/dist/index.cjs +314 -79
- package/package.json +4 -3
- package/scripts/verify-release-artifacts.mjs +239 -0
package/dist/cli.cjs
CHANGED
|
@@ -19747,7 +19747,7 @@ var require_response = __commonJS({
|
|
|
19747
19747
|
var assert = require("node:assert");
|
|
19748
19748
|
var { isomorphicEncode, serializeJavascriptValueToJSONString } = require_infra();
|
|
19749
19749
|
var textEncoder = new TextEncoder("utf-8");
|
|
19750
|
-
var
|
|
19750
|
+
var Response2 = class _Response {
|
|
19751
19751
|
/** @type {Headers} */
|
|
19752
19752
|
#headers;
|
|
19753
19753
|
#state;
|
|
@@ -19917,13 +19917,13 @@ var require_response = __commonJS({
|
|
|
19917
19917
|
response.#state = newState;
|
|
19918
19918
|
}
|
|
19919
19919
|
};
|
|
19920
|
-
var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } =
|
|
19921
|
-
Reflect.deleteProperty(
|
|
19922
|
-
Reflect.deleteProperty(
|
|
19923
|
-
Reflect.deleteProperty(
|
|
19924
|
-
Reflect.deleteProperty(
|
|
19925
|
-
mixinBody(
|
|
19926
|
-
Object.defineProperties(
|
|
19920
|
+
var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response2;
|
|
19921
|
+
Reflect.deleteProperty(Response2, "getResponseHeaders");
|
|
19922
|
+
Reflect.deleteProperty(Response2, "setResponseHeaders");
|
|
19923
|
+
Reflect.deleteProperty(Response2, "getResponseState");
|
|
19924
|
+
Reflect.deleteProperty(Response2, "setResponseState");
|
|
19925
|
+
mixinBody(Response2, getResponseState);
|
|
19926
|
+
Object.defineProperties(Response2.prototype, {
|
|
19927
19927
|
type: kEnumerableProperty,
|
|
19928
19928
|
url: kEnumerableProperty,
|
|
19929
19929
|
status: kEnumerableProperty,
|
|
@@ -19939,7 +19939,7 @@ var require_response = __commonJS({
|
|
|
19939
19939
|
configurable: true
|
|
19940
19940
|
}
|
|
19941
19941
|
});
|
|
19942
|
-
Object.defineProperties(
|
|
19942
|
+
Object.defineProperties(Response2, {
|
|
19943
19943
|
json: kEnumerableProperty,
|
|
19944
19944
|
redirect: kEnumerableProperty,
|
|
19945
19945
|
error: kEnumerableProperty
|
|
@@ -20072,7 +20072,7 @@ var require_response = __commonJS({
|
|
|
20072
20072
|
}
|
|
20073
20073
|
}
|
|
20074
20074
|
function fromInnerResponse(innerResponse, guard) {
|
|
20075
|
-
const response = new
|
|
20075
|
+
const response = new Response2(kConstruct);
|
|
20076
20076
|
setResponseState(response, innerResponse);
|
|
20077
20077
|
const headers = new Headers3(kConstruct);
|
|
20078
20078
|
setResponseHeaders(response, headers);
|
|
@@ -20126,14 +20126,14 @@ var require_response = __commonJS({
|
|
|
20126
20126
|
converter: webidl.converters.HeadersInit
|
|
20127
20127
|
}
|
|
20128
20128
|
]);
|
|
20129
|
-
webidl.is.Response = webidl.util.MakeTypeAssertion(
|
|
20129
|
+
webidl.is.Response = webidl.util.MakeTypeAssertion(Response2);
|
|
20130
20130
|
module2.exports = {
|
|
20131
20131
|
isNetworkError,
|
|
20132
20132
|
makeNetworkError,
|
|
20133
20133
|
makeResponse,
|
|
20134
20134
|
makeAppropriateNetworkError,
|
|
20135
20135
|
filterResponse,
|
|
20136
|
-
Response,
|
|
20136
|
+
Response: Response2,
|
|
20137
20137
|
cloneResponse,
|
|
20138
20138
|
fromInnerResponse,
|
|
20139
20139
|
getResponseState
|
|
@@ -99441,7 +99441,7 @@ var require_response2 = __commonJS({
|
|
|
99441
99441
|
}
|
|
99442
99442
|
return stream;
|
|
99443
99443
|
};
|
|
99444
|
-
var
|
|
99444
|
+
var Response2;
|
|
99445
99445
|
_.inherit(
|
|
99446
99446
|
/**
|
|
99447
99447
|
* Response holds data related to the request body. By default, it provides a nice wrapper for url-encoded,
|
|
@@ -99452,14 +99452,14 @@ var require_response2 = __commonJS({
|
|
|
99452
99452
|
*
|
|
99453
99453
|
* @param {Response.definition} options -
|
|
99454
99454
|
*/
|
|
99455
|
-
|
|
99456
|
-
|
|
99455
|
+
Response2 = function PostmanResponse(options) {
|
|
99456
|
+
Response2.super_.apply(this, arguments);
|
|
99457
99457
|
this.update(options || {});
|
|
99458
99458
|
},
|
|
99459
99459
|
Property
|
|
99460
99460
|
);
|
|
99461
99461
|
_.assign(
|
|
99462
|
-
|
|
99462
|
+
Response2.prototype,
|
|
99463
99463
|
/** @lends Response.prototype */
|
|
99464
99464
|
{
|
|
99465
99465
|
update(options) {
|
|
@@ -99525,7 +99525,7 @@ var require_response2 = __commonJS({
|
|
|
99525
99525
|
}
|
|
99526
99526
|
);
|
|
99527
99527
|
_.assign(
|
|
99528
|
-
|
|
99528
|
+
Response2.prototype,
|
|
99529
99529
|
/** @lends Response.prototype */
|
|
99530
99530
|
{
|
|
99531
99531
|
/**
|
|
@@ -99703,7 +99703,7 @@ var require_response2 = __commonJS({
|
|
|
99703
99703
|
}
|
|
99704
99704
|
);
|
|
99705
99705
|
_.assign(
|
|
99706
|
-
|
|
99706
|
+
Response2,
|
|
99707
99707
|
/** @lends Response */
|
|
99708
99708
|
{
|
|
99709
99709
|
/**
|
|
@@ -99721,7 +99721,7 @@ var require_response2 = __commonJS({
|
|
|
99721
99721
|
* @returns {Boolean}
|
|
99722
99722
|
*/
|
|
99723
99723
|
isResponse: function(obj) {
|
|
99724
|
-
return Boolean(obj) && (obj instanceof
|
|
99724
|
+
return Boolean(obj) && (obj instanceof Response2 || _.inSuperChain(obj.constructor, "_postman_propertyName", Response2._postman_propertyName));
|
|
99725
99725
|
},
|
|
99726
99726
|
/**
|
|
99727
99727
|
* Converts the response object from the request module to the postman responseBody format
|
|
@@ -99732,7 +99732,7 @@ var require_response2 = __commonJS({
|
|
|
99732
99732
|
* @todo Add a key: `originalRequest` to the returned object as well, referring to response.request
|
|
99733
99733
|
*/
|
|
99734
99734
|
createFromNode: function(response, cookies) {
|
|
99735
|
-
return new
|
|
99735
|
+
return new Response2({
|
|
99736
99736
|
cookie: cookies,
|
|
99737
99737
|
body: response.body.toString(),
|
|
99738
99738
|
stream: response.body,
|
|
@@ -99811,7 +99811,7 @@ var require_response2 = __commonJS({
|
|
|
99811
99811
|
}
|
|
99812
99812
|
);
|
|
99813
99813
|
module2.exports = {
|
|
99814
|
-
Response
|
|
99814
|
+
Response: Response2
|
|
99815
99815
|
};
|
|
99816
99816
|
}
|
|
99817
99817
|
});
|
|
@@ -99825,7 +99825,7 @@ var require_item = __commonJS({
|
|
|
99825
99825
|
var EventList = require_event_list().EventList;
|
|
99826
99826
|
var Request = require_request13().Request;
|
|
99827
99827
|
var RequestAuth = require_request_auth().RequestAuth;
|
|
99828
|
-
var
|
|
99828
|
+
var Response2 = require_response2().Response;
|
|
99829
99829
|
var Item;
|
|
99830
99830
|
var OBJECT = "object";
|
|
99831
99831
|
var STRING = "string";
|
|
@@ -99892,7 +99892,7 @@ var require_item = __commonJS({
|
|
|
99892
99892
|
*
|
|
99893
99893
|
* @type {PropertyList<Response>}
|
|
99894
99894
|
*/
|
|
99895
|
-
responses: new PropertyList(
|
|
99895
|
+
responses: new PropertyList(Response2, this, definition && definition.response),
|
|
99896
99896
|
/**
|
|
99897
99897
|
* Events are a set of of {@link Script}s that are executed when certain activities are triggered on an
|
|
99898
99898
|
* Item. For example, on defining an event that listens to the "test" event, would cause the associated
|
|
@@ -133661,6 +133661,54 @@ var HttpError = class _HttpError extends Error {
|
|
|
133661
133661
|
}
|
|
133662
133662
|
};
|
|
133663
133663
|
|
|
133664
|
+
// src/lib/postman/pmak-diagnostics.ts
|
|
133665
|
+
var memo = /* @__PURE__ */ new Map();
|
|
133666
|
+
var normalize3 = (value) => new URL(value.trim()).toString().replace(/\/+$/, "");
|
|
133667
|
+
function maskPmakDiagnostic(message, secrets) {
|
|
133668
|
+
let masked = String(message);
|
|
133669
|
+
for (const secret of secrets) if (secret) masked = masked.split(secret).join("***");
|
|
133670
|
+
return Array.from(masked, (character) => {
|
|
133671
|
+
const code = character.codePointAt(0) ?? 0;
|
|
133672
|
+
return code <= 31 || code >= 127 && code <= 159 ? " " : character;
|
|
133673
|
+
}).join("").replace(/\s+/g, " ").trim();
|
|
133674
|
+
}
|
|
133675
|
+
function formatRejectedMint(original, result) {
|
|
133676
|
+
const teamId = typeof result.payload?.user?.teamId === "number" ? ` (team ${(result.payload?.user).teamId})` : "";
|
|
133677
|
+
if (result.kind === "personal") return `Personal API key detected, cannot mint a service-account access token${teamId}.`;
|
|
133678
|
+
if (result.kind === "service-account") return `The postman-api-key authenticates (GET /me OK) but was rejected by POST /service-account-tokens${teamId} and lacks permission to mint access tokens.`;
|
|
133679
|
+
if (result.kind === "invalid") return "The postman-api-key is invalid, disabled, or expired.";
|
|
133680
|
+
return original;
|
|
133681
|
+
}
|
|
133682
|
+
async function inspectPmakIdentity(options) {
|
|
133683
|
+
const apiBaseUrl = normalize3(options.apiBaseUrl);
|
|
133684
|
+
const key = `${apiBaseUrl}\0${options.apiKey}`;
|
|
133685
|
+
let pending = memo.get(key);
|
|
133686
|
+
if (!pending) {
|
|
133687
|
+
pending = (async () => {
|
|
133688
|
+
try {
|
|
133689
|
+
const timeout = AbortSignal.timeout(options.timeoutMs ?? 2e3);
|
|
133690
|
+
const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
|
|
133691
|
+
const response = await (options.fetchImpl ?? fetch)(`${apiBaseUrl}/me`, { method: "GET", headers: { "X-Api-Key": options.apiKey }, signal });
|
|
133692
|
+
if (response.status === 401 || response.status === 403) return { kind: "invalid", status: response.status };
|
|
133693
|
+
if (!response.ok) return { kind: "inconclusive", status: response.status };
|
|
133694
|
+
const payload = await response.json().catch(() => void 0);
|
|
133695
|
+
const user = payload?.user;
|
|
133696
|
+
if (!user || typeof user !== "object" || Array.isArray(user)) return { kind: "inconclusive", payload };
|
|
133697
|
+
const record = user;
|
|
133698
|
+
if (typeof record.username === "string" && record.username || typeof record.email === "string" && record.email) return { kind: "personal", status: response.status, payload };
|
|
133699
|
+
if ("username" in record && "email" in record && (record.username == null || record.username === "") && (record.email == null || record.email === "")) return { kind: "service-account", status: response.status, payload };
|
|
133700
|
+
return { kind: "inconclusive", payload };
|
|
133701
|
+
} catch {
|
|
133702
|
+
return { kind: "inconclusive" };
|
|
133703
|
+
}
|
|
133704
|
+
})();
|
|
133705
|
+
memo.set(key, pending);
|
|
133706
|
+
}
|
|
133707
|
+
const result = await pending;
|
|
133708
|
+
if (options.mode === "preflight" && result.kind === "inconclusive") memo.delete(key);
|
|
133709
|
+
return result;
|
|
133710
|
+
}
|
|
133711
|
+
|
|
133664
133712
|
// src/lib/postman/credential-identity.ts
|
|
133665
133713
|
var sessionPath = "/api/sessions/current";
|
|
133666
133714
|
var SESSION_MAX_ATTEMPTS = 3;
|
|
@@ -133754,14 +133802,8 @@ async function resolvePmakIdentity(opts) {
|
|
|
133754
133802
|
}
|
|
133755
133803
|
async function probePmakIdentity(baseUrl, apiKey, fetchImpl) {
|
|
133756
133804
|
try {
|
|
133757
|
-
const
|
|
133758
|
-
|
|
133759
|
-
headers: { "X-Api-Key": apiKey }
|
|
133760
|
-
});
|
|
133761
|
-
if (!response.ok) {
|
|
133762
|
-
return void 0;
|
|
133763
|
-
}
|
|
133764
|
-
const payload = asRecord(await response.json());
|
|
133805
|
+
const diagnostic = await inspectPmakIdentity({ apiBaseUrl: baseUrl, apiKey, fetchImpl });
|
|
133806
|
+
const payload = asRecord(diagnostic.payload);
|
|
133765
133807
|
const user = asRecord(payload?.user);
|
|
133766
133808
|
if (!user) {
|
|
133767
133809
|
return void 0;
|
|
@@ -134063,6 +134105,39 @@ function adviseFromHttpError(err, ctx) {
|
|
|
134063
134105
|
return new Error(ctx.mask(advice), { cause: err });
|
|
134064
134106
|
}
|
|
134065
134107
|
|
|
134108
|
+
// src/lib/postman/app-version.ts
|
|
134109
|
+
var UPDATE_URL = "https://dl.pstmn.io/update/status?currentVersion=12.0.0&platform=osx_arm64";
|
|
134110
|
+
var FLOOR_VERSION = "12.0.0";
|
|
134111
|
+
var VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
134112
|
+
var PostmanAppVersionProvider = class {
|
|
134113
|
+
fetchImpl;
|
|
134114
|
+
requestTimeoutMs;
|
|
134115
|
+
pending;
|
|
134116
|
+
constructor(options = {}) {
|
|
134117
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
134118
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? 2e3;
|
|
134119
|
+
}
|
|
134120
|
+
async get() {
|
|
134121
|
+
if (process.env.POSTMAN_GATEWAY_APP_VERSION === "off") return void 0;
|
|
134122
|
+
this.pending ??= this.resolve();
|
|
134123
|
+
return this.pending;
|
|
134124
|
+
}
|
|
134125
|
+
async resolve() {
|
|
134126
|
+
try {
|
|
134127
|
+
const response = await this.fetchImpl(UPDATE_URL, {
|
|
134128
|
+
signal: AbortSignal.timeout(this.requestTimeoutMs)
|
|
134129
|
+
});
|
|
134130
|
+
if (!response.ok) return FLOOR_VERSION;
|
|
134131
|
+
const payload = await response.json();
|
|
134132
|
+
const version = typeof payload.version === "string" ? payload.version : "";
|
|
134133
|
+
return VERSION_PATTERN.test(version) ? version : FLOOR_VERSION;
|
|
134134
|
+
} catch {
|
|
134135
|
+
return FLOOR_VERSION;
|
|
134136
|
+
}
|
|
134137
|
+
}
|
|
134138
|
+
};
|
|
134139
|
+
var defaultPostmanAppVersionProvider = new PostmanAppVersionProvider();
|
|
134140
|
+
|
|
134066
134141
|
// src/lib/postman/internal-integration-adapter.ts
|
|
134067
134142
|
function extractDuplicateWorkspaceId(body) {
|
|
134068
134143
|
try {
|
|
@@ -134082,6 +134157,8 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134082
134157
|
secretMasker;
|
|
134083
134158
|
teamId;
|
|
134084
134159
|
workerBaseUrl;
|
|
134160
|
+
gateway;
|
|
134161
|
+
appVersionProvider;
|
|
134085
134162
|
constructor(options) {
|
|
134086
134163
|
this.accessToken = String(options.accessToken || "").trim();
|
|
134087
134164
|
this.getAccessToken = options.getAccessToken;
|
|
@@ -134094,6 +134171,8 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134094
134171
|
this.workerBaseUrl = String(
|
|
134095
134172
|
options.workerBaseUrl || "https://catalog-admin.postman-account2009.workers.dev"
|
|
134096
134173
|
).replace(/\/+$/, "");
|
|
134174
|
+
this.gateway = options.gateway;
|
|
134175
|
+
this.appVersionProvider = options.appVersionProvider ?? defaultPostmanAppVersionProvider;
|
|
134097
134176
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.accessToken]);
|
|
134098
134177
|
}
|
|
134099
134178
|
/** Live access token: re-minted value when a provider accessor is wired, else the captured one. */
|
|
@@ -134101,7 +134180,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134101
134180
|
return this.getAccessToken ? String(this.getAccessToken() || "").trim() : this.accessToken;
|
|
134102
134181
|
}
|
|
134103
134182
|
/** Build Bifrost proxy headers. Only includes x-entity-team-id for org-mode teams. */
|
|
134104
|
-
bifrostHeaders() {
|
|
134183
|
+
async bifrostHeaders() {
|
|
134105
134184
|
const headers = {
|
|
134106
134185
|
"Content-Type": "application/json",
|
|
134107
134186
|
"x-access-token": this.currentToken()
|
|
@@ -134109,6 +134188,8 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134109
134188
|
if (this.teamId && this.orgMode) {
|
|
134110
134189
|
headers["x-entity-team-id"] = this.teamId;
|
|
134111
134190
|
}
|
|
134191
|
+
const appVersion = await this.appVersionProvider.get();
|
|
134192
|
+
if (appVersion) headers["x-app-version"] = appVersion;
|
|
134112
134193
|
return headers;
|
|
134113
134194
|
}
|
|
134114
134195
|
/** Reactive error-advice context, enriched with the preflight session memo when present. */
|
|
@@ -134139,6 +134220,58 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134139
134220
|
if (associations.length === 0) {
|
|
134140
134221
|
return;
|
|
134141
134222
|
}
|
|
134223
|
+
const mode = process.env.POSTMAN_SYSTEM_ENV_ASSOCIATION_MODE ?? "direct";
|
|
134224
|
+
if (mode !== "direct" && mode !== "worker") {
|
|
134225
|
+
throw new Error("POSTMAN_SYSTEM_ENV_ASSOCIATION_MODE must be direct or worker");
|
|
134226
|
+
}
|
|
134227
|
+
if (mode === "direct") {
|
|
134228
|
+
if (!this.gateway) {
|
|
134229
|
+
throw new Error("Direct system-environment association requires the access-token gateway");
|
|
134230
|
+
}
|
|
134231
|
+
const groups = /* @__PURE__ */ new Map();
|
|
134232
|
+
for (const association of associations) {
|
|
134233
|
+
const systemEnvId = String(association.systemEnvId || "").trim();
|
|
134234
|
+
const uid = String(association.envUid || "").trim();
|
|
134235
|
+
if (!systemEnvId || !uid) continue;
|
|
134236
|
+
const key = `${systemEnvId}\0${workspaceId}`;
|
|
134237
|
+
const uids = groups.get(key) ?? /* @__PURE__ */ new Set();
|
|
134238
|
+
uids.add(uid);
|
|
134239
|
+
groups.set(key, uids);
|
|
134240
|
+
}
|
|
134241
|
+
for (const [key, uids] of [...groups.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
134242
|
+
const [systemEnvironmentId, groupedWorkspaceId] = key.split("\0");
|
|
134243
|
+
const postmanEnvironmentIds = [...uids].sort();
|
|
134244
|
+
let response2;
|
|
134245
|
+
try {
|
|
134246
|
+
response2 = await this.gateway.requestJson({
|
|
134247
|
+
service: "api-catalog",
|
|
134248
|
+
method: "post",
|
|
134249
|
+
path: "/api/system-envs/associations",
|
|
134250
|
+
body: {
|
|
134251
|
+
systemEnvironmentId,
|
|
134252
|
+
workspaceEntries: [{ workspaceId: groupedWorkspaceId, postmanEnvironmentIds }]
|
|
134253
|
+
},
|
|
134254
|
+
fallback: "none"
|
|
134255
|
+
}, { retryTransient: true });
|
|
134256
|
+
} catch (error) {
|
|
134257
|
+
if (error instanceof HttpError) {
|
|
134258
|
+
throw adviseFromHttpError(error, this.adviceContext("system environment association")) ?? error;
|
|
134259
|
+
}
|
|
134260
|
+
throw error;
|
|
134261
|
+
}
|
|
134262
|
+
if (!response2 || response2.success !== true) {
|
|
134263
|
+
throw new Error("SYSTEM_ENV_ASSOCIATION_INCOMPLETE");
|
|
134264
|
+
}
|
|
134265
|
+
if (response2.data !== void 0) {
|
|
134266
|
+
if (!Array.isArray(response2.data)) throw new Error("SYSTEM_ENV_ASSOCIATION_INCOMPLETE");
|
|
134267
|
+
const seen = new Set(response2.data.filter((row) => !!row && typeof row === "object").map((row) => `${row.systemEnvironmentId}\0${row.workspaceId}\0${row.postmanEnvironmentId}`));
|
|
134268
|
+
if (!postmanEnvironmentIds.every((uid) => seen.has(`${systemEnvironmentId}\0${groupedWorkspaceId}\0${uid}`))) {
|
|
134269
|
+
throw new Error("SYSTEM_ENV_ASSOCIATION_INCOMPLETE");
|
|
134270
|
+
}
|
|
134271
|
+
}
|
|
134272
|
+
}
|
|
134273
|
+
return;
|
|
134274
|
+
}
|
|
134142
134275
|
const token = this.currentToken();
|
|
134143
134276
|
const response = await this.fetchImpl(
|
|
134144
134277
|
`${this.workerBaseUrl}/api/internal/system-envs/associate`,
|
|
@@ -134196,7 +134329,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134196
134329
|
try {
|
|
134197
134330
|
const response = await this.fetchImpl(url, {
|
|
134198
134331
|
method: "POST",
|
|
134199
|
-
headers: this.bifrostHeaders(),
|
|
134332
|
+
headers: await this.bifrostHeaders(),
|
|
134200
134333
|
body: JSON.stringify(payload)
|
|
134201
134334
|
});
|
|
134202
134335
|
let parsed = {};
|
|
@@ -134285,7 +134418,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134285
134418
|
versionControl: true
|
|
134286
134419
|
}
|
|
134287
134420
|
};
|
|
134288
|
-
const headers = this.bifrostHeaders();
|
|
134421
|
+
const headers = await this.bifrostHeaders();
|
|
134289
134422
|
const response = await this.fetchImpl(url, {
|
|
134290
134423
|
method: "POST",
|
|
134291
134424
|
headers,
|
|
@@ -134340,7 +134473,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134340
134473
|
try {
|
|
134341
134474
|
const response = await this.fetchImpl(`${this.bifrostBaseUrl}/ws/proxy`, {
|
|
134342
134475
|
method: "POST",
|
|
134343
|
-
headers: this.bifrostHeaders(),
|
|
134476
|
+
headers: await this.bifrostHeaders(),
|
|
134344
134477
|
body: JSON.stringify({
|
|
134345
134478
|
service: "workspaces",
|
|
134346
134479
|
method: "GET",
|
|
@@ -134371,7 +134504,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134371
134504
|
}
|
|
134372
134505
|
async createApiKey(name) {
|
|
134373
134506
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
134374
|
-
const headers = this.bifrostHeaders();
|
|
134507
|
+
const headers = await this.bifrostHeaders();
|
|
134375
134508
|
const payload = {
|
|
134376
134509
|
service: "identity",
|
|
134377
134510
|
method: "POST",
|
|
@@ -134456,6 +134589,16 @@ async function retry(operation, options = {}) {
|
|
|
134456
134589
|
}
|
|
134457
134590
|
throw new Error("Retry exhausted without returning or throwing");
|
|
134458
134591
|
}
|
|
134592
|
+
function fullJitterDelayMs(attempt, baseMs, capMs, random = Math.random) {
|
|
134593
|
+
return Math.floor(random() * Math.max(0, Math.min(capMs, baseMs * 2 ** Math.max(0, attempt))));
|
|
134594
|
+
}
|
|
134595
|
+
function parseRetryAfterMs2(value) {
|
|
134596
|
+
const trimmed = value?.trim();
|
|
134597
|
+
if (!trimmed) return void 0;
|
|
134598
|
+
if (/^\d+$/.test(trimmed)) return Number(trimmed) * 1e3;
|
|
134599
|
+
const time = Date.parse(trimmed);
|
|
134600
|
+
return Number.isNaN(time) ? void 0 : Math.max(0, time - Date.now());
|
|
134601
|
+
}
|
|
134459
134602
|
|
|
134460
134603
|
// src/contracts.ts
|
|
134461
134604
|
var postmanRepoSyncActionContract = {
|
|
@@ -134885,6 +135028,17 @@ var PostmanGatewayAssetsClient = class {
|
|
|
134885
135028
|
return data.map((entry) => this.asRecord(entry)).filter((entry) => entry !== null).map((entry) => ({ uid: String(entry.id ?? entry.uid ?? "").trim(), name: String(entry.name ?? "").trim() })).filter((entry) => entry.uid && entry.name);
|
|
134886
135029
|
}
|
|
134887
135030
|
async getSpecContent(specId) {
|
|
135031
|
+
if (process.env.POSTMAN_SPEC_TREE_FAST_PATH !== "off") {
|
|
135032
|
+
try {
|
|
135033
|
+
const treeContent = await this.getSpecContentFromTree(specId);
|
|
135034
|
+
if (treeContent !== void 0) return treeContent;
|
|
135035
|
+
} catch (error) {
|
|
135036
|
+
if (!(error instanceof HttpError) || ![403, 404, 405, 501].includes(error.status)) throw error;
|
|
135037
|
+
}
|
|
135038
|
+
}
|
|
135039
|
+
return this.getSpecContentLegacy(specId);
|
|
135040
|
+
}
|
|
135041
|
+
async getSpecContentLegacy(specId) {
|
|
134888
135042
|
const files = await this.gateway.requestJson({
|
|
134889
135043
|
service: "specification",
|
|
134890
135044
|
method: "get",
|
|
@@ -134903,6 +135057,46 @@ var PostmanGatewayAssetsClient = class {
|
|
|
134903
135057
|
const record = this.dataOf(file);
|
|
134904
135058
|
return typeof record?.content === "string" ? record.content : void 0;
|
|
134905
135059
|
}
|
|
135060
|
+
/** Minimal `/tree` reader: validate the entire returned inventory before selecting ROOT. */
|
|
135061
|
+
async getSpecContentFromTree(specId) {
|
|
135062
|
+
const rows = [];
|
|
135063
|
+
const cursors = /* @__PURE__ */ new Set();
|
|
135064
|
+
let cursor;
|
|
135065
|
+
for (let page = 0; page < 100; page += 1) {
|
|
135066
|
+
const response = await this.gateway.requestJson({
|
|
135067
|
+
service: "specification",
|
|
135068
|
+
method: "get",
|
|
135069
|
+
path: `/specifications/${specId}/tree`,
|
|
135070
|
+
query: { fields: "id,name,type,path,parentId,fileType,content", limit: 100, ...cursor ? { cursor } : {} }
|
|
135071
|
+
});
|
|
135072
|
+
if (!Array.isArray(response?.data)) return void 0;
|
|
135073
|
+
for (const value of response.data) {
|
|
135074
|
+
const row = this.asRecord(value);
|
|
135075
|
+
if (!row || row.type === "FOLDER") continue;
|
|
135076
|
+
if (row.type !== "FILE" || typeof row.id !== "string" || !row.id.trim() || typeof row.path !== "string" || !row.path.trim() || typeof row.content !== "string" || typeof row.fileType !== "string" || !row.fileType.trim()) return void 0;
|
|
135077
|
+
const path5 = row.path.replace(/\\/g, "/").normalize("NFC");
|
|
135078
|
+
if (path5.startsWith("/") || path5.split("/").some((part) => part === ".." || !part)) throw new Error("CONTRACT_DEFINITION_PATH_INVALID");
|
|
135079
|
+
rows.push({ ...row, path: path5 });
|
|
135080
|
+
}
|
|
135081
|
+
const meta = this.asRecord(response?.meta);
|
|
135082
|
+
const cursorValue = this.asRecord(meta?.cursor)?.next;
|
|
135083
|
+
const next = typeof cursorValue === "string" && cursorValue.trim() ? cursorValue.trim() : void 0;
|
|
135084
|
+
if (!next) break;
|
|
135085
|
+
if (cursors.has(next)) throw new Error("SPEC_TREE_CURSOR_REPEATED");
|
|
135086
|
+
cursors.add(next);
|
|
135087
|
+
if (page === 99) throw new Error("SPEC_TREE_PAGE_LIMIT_EXCEEDED");
|
|
135088
|
+
cursor = next;
|
|
135089
|
+
}
|
|
135090
|
+
const paths = /* @__PURE__ */ new Set();
|
|
135091
|
+
for (const row of rows) {
|
|
135092
|
+
const path5 = String(row.path).toLocaleLowerCase();
|
|
135093
|
+
if (paths.has(path5)) throw new Error("CONTRACT_DEFINITION_DUPLICATE_PATH");
|
|
135094
|
+
paths.add(path5);
|
|
135095
|
+
}
|
|
135096
|
+
const roots = rows.filter((row) => row.fileType === "ROOT");
|
|
135097
|
+
if (roots.length !== 1) throw new Error("CONTRACT_DEFINITION_INVENTORY_INVALID");
|
|
135098
|
+
return String(roots[0]?.content);
|
|
135099
|
+
}
|
|
134906
135100
|
async listSpecCollections(specId) {
|
|
134907
135101
|
const response = await this.gateway.requestJson({
|
|
134908
135102
|
service: "specification",
|
|
@@ -135462,10 +135656,12 @@ var PostmanGatewayAssetsClient = class {
|
|
|
135462
135656
|
// src/lib/postman/token-provider.ts
|
|
135463
135657
|
var MintError = class extends Error {
|
|
135464
135658
|
permanent;
|
|
135465
|
-
|
|
135659
|
+
status;
|
|
135660
|
+
constructor(message, permanent, status) {
|
|
135466
135661
|
super(message);
|
|
135467
135662
|
this.name = "MintError";
|
|
135468
135663
|
this.permanent = permanent;
|
|
135664
|
+
this.status = status;
|
|
135469
135665
|
}
|
|
135470
135666
|
};
|
|
135471
135667
|
function extractAccessToken(payload) {
|
|
@@ -135545,7 +135741,8 @@ var AccessTokenProvider = class {
|
|
|
135545
135741
|
if (status === 401 || status === 403) {
|
|
135546
135742
|
throw new MintError(
|
|
135547
135743
|
`postman: re-mint failed because the postman-api-key was rejected (PMAK rejected, HTTP ${status}); confirm it is a valid, enabled service-account PMAK for the intended team.`,
|
|
135548
|
-
true
|
|
135744
|
+
true,
|
|
135745
|
+
status
|
|
135549
135746
|
);
|
|
135550
135747
|
}
|
|
135551
135748
|
if (status === 400 && body.toLowerCase().includes("service accounts not enabled")) {
|
|
@@ -135570,26 +135767,9 @@ var AccessTokenProvider = class {
|
|
|
135570
135767
|
}
|
|
135571
135768
|
};
|
|
135572
135769
|
async function describeMintFailure(mintError, apiKey, apiBaseUrl, fetchImpl) {
|
|
135573
|
-
const raw = mintError instanceof Error ? mintError.message : String(mintError);
|
|
135574
|
-
|
|
135575
|
-
|
|
135576
|
-
return raw;
|
|
135577
|
-
}
|
|
135578
|
-
try {
|
|
135579
|
-
const me = await fetchImpl(`${apiBaseUrl}/me`, { headers: { "x-api-key": apiKey } });
|
|
135580
|
-
if (me.ok) {
|
|
135581
|
-
const body = await me.json().catch(() => void 0);
|
|
135582
|
-
const user = body?.user;
|
|
135583
|
-
const looksPersonal = Boolean(user && (user.username || user.email));
|
|
135584
|
-
if (looksPersonal) {
|
|
135585
|
-
return "Personal API key detected, cannot mint a service-account access token. POST /service-account-tokens only accepts a SERVICE-ACCOUNT API key; this postman-api-key belongs to a user account" + (user?.teamId ? ` (team ${user.teamId})` : "") + ". Create a service account in Team Settings and use its PMAK, or mint the token elsewhere and pass postman-access-token.";
|
|
135586
|
-
}
|
|
135587
|
-
return "The postman-api-key authenticates (GET /me OK) but was rejected by POST /service-account-tokens" + (user?.teamId ? ` (team ${user.teamId})` : "") + ". The service account likely lacks permission to mint access tokens, or service accounts are restricted for this team. Check the service account role in Team Settings, or pass a pre-minted postman-access-token.";
|
|
135588
|
-
}
|
|
135589
|
-
return "The postman-api-key is invalid, disabled, or expired (rejected by both POST /service-account-tokens and GET /me). Generate a fresh service-account PMAK in Team Settings and update the secret.";
|
|
135590
|
-
} catch {
|
|
135591
|
-
return raw;
|
|
135592
|
-
}
|
|
135770
|
+
const raw = maskPmakDiagnostic(mintError instanceof Error ? mintError.message : String(mintError), [apiKey]);
|
|
135771
|
+
if (!(mintError instanceof MintError) || mintError.status !== 401 && mintError.status !== 403) return raw;
|
|
135772
|
+
return formatRejectedMint(raw, await inspectPmakIdentity({ apiBaseUrl, apiKey, fetchImpl }));
|
|
135593
135773
|
}
|
|
135594
135774
|
async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetch) {
|
|
135595
135775
|
if (inputs.postmanAccessToken || !inputs.postmanApiKey) {
|
|
@@ -135638,6 +135818,10 @@ var AccessTokenGatewayClient = class {
|
|
|
135638
135818
|
fallbackBaseUrl;
|
|
135639
135819
|
retryBaseDelayMs;
|
|
135640
135820
|
sleepImpl;
|
|
135821
|
+
appVersionProvider;
|
|
135822
|
+
requestTimeoutMs;
|
|
135823
|
+
retryMaxDelayMs;
|
|
135824
|
+
randomImpl;
|
|
135641
135825
|
constructor(options) {
|
|
135642
135826
|
this.tokenProvider = options.tokenProvider;
|
|
135643
135827
|
this.bifrostBaseUrl = String(
|
|
@@ -135652,16 +135836,22 @@ var AccessTokenGatewayClient = class {
|
|
|
135652
135836
|
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
135653
135837
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
135654
135838
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
135839
|
+
this.appVersionProvider = options.appVersionProvider ?? defaultPostmanAppVersionProvider;
|
|
135840
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? 3e4;
|
|
135841
|
+
this.retryMaxDelayMs = options.retryMaxDelayMs ?? 5e3;
|
|
135842
|
+
this.randomImpl = options.randomImpl ?? Math.random;
|
|
135655
135843
|
}
|
|
135656
135844
|
configureTeamContext(teamId, orgMode) {
|
|
135657
135845
|
this.teamId = String(teamId || "").trim();
|
|
135658
135846
|
this.orgMode = orgMode;
|
|
135659
135847
|
}
|
|
135660
|
-
buildHeaders(extra) {
|
|
135848
|
+
async buildHeaders(extra) {
|
|
135849
|
+
const appVersion = await this.appVersionProvider.get();
|
|
135661
135850
|
const headers = {
|
|
135662
135851
|
"Content-Type": "application/json",
|
|
135663
135852
|
"x-access-token": this.tokenProvider.current(),
|
|
135664
|
-
...extra || {}
|
|
135853
|
+
...extra || {},
|
|
135854
|
+
...appVersion ? { "x-app-version": appVersion } : {}
|
|
135665
135855
|
};
|
|
135666
135856
|
if (this.teamId && this.orgMode) {
|
|
135667
135857
|
headers["x-entity-team-id"] = this.teamId;
|
|
@@ -135670,17 +135860,24 @@ var AccessTokenGatewayClient = class {
|
|
|
135670
135860
|
}
|
|
135671
135861
|
async send(request, baseUrl) {
|
|
135672
135862
|
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
135673
|
-
|
|
135674
|
-
|
|
135675
|
-
|
|
135676
|
-
|
|
135677
|
-
|
|
135678
|
-
|
|
135679
|
-
|
|
135680
|
-
|
|
135681
|
-
|
|
135682
|
-
|
|
135683
|
-
|
|
135863
|
+
const controller = new AbortController();
|
|
135864
|
+
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
135865
|
+
try {
|
|
135866
|
+
return await this.fetchImpl(url, {
|
|
135867
|
+
method: "POST",
|
|
135868
|
+
headers: await this.buildHeaders(request.headers),
|
|
135869
|
+
signal: controller.signal,
|
|
135870
|
+
body: JSON.stringify({
|
|
135871
|
+
service: request.service,
|
|
135872
|
+
method: request.method,
|
|
135873
|
+
path: request.path,
|
|
135874
|
+
...request.query !== void 0 ? { query: request.query } : {},
|
|
135875
|
+
...request.body !== void 0 ? { body: request.body } : {}
|
|
135876
|
+
})
|
|
135877
|
+
});
|
|
135878
|
+
} finally {
|
|
135879
|
+
clearTimeout(timer);
|
|
135880
|
+
}
|
|
135684
135881
|
}
|
|
135685
135882
|
/**
|
|
135686
135883
|
* One cold, serial attempt against the fallback base URL after the primary
|
|
@@ -135707,6 +135904,7 @@ var AccessTokenGatewayClient = class {
|
|
|
135707
135904
|
* they are the freshest authoritative answer.
|
|
135708
135905
|
*/
|
|
135709
135906
|
fallbackEligible(request, retryTransient) {
|
|
135907
|
+
if (request.fallback === "none") return false;
|
|
135710
135908
|
if (!this.fallbackBaseUrl) return false;
|
|
135711
135909
|
return retryTransient || request.fallback === "auto";
|
|
135712
135910
|
}
|
|
@@ -135736,7 +135934,7 @@ var AccessTokenGatewayClient = class {
|
|
|
135736
135934
|
response = await this.send(request);
|
|
135737
135935
|
} catch (error) {
|
|
135738
135936
|
if (retryTransient && attempt < this.maxRetries) {
|
|
135739
|
-
const delay = this.
|
|
135937
|
+
const delay = this.retryDelayMs(attempt);
|
|
135740
135938
|
attempt += 1;
|
|
135741
135939
|
await this.sleepImpl(delay);
|
|
135742
135940
|
continue;
|
|
@@ -135746,7 +135944,17 @@ var AccessTokenGatewayClient = class {
|
|
|
135746
135944
|
throw error;
|
|
135747
135945
|
}
|
|
135748
135946
|
if (response.ok) {
|
|
135749
|
-
|
|
135947
|
+
const okBody = await response.text().catch(() => "");
|
|
135948
|
+
const inner = this.innerStatus(okBody);
|
|
135949
|
+
if (inner !== void 0) {
|
|
135950
|
+
if (retryTransient && this.isTransient(inner, okBody) && attempt < this.maxRetries) {
|
|
135951
|
+
await this.sleepImpl(this.retryDelayMs(attempt));
|
|
135952
|
+
attempt += 1;
|
|
135953
|
+
continue;
|
|
135954
|
+
}
|
|
135955
|
+
throw this.toInnerHttpError(request, inner, okBody);
|
|
135956
|
+
}
|
|
135957
|
+
return this.rebuildResponse(response, okBody);
|
|
135750
135958
|
}
|
|
135751
135959
|
const body = await response.text().catch(() => "");
|
|
135752
135960
|
if (isExpiredAuthError(response.status, body) && this.tokenProvider.canRefresh()) {
|
|
@@ -135758,8 +135966,8 @@ var AccessTokenGatewayClient = class {
|
|
|
135758
135966
|
const retryBody = await response.text().catch(() => "");
|
|
135759
135967
|
throw this.toHttpError(request, response, retryBody);
|
|
135760
135968
|
}
|
|
135761
|
-
if (retryTransient &&
|
|
135762
|
-
const delay = this.
|
|
135969
|
+
if (retryTransient && this.isTransient(response.status, body) && attempt < this.maxRetries) {
|
|
135970
|
+
const delay = this.retryDelayMs(attempt, parseRetryAfterMs2(response.headers.get("retry-after")));
|
|
135763
135971
|
attempt += 1;
|
|
135764
135972
|
await this.sleepImpl(delay);
|
|
135765
135973
|
continue;
|
|
@@ -135769,6 +135977,24 @@ var AccessTokenGatewayClient = class {
|
|
|
135769
135977
|
throw this.toHttpError(request, response, body);
|
|
135770
135978
|
}
|
|
135771
135979
|
}
|
|
135980
|
+
retryDelayMs(attempt, retryAfter) {
|
|
135981
|
+
return retryAfter === void 0 ? fullJitterDelayMs(attempt, this.retryBaseDelayMs, this.retryMaxDelayMs, this.randomImpl) : Math.min(this.retryMaxDelayMs, retryAfter);
|
|
135982
|
+
}
|
|
135983
|
+
isTransient(status, body) {
|
|
135984
|
+
return status === 408 || status === 429 || status >= 500 || /ESOCKETTIMEDOUT|ETIMEDOUT|ECONNRESET|serverError|downstream/.test(body);
|
|
135985
|
+
}
|
|
135986
|
+
innerStatus(body) {
|
|
135987
|
+
try {
|
|
135988
|
+
const value = JSON.parse(body);
|
|
135989
|
+
const status = Number(value.status ?? value.statusCode);
|
|
135990
|
+
return value.error || value.success === false || status >= 400 ? status >= 400 ? status : 502 : void 0;
|
|
135991
|
+
} catch {
|
|
135992
|
+
return void 0;
|
|
135993
|
+
}
|
|
135994
|
+
}
|
|
135995
|
+
rebuildResponse(response, body) {
|
|
135996
|
+
return new Response([204, 205, 304].includes(response.status) ? null : body, { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
135997
|
+
}
|
|
135772
135998
|
/** Send a gateway request and parse the JSON body, or null when empty. */
|
|
135773
135999
|
async requestJson(request, options = {}) {
|
|
135774
136000
|
const response = await this.request(request, options);
|
|
@@ -135815,11 +136041,19 @@ var AccessTokenGatewayClient = class {
|
|
|
135815
136041
|
url: `${this.bifrostBaseUrl}/ws/proxy (${request.service}: ${request.method} ${request.path})`,
|
|
135816
136042
|
status: response.status,
|
|
135817
136043
|
statusText: response.statusText,
|
|
135818
|
-
requestHeaders:
|
|
136044
|
+
requestHeaders: {
|
|
136045
|
+
"Content-Type": "application/json",
|
|
136046
|
+
"x-access-token": this.tokenProvider.current(),
|
|
136047
|
+
...request.headers || {},
|
|
136048
|
+
...this.teamId && this.orgMode ? { "x-entity-team-id": this.teamId } : {}
|
|
136049
|
+
},
|
|
135819
136050
|
responseBody: this.secretMasker(body),
|
|
135820
136051
|
secretValues: [this.tokenProvider.current()]
|
|
135821
136052
|
});
|
|
135822
136053
|
}
|
|
136054
|
+
toInnerHttpError(request, status, body) {
|
|
136055
|
+
return new HttpError({ method: request.method.toUpperCase(), url: `${this.bifrostBaseUrl}/ws/proxy (${request.service}: ${request.method} ${request.path}) [inner]`, status, statusText: "Inner Error", requestHeaders: { "x-access-token": this.tokenProvider.current() }, responseBody: this.secretMasker(body), secretValues: [this.tokenProvider.current()] });
|
|
136056
|
+
}
|
|
135823
136057
|
};
|
|
135824
136058
|
|
|
135825
136059
|
// src/lib/repo/branch-decision.ts
|
|
@@ -136742,8 +136976,8 @@ function stripVolatileFields(obj) {
|
|
|
136742
136976
|
}
|
|
136743
136977
|
return obj;
|
|
136744
136978
|
}
|
|
136745
|
-
function writeJsonFile(path5, content,
|
|
136746
|
-
const data =
|
|
136979
|
+
function writeJsonFile(path5, content, normalize4 = false) {
|
|
136980
|
+
const data = normalize4 ? stripVolatileFields(content) : content;
|
|
136747
136981
|
(0, import_node_fs4.writeFileSync)(path5, JSON.stringify(data, null, 2));
|
|
136748
136982
|
}
|
|
136749
136983
|
function buildMappedSpecCloudKey(mappedSource, specSyncMode, releaseLabel) {
|
|
@@ -137766,7 +138000,8 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
137766
138000
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
137767
138001
|
orgMode: inputs.orgMode,
|
|
137768
138002
|
teamId: resolved.teamId,
|
|
137769
|
-
secretMasker: masker
|
|
138003
|
+
secretMasker: masker,
|
|
138004
|
+
gateway
|
|
137770
138005
|
});
|
|
137771
138006
|
return {
|
|
137772
138007
|
teamId: resolved.teamId,
|