@postman-cse/onboarding-insights 1.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -12167,7 +12167,7 @@ var require_response = __commonJS({
12167
12167
  var assert = require("node:assert");
12168
12168
  var { types } = require("node:util");
12169
12169
  var textEncoder = new TextEncoder("utf-8");
12170
- var Response = class _Response {
12170
+ var Response2 = class _Response {
12171
12171
  // Creates network error Response.
12172
12172
  static error() {
12173
12173
  const responseObject = fromInnerResponse(makeNetworkError(), "immutable");
@@ -12310,8 +12310,8 @@ var require_response = __commonJS({
12310
12310
  return `Response ${nodeUtil.formatWithOptions(options, properties)}`;
12311
12311
  }
12312
12312
  };
12313
- mixinBody(Response);
12314
- Object.defineProperties(Response.prototype, {
12313
+ mixinBody(Response2);
12314
+ Object.defineProperties(Response2.prototype, {
12315
12315
  type: kEnumerableProperty,
12316
12316
  url: kEnumerableProperty,
12317
12317
  status: kEnumerableProperty,
@@ -12327,7 +12327,7 @@ var require_response = __commonJS({
12327
12327
  configurable: true
12328
12328
  }
12329
12329
  });
12330
- Object.defineProperties(Response, {
12330
+ Object.defineProperties(Response2, {
12331
12331
  json: kEnumerableProperty,
12332
12332
  redirect: kEnumerableProperty,
12333
12333
  error: kEnumerableProperty
@@ -12460,7 +12460,7 @@ var require_response = __commonJS({
12460
12460
  }
12461
12461
  }
12462
12462
  function fromInnerResponse(innerResponse, guard) {
12463
- const response = new Response(kConstruct);
12463
+ const response = new Response2(kConstruct);
12464
12464
  response[kState] = innerResponse;
12465
12465
  response[kHeaders] = new Headers3(kConstruct);
12466
12466
  setHeadersList(response[kHeaders], innerResponse.headersList);
@@ -12528,7 +12528,7 @@ var require_response = __commonJS({
12528
12528
  makeResponse,
12529
12529
  makeAppropriateNetworkError,
12530
12530
  filterResponse,
12531
- Response,
12531
+ Response: Response2,
12532
12532
  cloneResponse,
12533
12533
  fromInnerResponse
12534
12534
  };
@@ -15200,7 +15200,7 @@ var require_cache = __commonJS({
15200
15200
  var { urlEquals, getFieldValues } = require_util5();
15201
15201
  var { kEnumerableProperty, isDisturbed } = require_util();
15202
15202
  var { webidl } = require_webidl();
15203
- var { Response, cloneResponse, fromInnerResponse } = require_response();
15203
+ var { Response: Response2, cloneResponse, fromInnerResponse } = require_response();
15204
15204
  var { Request, fromInnerRequest } = require_request2();
15205
15205
  var { kState } = require_symbols2();
15206
15206
  var { fetching } = require_fetch();
@@ -15727,7 +15727,7 @@ var require_cache = __commonJS({
15727
15727
  converter: webidl.converters.DOMString
15728
15728
  }
15729
15729
  ]);
15730
- webidl.converters.Response = webidl.interfaceConverter(Response);
15730
+ webidl.converters.Response = webidl.interfaceConverter(Response2);
15731
15731
  webidl.converters["sequence<RequestInfo>"] = webidl.sequenceConverter(
15732
15732
  webidl.converters.RequestInfo
15733
15733
  );
@@ -18685,9 +18685,259 @@ __export(cli_exports, {
18685
18685
  toDotenv: () => toDotenv
18686
18686
  });
18687
18687
  module.exports = __toCommonJS(cli_exports);
18688
- var import_node_fs = require("node:fs");
18688
+ var import_node_fs2 = require("node:fs");
18689
18689
  var import_promises = require("node:fs/promises");
18690
- var import_node_path = __toESM(require("node:path"), 1);
18690
+ var import_node_path2 = __toESM(require("node:path"), 1);
18691
+
18692
+ // src/lib/retry.ts
18693
+ function sleep(delayMs) {
18694
+ return new Promise((resolve2) => {
18695
+ setTimeout(resolve2, delayMs);
18696
+ });
18697
+ }
18698
+ function normalizeRetryOptions(options) {
18699
+ return {
18700
+ maxAttempts: Math.max(1, options.maxAttempts ?? 3),
18701
+ delayMs: Math.max(0, options.delayMs ?? 2e3),
18702
+ backoffMultiplier: Math.max(1, options.backoffMultiplier ?? 1),
18703
+ maxDelayMs: options.maxDelayMs === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, options.maxDelayMs),
18704
+ onRetry: options.onRetry ?? (async () => void 0),
18705
+ shouldRetry: options.shouldRetry ?? (() => true),
18706
+ sleep: options.sleep ?? sleep
18707
+ };
18708
+ }
18709
+ async function retry(operation, options = {}) {
18710
+ const normalized = normalizeRetryOptions(options);
18711
+ let nextDelayMs = normalized.delayMs;
18712
+ for (let attempt = 1; attempt <= normalized.maxAttempts; attempt += 1) {
18713
+ try {
18714
+ return await operation();
18715
+ } catch (error2) {
18716
+ const shouldRetry = attempt < normalized.maxAttempts && normalized.shouldRetry(error2, {
18717
+ attempt,
18718
+ maxAttempts: normalized.maxAttempts
18719
+ });
18720
+ if (!shouldRetry) {
18721
+ throw error2;
18722
+ }
18723
+ await normalized.onRetry({
18724
+ attempt,
18725
+ maxAttempts: normalized.maxAttempts,
18726
+ delayMs: nextDelayMs,
18727
+ error: error2
18728
+ });
18729
+ await normalized.sleep(nextDelayMs);
18730
+ nextDelayMs = Math.min(
18731
+ normalized.maxDelayMs,
18732
+ Math.round(nextDelayMs * normalized.backoffMultiplier)
18733
+ );
18734
+ }
18735
+ }
18736
+ throw new Error("Retry exhausted without returning or throwing");
18737
+ }
18738
+
18739
+ // src/lib/postman/base-urls.ts
18740
+ var POSTMAN_ENDPOINT_PROFILES = {
18741
+ prod: {
18742
+ apiBaseUrl: "https://api.getpostman.com",
18743
+ bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
18744
+ iapubBaseUrl: "https://iapub.postman.co",
18745
+ observabilityBaseUrl: "https://api.observability.postman.com",
18746
+ observabilityEnv: "production"
18747
+ },
18748
+ beta: {
18749
+ apiBaseUrl: "https://api.getpostman-beta.com",
18750
+ bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
18751
+ iapubBaseUrl: "https://iapub.postman.co",
18752
+ observabilityBaseUrl: "https://api.observability.postman-beta.com",
18753
+ observabilityEnv: "beta"
18754
+ }
18755
+ };
18756
+ function parsePostmanRegion(value) {
18757
+ const normalized = String(value || "us").trim().toLowerCase();
18758
+ if (normalized === "us" || normalized === "eu") {
18759
+ return normalized;
18760
+ }
18761
+ throw new Error(`Unsupported postman-region "${value}". Supported values: us, eu`);
18762
+ }
18763
+ function parsePostmanStack(value) {
18764
+ const normalized = String(value || "prod").trim().toLowerCase();
18765
+ if (normalized === "prod" || normalized === "beta") {
18766
+ return normalized;
18767
+ }
18768
+ throw new Error(`Unsupported postman-stack "${value}". Supported values: prod, beta`);
18769
+ }
18770
+ function resolvePostmanEndpointProfile(stack, region = "us") {
18771
+ if (stack === "beta" && region !== "us") {
18772
+ throw new Error("postman-region=eu is only supported with postman-stack=prod");
18773
+ }
18774
+ const profile = POSTMAN_ENDPOINT_PROFILES[stack];
18775
+ if (region === "eu") {
18776
+ return {
18777
+ ...profile,
18778
+ apiBaseUrl: "https://api.eu.postman.com"
18779
+ };
18780
+ }
18781
+ return profile;
18782
+ }
18783
+
18784
+ // src/lib/postman/token-provider.ts
18785
+ var MintError = class extends Error {
18786
+ permanent;
18787
+ constructor(message, permanent) {
18788
+ super(message);
18789
+ this.name = "MintError";
18790
+ this.permanent = permanent;
18791
+ }
18792
+ };
18793
+ function extractAccessToken(payload) {
18794
+ if (!payload || typeof payload !== "object") return void 0;
18795
+ const record = payload;
18796
+ const direct = record.access_token;
18797
+ if (typeof direct === "string" && direct.trim()) return direct.trim();
18798
+ const session = record.session;
18799
+ if (session && typeof session === "object") {
18800
+ const token = session.token;
18801
+ if (typeof token === "string" && token.trim()) return token.trim();
18802
+ }
18803
+ return void 0;
18804
+ }
18805
+ var AccessTokenProvider = class {
18806
+ token;
18807
+ apiKey;
18808
+ apiBaseUrl;
18809
+ fetchImpl;
18810
+ maxAttempts;
18811
+ onToken;
18812
+ sleep;
18813
+ inflight;
18814
+ constructor(options) {
18815
+ this.token = String(options.accessToken || "").trim();
18816
+ this.apiKey = String(options.apiKey || "").trim();
18817
+ this.apiBaseUrl = String(
18818
+ options.apiBaseUrl || POSTMAN_ENDPOINT_PROFILES.prod.apiBaseUrl
18819
+ ).replace(/\/+$/, "");
18820
+ this.fetchImpl = options.fetchImpl ?? fetch;
18821
+ this.maxAttempts = Math.max(1, options.maxAttempts ?? 2);
18822
+ this.onToken = options.onToken;
18823
+ this.sleep = options.sleep;
18824
+ }
18825
+ current() {
18826
+ return this.token;
18827
+ }
18828
+ /** True when a PMAK is present, so an expired token can be re-minted. */
18829
+ canRefresh() {
18830
+ return Boolean(this.apiKey);
18831
+ }
18832
+ refresh() {
18833
+ this.inflight ??= this.mintWithRetry().finally(() => {
18834
+ this.inflight = void 0;
18835
+ });
18836
+ return this.inflight;
18837
+ }
18838
+ async mintWithRetry() {
18839
+ if (!this.apiKey) {
18840
+ throw new Error(
18841
+ "postman: the access token expired and cannot be refreshed because no postman-api-key is present. Service-account access tokens expire after about 1 to 1.5 hours. Re-mint a fresh token (postman-resolve-service-token-action) and re-run."
18842
+ );
18843
+ }
18844
+ const token = await retry(() => this.mintOnce(), {
18845
+ maxAttempts: this.maxAttempts,
18846
+ delayMs: 1e3,
18847
+ backoffMultiplier: 2,
18848
+ ...this.sleep ? { sleep: this.sleep } : {},
18849
+ shouldRetry: (error2) => !(error2 instanceof MintError && error2.permanent)
18850
+ });
18851
+ this.token = token;
18852
+ this.onToken?.(token);
18853
+ return token;
18854
+ }
18855
+ async mintOnce() {
18856
+ const response = await this.fetchImpl(`${this.apiBaseUrl}/service-account-tokens`, {
18857
+ method: "POST",
18858
+ headers: {
18859
+ "Content-Type": "application/json",
18860
+ "x-api-key": this.apiKey
18861
+ },
18862
+ body: JSON.stringify({ apiKey: this.apiKey })
18863
+ });
18864
+ const body = await response.text().catch(() => "");
18865
+ if (!response.ok) {
18866
+ const status = response.status;
18867
+ if (status === 401 || status === 403) {
18868
+ throw new MintError(
18869
+ `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.`,
18870
+ true
18871
+ );
18872
+ }
18873
+ if (status === 400 && body.toLowerCase().includes("service accounts not enabled")) {
18874
+ throw new MintError(
18875
+ "postman: re-mint failed because service accounts are not enabled for this team; enable them in Team Settings or use a team where they are.",
18876
+ true
18877
+ );
18878
+ }
18879
+ throw new MintError(`postman: re-mint failed (service-account-tokens HTTP ${status}).`, false);
18880
+ }
18881
+ let parsed;
18882
+ try {
18883
+ parsed = JSON.parse(body);
18884
+ } catch {
18885
+ parsed = void 0;
18886
+ }
18887
+ const token = extractAccessToken(parsed);
18888
+ if (!token) {
18889
+ throw new MintError("postman: re-mint succeeded but no access token was returned.", false);
18890
+ }
18891
+ return token;
18892
+ }
18893
+ };
18894
+ async function describeMintFailure(mintError, apiKey, apiBaseUrl, fetchImpl) {
18895
+ const raw = mintError instanceof Error ? mintError.message : String(mintError);
18896
+ const rejected = /HTTP 40[13]|PMAK rejected/.test(raw);
18897
+ if (!rejected) {
18898
+ return raw;
18899
+ }
18900
+ try {
18901
+ const me = await fetchImpl(`${apiBaseUrl}/me`, { headers: { "x-api-key": apiKey } });
18902
+ if (me.ok) {
18903
+ const body = await me.json().catch(() => void 0);
18904
+ const user = body?.user;
18905
+ const looksPersonal = Boolean(user && (user.username || user.email));
18906
+ if (looksPersonal) {
18907
+ 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.";
18908
+ }
18909
+ 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.";
18910
+ }
18911
+ 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.";
18912
+ } catch {
18913
+ return raw;
18914
+ }
18915
+ }
18916
+ async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetch) {
18917
+ if (inputs.postmanAccessToken || !inputs.postmanApiKey) {
18918
+ return;
18919
+ }
18920
+ const apiBaseUrl = String(
18921
+ inputs.postmanApiBase || POSTMAN_ENDPOINT_PROFILES.prod.apiBaseUrl
18922
+ ).replace(/\/+$/, "");
18923
+ const provider = new AccessTokenProvider({
18924
+ apiKey: inputs.postmanApiKey,
18925
+ apiBaseUrl,
18926
+ fetchImpl,
18927
+ onToken: (token) => setSecret2?.(token)
18928
+ });
18929
+ try {
18930
+ inputs.postmanAccessToken = await provider.refresh();
18931
+ log.info(
18932
+ "postman: no postman-access-token configured - minted a short-lived service-account access token from the postman-api-key."
18933
+ );
18934
+ } catch (error2) {
18935
+ const diagnosis = await describeMintFailure(error2, inputs.postmanApiKey, apiBaseUrl, fetchImpl);
18936
+ log.warning(
18937
+ "postman: could not mint an access token from the postman-api-key. " + diagnosis + " Continuing without an access token - access-token-only functionality will be unavailable unless postman-access-token is provided."
18938
+ );
18939
+ }
18940
+ }
18691
18941
 
18692
18942
  // node_modules/@actions/core/lib/core.js
18693
18943
  var core_exports = {};
@@ -20964,12 +21214,62 @@ function getIDToken(aud) {
20964
21214
 
20965
21215
  // src/lib/credential-identity.ts
20966
21216
  var sessionPath = "/api/sessions/current";
21217
+ var SESSION_MAX_ATTEMPTS = 3;
21218
+ var SESSION_RETRY_BASE_DELAY_MS = 500;
21219
+ var SESSION_RETRY_MAX_DELAY_MS = 8e3;
20967
21220
  var pmakMemo = /* @__PURE__ */ new Map();
20968
21221
  var sessionMemo = /* @__PURE__ */ new Map();
20969
21222
  var memoizedSessionIdentity;
21223
+ var memoizedSessionFailure;
21224
+ function defaultSessionSleep(ms) {
21225
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
21226
+ }
21227
+ function defaultRandom() {
21228
+ return Math.random();
21229
+ }
21230
+ function parseRetryAfterMs(value) {
21231
+ const trimmed = value?.trim();
21232
+ if (!trimmed) {
21233
+ return void 0;
21234
+ }
21235
+ if (/^\d+$/.test(trimmed)) {
21236
+ return Number(trimmed) * 1e3;
21237
+ }
21238
+ const dateMs = Date.parse(trimmed);
21239
+ if (!Number.isNaN(dateMs)) {
21240
+ return Math.max(0, dateMs - Date.now());
21241
+ }
21242
+ return void 0;
21243
+ }
21244
+ function parseRateLimitResetMs(value) {
21245
+ const trimmed = value?.trim();
21246
+ if (!trimmed || !/^\d+$/.test(trimmed)) {
21247
+ return void 0;
21248
+ }
21249
+ const seconds = Number(trimmed);
21250
+ const nowSeconds = Date.now() / 1e3;
21251
+ if (seconds > nowSeconds) {
21252
+ return Math.max(0, (seconds - nowSeconds) * 1e3);
21253
+ }
21254
+ return seconds * 1e3;
21255
+ }
21256
+ function computeSessionRetryDelayMs(response, attempt, random) {
21257
+ const headers = response?.headers;
21258
+ const signal = parseRetryAfterMs(headers?.get("retry-after") ?? null) ?? parseRateLimitResetMs(
21259
+ headers?.get("ratelimit-reset") ?? headers?.get("x-ratelimit-reset") ?? null
21260
+ );
21261
+ if (signal !== void 0) {
21262
+ return Math.min(Math.max(0, signal), SESSION_RETRY_MAX_DELAY_MS);
21263
+ }
21264
+ const ceiling = Math.min(SESSION_RETRY_MAX_DELAY_MS, SESSION_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
21265
+ return Math.round(random() * ceiling);
21266
+ }
20970
21267
  function getMemoizedSessionIdentity() {
20971
21268
  return memoizedSessionIdentity;
20972
21269
  }
21270
+ function getSessionResolutionFailure() {
21271
+ return memoizedSessionFailure;
21272
+ }
20973
21273
  function asRecord(value) {
20974
21274
  if (!value || typeof value !== "object" || Array.isArray(value)) {
20975
21275
  return void 0;
@@ -21038,46 +21338,90 @@ async function resolveSessionIdentity(opts) {
21038
21338
  const memoKey = `${baseUrl}::${accessToken}`;
21039
21339
  let pending = sessionMemo.get(memoKey);
21040
21340
  if (!pending) {
21041
- pending = probeSessionIdentity(baseUrl, accessToken, opts.fetchImpl ?? fetch);
21341
+ pending = probeSessionIdentity(
21342
+ baseUrl,
21343
+ accessToken,
21344
+ opts.fetchImpl ?? fetch,
21345
+ Math.max(1, opts.maxAttempts ?? SESSION_MAX_ATTEMPTS),
21346
+ opts.sleepImpl ?? defaultSessionSleep,
21347
+ opts.randomImpl ?? defaultRandom
21348
+ );
21042
21349
  sessionMemo.set(memoKey, pending);
21043
21350
  }
21044
21351
  return pending;
21045
21352
  }
21046
- async function probeSessionIdentity(baseUrl, accessToken, fetchImpl) {
21353
+ async function parseSessionResponse(response) {
21354
+ let payload;
21047
21355
  try {
21048
- const response = await fetchImpl(`${baseUrl}${sessionPath}`, {
21049
- method: "GET",
21050
- headers: { "x-access-token": accessToken }
21051
- });
21052
- if (!response.ok) {
21053
- return void 0;
21054
- }
21055
- const payload = asRecord(await response.json());
21056
- if (!payload) {
21057
- return void 0;
21058
- }
21059
- const root = asRecord(payload.session) ?? payload;
21060
- const identity = asRecord(root.identity);
21061
- const data = asRecord(root.data);
21062
- const user = asRecord(data?.user);
21063
- const roleEntries = Array.isArray(user?.roles) ? user.roles.map((entry) => coerceText(entry) ?? coerceId(entry)).filter((entry) => Boolean(entry)) : [];
21064
- const singleRole = coerceText(user?.role);
21065
- const roles = roleEntries.length > 0 ? roleEntries : singleRole ? [singleRole] : void 0;
21066
- const resolved = {
21067
- source: "iapub/sessions",
21068
- userId: coerceId(identity?.user) ?? coerceId(user?.id),
21069
- fullName: coerceText(user?.fullName) ?? coerceText(user?.name) ?? coerceText(user?.username),
21070
- teamId: coerceId(identity?.team),
21071
- teamName: coerceText(user?.teamName),
21072
- teamDomain: coerceText(identity?.domain),
21073
- ...roles ? { roles } : {},
21074
- consumerType: coerceText(root.consumerType) ?? coerceText(data?.consumerType) ?? coerceText(user?.consumerType)
21075
- };
21076
- memoizedSessionIdentity = resolved;
21077
- return resolved;
21356
+ payload = asRecord(await response.json());
21078
21357
  } catch {
21079
21358
  return void 0;
21080
21359
  }
21360
+ if (!payload) {
21361
+ return void 0;
21362
+ }
21363
+ const root = asRecord(payload.session) ?? payload;
21364
+ const identity = asRecord(root.identity);
21365
+ const data = asRecord(root.data);
21366
+ const user = asRecord(data?.user);
21367
+ const roleEntries = Array.isArray(user?.roles) ? user.roles.map((entry) => coerceText(entry) ?? coerceId(entry)).filter((entry) => Boolean(entry)) : [];
21368
+ const singleRole = coerceText(user?.role);
21369
+ const roles = roleEntries.length > 0 ? roleEntries : singleRole ? [singleRole] : void 0;
21370
+ return {
21371
+ source: "iapub/sessions",
21372
+ userId: coerceId(identity?.user) ?? coerceId(user?.id),
21373
+ fullName: coerceText(user?.fullName) ?? coerceText(user?.name) ?? coerceText(user?.username),
21374
+ teamId: coerceId(identity?.team),
21375
+ teamName: coerceText(user?.teamName),
21376
+ teamDomain: coerceText(identity?.domain),
21377
+ ...roles ? { roles } : {},
21378
+ consumerType: coerceText(root.consumerType) ?? coerceText(data?.consumerType) ?? coerceText(user?.consumerType)
21379
+ };
21380
+ }
21381
+ async function probeSessionIdentity(baseUrl, accessToken, fetchImpl, maxAttempts, sleepImpl, random) {
21382
+ let failure = "unavailable";
21383
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
21384
+ let response;
21385
+ try {
21386
+ response = await fetchImpl(`${baseUrl}${sessionPath}`, {
21387
+ method: "GET",
21388
+ headers: { "x-access-token": accessToken }
21389
+ });
21390
+ } catch {
21391
+ failure = "unavailable";
21392
+ if (attempt < maxAttempts) {
21393
+ await sleepImpl(computeSessionRetryDelayMs(void 0, attempt, random));
21394
+ continue;
21395
+ }
21396
+ break;
21397
+ }
21398
+ if (response.ok) {
21399
+ const resolved = await parseSessionResponse(response);
21400
+ if (resolved) {
21401
+ memoizedSessionIdentity = resolved;
21402
+ memoizedSessionFailure = void 0;
21403
+ return resolved;
21404
+ }
21405
+ failure = "unavailable";
21406
+ break;
21407
+ }
21408
+ if (response.status === 401 || response.status === 403) {
21409
+ failure = "auth";
21410
+ break;
21411
+ }
21412
+ if (response.status === 429 || response.status >= 500) {
21413
+ failure = "unavailable";
21414
+ if (attempt < maxAttempts) {
21415
+ await sleepImpl(computeSessionRetryDelayMs(response, attempt, random));
21416
+ continue;
21417
+ }
21418
+ break;
21419
+ }
21420
+ failure = "unavailable";
21421
+ break;
21422
+ }
21423
+ memoizedSessionFailure = failure;
21424
+ return void 0;
21081
21425
  }
21082
21426
  function describeTeam(id) {
21083
21427
  const label = id?.teamName ?? id?.teamDomain;
@@ -21170,7 +21514,9 @@ async function runCredentialPreflight(args) {
21170
21514
  session = await resolveSessionIdentity({
21171
21515
  iapubBaseUrl: args.iapubBaseUrl,
21172
21516
  accessToken,
21173
- fetchImpl: args.fetchImpl
21517
+ fetchImpl: args.fetchImpl,
21518
+ ...args.sleepImpl ? { sleepImpl: args.sleepImpl } : {},
21519
+ ...args.randomImpl ? { randomImpl: args.randomImpl } : {}
21174
21520
  });
21175
21521
  } catch (error2) {
21176
21522
  args.log.warning(
@@ -21190,11 +21536,20 @@ async function runCredentialPreflight(args) {
21190
21536
  );
21191
21537
  }
21192
21538
  } else {
21539
+ const failure = getSessionResolutionFailure();
21540
+ const detail = failure === "auth" ? "the access token was rejected by iapub (401/403), so it is invalid or expired. Re-mint it with postman-resolve-service-token-action (or POST https://api.getpostman.com/service-account-tokens) and re-run." : "iapub was unreachable after retries (network or 5xx). This is usually transient; re-run the job.";
21541
+ const base = "postman: credential preflight could not resolve the access-token session identity from iapub: " + detail;
21542
+ if (args.mode === "enforce") {
21543
+ throw new Error(
21544
+ mask(
21545
+ `${base} (credential-preflight: enforce requires a resolvable session identity; use credential-preflight: warn to continue with reactive error guidance only.)`
21546
+ )
21547
+ );
21548
+ }
21193
21549
  args.log.warning(
21194
- mask(
21195
- "postman: credential preflight could not resolve the access-token session identity from iapub; continuing with reactive error guidance only"
21196
- )
21550
+ mask(`${base} Continuing with reactive error guidance only (credential-preflight: warn).`)
21197
21551
  );
21552
+ return;
21198
21553
  }
21199
21554
  const result = crossCheckIdentities({
21200
21555
  pmak,
@@ -21404,98 +21759,6 @@ var HttpError = class _HttpError extends Error {
21404
21759
  }
21405
21760
  };
21406
21761
 
21407
- // src/lib/retry.ts
21408
- function sleep(delayMs) {
21409
- return new Promise((resolve2) => {
21410
- setTimeout(resolve2, delayMs);
21411
- });
21412
- }
21413
- function normalizeRetryOptions(options) {
21414
- return {
21415
- maxAttempts: Math.max(1, options.maxAttempts ?? 3),
21416
- delayMs: Math.max(0, options.delayMs ?? 2e3),
21417
- backoffMultiplier: Math.max(1, options.backoffMultiplier ?? 1),
21418
- maxDelayMs: options.maxDelayMs === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, options.maxDelayMs),
21419
- onRetry: options.onRetry ?? (async () => void 0),
21420
- shouldRetry: options.shouldRetry ?? (() => true),
21421
- sleep: options.sleep ?? sleep
21422
- };
21423
- }
21424
- async function retry(operation, options = {}) {
21425
- const normalized = normalizeRetryOptions(options);
21426
- let nextDelayMs = normalized.delayMs;
21427
- for (let attempt = 1; attempt <= normalized.maxAttempts; attempt += 1) {
21428
- try {
21429
- return await operation();
21430
- } catch (error2) {
21431
- const shouldRetry = attempt < normalized.maxAttempts && normalized.shouldRetry(error2, {
21432
- attempt,
21433
- maxAttempts: normalized.maxAttempts
21434
- });
21435
- if (!shouldRetry) {
21436
- throw error2;
21437
- }
21438
- await normalized.onRetry({
21439
- attempt,
21440
- maxAttempts: normalized.maxAttempts,
21441
- delayMs: nextDelayMs,
21442
- error: error2
21443
- });
21444
- await normalized.sleep(nextDelayMs);
21445
- nextDelayMs = Math.min(
21446
- normalized.maxDelayMs,
21447
- Math.round(nextDelayMs * normalized.backoffMultiplier)
21448
- );
21449
- }
21450
- }
21451
- throw new Error("Retry exhausted without returning or throwing");
21452
- }
21453
-
21454
- // src/lib/postman/base-urls.ts
21455
- var POSTMAN_ENDPOINT_PROFILES = {
21456
- prod: {
21457
- apiBaseUrl: "https://api.getpostman.com",
21458
- bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
21459
- iapubBaseUrl: "https://iapub.postman.co",
21460
- observabilityBaseUrl: "https://api.observability.postman.com",
21461
- observabilityEnv: "production"
21462
- },
21463
- beta: {
21464
- apiBaseUrl: "https://api.getpostman-beta.com",
21465
- bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
21466
- iapubBaseUrl: "https://iapub.postman.co",
21467
- observabilityBaseUrl: "https://api.observability.postman-beta.com",
21468
- observabilityEnv: "beta"
21469
- }
21470
- };
21471
- function parsePostmanRegion(value) {
21472
- const normalized = String(value || "us").trim().toLowerCase();
21473
- if (normalized === "us" || normalized === "eu") {
21474
- return normalized;
21475
- }
21476
- throw new Error(`Unsupported postman-region "${value}". Supported values: us, eu`);
21477
- }
21478
- function parsePostmanStack(value) {
21479
- const normalized = String(value || "prod").trim().toLowerCase();
21480
- if (normalized === "prod" || normalized === "beta") {
21481
- return normalized;
21482
- }
21483
- throw new Error(`Unsupported postman-stack "${value}". Supported values: prod, beta`);
21484
- }
21485
- function resolvePostmanEndpointProfile(stack, region = "us") {
21486
- if (stack === "beta" && region !== "us") {
21487
- throw new Error("postman-region=eu is only supported with postman-stack=prod");
21488
- }
21489
- const profile = POSTMAN_ENDPOINT_PROFILES[stack];
21490
- if (region === "eu") {
21491
- return {
21492
- ...profile,
21493
- apiBaseUrl: "https://api.eu.postman.com"
21494
- };
21495
- }
21496
- return profile;
21497
- }
21498
-
21499
21762
  // src/lib/bifrost-client.ts
21500
21763
  var DEFAULT_BIFROST_BASE_URL = POSTMAN_ENDPOINT_PROFILES.prod.bifrostBaseUrl;
21501
21764
  var BIFROST_PROXY_PATH = "/ws/proxy";
@@ -21503,8 +21766,11 @@ var DEFAULT_OBSERVABILITY_BASE_URL = POSTMAN_ENDPOINT_PROFILES.prod.observabilit
21503
21766
  var DEFAULT_OBSERVABILITY_ENV = POSTMAN_ENDPOINT_PROFILES.prod.observabilityEnv;
21504
21767
  var MAX_DISCOVERED_SERVICE_PAGES = 100;
21505
21768
  var MAX_PROVIDER_SERVICE_PAGES = 100;
21769
+ function isExpiredAuthError(status, body) {
21770
+ return status === 401 || body.includes("UNAUTHENTICATED") || body.includes("authenticationError");
21771
+ }
21506
21772
  var BifrostCatalogClient = class {
21507
- accessToken;
21773
+ tokenProvider;
21508
21774
  teamId;
21509
21775
  apiKey;
21510
21776
  fetchFn;
@@ -21513,11 +21779,14 @@ var BifrostCatalogClient = class {
21513
21779
  observabilityBaseUrl;
21514
21780
  observabilityEnv;
21515
21781
  constructor(options) {
21516
- this.accessToken = options.accessToken;
21782
+ this.tokenProvider = options.tokenProvider ?? new AccessTokenProvider({
21783
+ accessToken: options.accessToken,
21784
+ apiKey: options.apiKey
21785
+ });
21517
21786
  this.teamId = options.teamId;
21518
21787
  this.apiKey = options.apiKey;
21519
21788
  this.fetchFn = options.fetchFn ?? globalThis.fetch;
21520
- this.secretValues = [options.accessToken, options.apiKey].filter(Boolean);
21789
+ this.secretValues = [this.tokenProvider.current(), options.apiKey].filter(Boolean);
21521
21790
  const base = (options.bifrostBaseUrl || DEFAULT_BIFROST_BASE_URL).replace(/\/+$/, "");
21522
21791
  this.bifrostProxyUrl = `${base}${BIFROST_PROXY_PATH}`;
21523
21792
  this.observabilityBaseUrl = (options.observabilityBaseUrl || DEFAULT_OBSERVABILITY_BASE_URL).replace(/\/+$/, "");
@@ -21529,6 +21798,11 @@ var BifrostCatalogClient = class {
21529
21798
  this.secretValues.push(apiKey);
21530
21799
  }
21531
21800
  }
21801
+ registerAccessToken(token) {
21802
+ if (token && !this.secretValues.includes(token)) {
21803
+ this.secretValues.push(token);
21804
+ }
21805
+ }
21532
21806
  /**
21533
21807
  * Build Bifrost proxy headers.
21534
21808
  * x-entity-team-id is ONLY included when teamId is present (org-mode tokens).
@@ -21536,7 +21810,7 @@ var BifrostCatalogClient = class {
21536
21810
  */
21537
21811
  headers() {
21538
21812
  const h = {
21539
- "x-access-token": this.accessToken,
21813
+ "x-access-token": this.tokenProvider.current(),
21540
21814
  "Content-Type": "application/json"
21541
21815
  };
21542
21816
  if (this.teamId) {
@@ -21552,7 +21826,7 @@ var BifrostCatalogClient = class {
21552
21826
  const session = getMemoizedSessionIdentity();
21553
21827
  return {
21554
21828
  operation,
21555
- hasAccessToken: Boolean(this.accessToken),
21829
+ hasAccessToken: Boolean(this.tokenProvider.current()),
21556
21830
  sessionTeamId: session?.teamId,
21557
21831
  sessionRoles: session?.roles,
21558
21832
  sessionConsumerType: session?.consumerType,
@@ -21561,7 +21835,7 @@ var BifrostCatalogClient = class {
21561
21835
  };
21562
21836
  }
21563
21837
  async proxyRequest(method, path7, body = {}, operation = "api-catalog request") {
21564
- const response = await this.fetchFn(this.bifrostProxyUrl, {
21838
+ const send2 = async () => this.fetchFn(this.bifrostProxyUrl, {
21565
21839
  method: "POST",
21566
21840
  headers: this.headers(),
21567
21841
  body: JSON.stringify({
@@ -21571,6 +21845,39 @@ var BifrostCatalogClient = class {
21571
21845
  body
21572
21846
  })
21573
21847
  });
21848
+ let response = await send2();
21849
+ if (!response.ok) {
21850
+ const bodyText = await response.text().catch(() => "");
21851
+ if (isExpiredAuthError(response.status, bodyText) && this.tokenProvider.canRefresh()) {
21852
+ try {
21853
+ const refreshed = await this.tokenProvider.refresh();
21854
+ this.registerAccessToken(refreshed);
21855
+ response = await send2();
21856
+ } catch {
21857
+ const httpErr = await HttpError.fromResponse(
21858
+ new Response(bodyText, { status: response.status, headers: response.headers }),
21859
+ {
21860
+ method: "POST",
21861
+ url: `bifrost:api-catalog:${method} ${path7}`,
21862
+ secretValues: this.secretValues
21863
+ }
21864
+ );
21865
+ const advised = adviseFromHttpError(httpErr, this.adviceContext(operation));
21866
+ throw advised ?? httpErr;
21867
+ }
21868
+ } else {
21869
+ const httpErr = await HttpError.fromResponse(
21870
+ new Response(bodyText, { status: response.status, headers: response.headers }),
21871
+ {
21872
+ method: "POST",
21873
+ url: `bifrost:api-catalog:${method} ${path7}`,
21874
+ secretValues: this.secretValues
21875
+ }
21876
+ );
21877
+ const advised = adviseFromHttpError(httpErr, this.adviceContext(operation));
21878
+ throw advised ?? httpErr;
21879
+ }
21880
+ }
21574
21881
  if (!response.ok) {
21575
21882
  const httpErr = await HttpError.fromResponse(response, {
21576
21883
  method: "POST",
@@ -21593,7 +21900,7 @@ var BifrostCatalogClient = class {
21593
21900
  return data;
21594
21901
  }
21595
21902
  async akitaProxyRequest(method, path7, body = {}, operation = "Insights request") {
21596
- const response = await this.fetchFn(this.bifrostProxyUrl, {
21903
+ const send2 = async () => this.fetchFn(this.bifrostProxyUrl, {
21597
21904
  method: "POST",
21598
21905
  headers: this.headers(),
21599
21906
  body: JSON.stringify({
@@ -21603,8 +21910,30 @@ var BifrostCatalogClient = class {
21603
21910
  body
21604
21911
  })
21605
21912
  });
21913
+ let response = await send2();
21606
21914
  if (!response.ok) {
21607
21915
  const text = await response.text().catch(() => "");
21916
+ if (isExpiredAuthError(response.status, text) && this.tokenProvider.canRefresh()) {
21917
+ try {
21918
+ const refreshed = await this.tokenProvider.refresh();
21919
+ this.registerAccessToken(refreshed);
21920
+ response = await send2();
21921
+ if (response.ok) {
21922
+ const data2 = await response.json();
21923
+ return { ok: true, status: response.status, data: data2, errorText: "" };
21924
+ }
21925
+ const retryText = await response.text().catch(() => "");
21926
+ const advised2 = adviseFromBifrostBody(response.status, retryText, this.adviceContext(operation));
21927
+ const errorText2 = advised2 ? retryText ? `${retryText}
21928
+ ${advised2.message}` : advised2.message : retryText;
21929
+ return { ok: false, status: response.status, data: null, errorText: errorText2 };
21930
+ } catch {
21931
+ const advised2 = adviseFromBifrostBody(response.status, text, this.adviceContext(operation));
21932
+ const errorText2 = advised2 ? text ? `${text}
21933
+ ${advised2.message}` : advised2.message : text;
21934
+ return { ok: false, status: response.status, data: null, errorText: errorText2 };
21935
+ }
21936
+ }
21608
21937
  const advised = adviseFromBifrostBody(response.status, text, this.adviceContext(operation));
21609
21938
  const errorText = advised ? text ? `${text}
21610
21939
  ${advised.message}` : advised.message : text;
@@ -21703,12 +22032,19 @@ ${advised.message}` : advised.message : text;
21703
22032
  }
21704
22033
  page++;
21705
22034
  }
21706
- const fullName = clusterName ? `${clusterName}/${projectName}` : projectName;
21707
- const exactMatch = allServices.find((s) => s.name === fullName);
21708
- if (exactMatch) return exactMatch.id;
21709
- if (clusterName) return null;
21710
- const suffixMatch = allServices.find((s) => s.name.endsWith(`/${projectName}`));
21711
- return suffixMatch?.id || null;
22035
+ if (clusterName) {
22036
+ const fullName = `${clusterName}/${projectName}`;
22037
+ const exactMatch = allServices.find((s) => s.name === fullName);
22038
+ return exactMatch?.id || null;
22039
+ }
22040
+ const finalSegmentMatch = allServices.find(
22041
+ (s) => getFinalServiceSegment(s.name) === projectName
22042
+ );
22043
+ if (finalSegmentMatch) return finalSegmentMatch.id;
22044
+ const bracketedMatch = allServices.find(
22045
+ (s) => getFinalServiceSegment(s.name).includes(`[${projectName}]`)
22046
+ );
22047
+ return bracketedMatch?.id || null;
21712
22048
  }
21713
22049
  async acknowledgeOnboarding(providerServiceId, workspaceId, systemEnvironmentId) {
21714
22050
  const result = await this.akitaProxyRequest(
@@ -21738,6 +22074,14 @@ ${advised.message}` : advised.message : text;
21738
22074
  throw new Error(`Workspace acknowledge failed: ${result.status} ${result.errorText}`);
21739
22075
  }
21740
22076
  }
22077
+ // PMAK-only by proven exception. A live probe against the observability
22078
+ // application-binding endpoint (POST /v2/agent/api-catalog/workspaces/:id/
22079
+ // applications) showed x-access-token is rejected identically to the x-api-key
22080
+ // control: both return 401 {"message":"Postman User not found"} for a
22081
+ // service-account credential, because the observability service has no
22082
+ // "Postman User" for a service account. The access token offers no improvement
22083
+ // over the API key here, so this route is not migrated to access-token-primary
22084
+ // (the suite-wide migration explicitly leaves probe-failed routes on PMAK).
21741
22085
  async createApplication(workspaceId, systemEnv) {
21742
22086
  const response = await this.fetchFn(
21743
22087
  `${this.observabilityBaseUrl}/v2/agent/api-catalog/workspaces/${workspaceId}/applications`,
@@ -21805,7 +22149,17 @@ function findDiscoveredService(services, projectName, clusterName) {
21805
22149
  const fullName = `${clusterName}/${projectName}`;
21806
22150
  return services.find((s) => s.name === fullName);
21807
22151
  }
21808
- return services.find((s) => s.name.endsWith(`/${projectName}`));
22152
+ const finalSegmentMatch = services.find(
22153
+ (service) => getFinalServiceSegment(service.name) === projectName
22154
+ );
22155
+ if (finalSegmentMatch) return finalSegmentMatch;
22156
+ return services.find(
22157
+ (service) => getFinalServiceSegment(service.name).includes(`[${projectName}]`)
22158
+ );
22159
+ }
22160
+ function getFinalServiceSegment(serviceName) {
22161
+ const lastSlash = serviceName.lastIndexOf("/");
22162
+ return lastSlash === -1 ? serviceName : serviceName.slice(lastSlash + 1);
21809
22163
  }
21810
22164
 
21811
22165
  // node_modules/@postman-cse/automation-telemetry-core/dist/ci-context.js
@@ -22062,7 +22416,7 @@ function resolveActionVersion(explicit) {
22062
22416
  if (explicit) {
22063
22417
  return explicit;
22064
22418
  }
22065
- return "1.0.4" ? "1.0.4" : "unknown";
22419
+ return typeof __ACTION_VERSION__ !== "undefined" && __ACTION_VERSION__ ? __ACTION_VERSION__ : "unknown";
22066
22420
  }
22067
22421
  function telemetryDisabled(env) {
22068
22422
  const flag = String(env.POSTMAN_ACTIONS_TELEMETRY ?? "").trim().toLowerCase();
@@ -22184,6 +22538,18 @@ function createTelemetryContext(options) {
22184
22538
  };
22185
22539
  }
22186
22540
 
22541
+ // src/action-version.ts
22542
+ var import_node_fs = require("node:fs");
22543
+ var import_node_path = require("node:path");
22544
+ function resolveActionVersion2() {
22545
+ try {
22546
+ const raw = (0, import_node_fs.readFileSync)((0, import_node_path.join)(__dirname, "..", "package.json"), "utf8");
22547
+ return JSON.parse(raw).version ?? "unknown";
22548
+ } catch {
22549
+ return "unknown";
22550
+ }
22551
+ }
22552
+
22187
22553
  // src/index.ts
22188
22554
  var POLL_TIMEOUT_MIN = 10;
22189
22555
  var POLL_TIMEOUT_MAX = 600;
@@ -22249,8 +22615,12 @@ function resolveInputs(env = process.env) {
22249
22615
  const projectName = get("project-name");
22250
22616
  if (!projectName) throw new Error("project-name is required");
22251
22617
  const postmanAccessToken = get("postman-access-token");
22252
- if (!postmanAccessToken) throw new Error("postman-access-token is required");
22253
22618
  const postmanApiKey = get("postman-api-key");
22619
+ if (!postmanAccessToken && !postmanApiKey) {
22620
+ throw new Error(
22621
+ "postman-access-token is required (or provide a service-account postman-api-key so the action can mint one)."
22622
+ );
22623
+ }
22254
22624
  const postmanTeamId = get("postman-team-id") || env.POSTMAN_TEAM_ID?.trim() || "";
22255
22625
  const workspaceId = get("workspace-id") || env.POSTMAN_WORKSPACE_ID?.trim() || "";
22256
22626
  if (!workspaceId) {
@@ -22441,19 +22811,39 @@ async function resolveApiKeyAndTeamId(inputs, client, reporter = core_exports) {
22441
22811
  }
22442
22812
  return { apiKey, teamId: resolvedTeamId, pmakIdentity };
22443
22813
  }
22444
- async function runCredentialPreflightForInputs(inputs, pmak, reporter, fetchImpl) {
22814
+ async function runCredentialPreflightForInputs(inputs, pmak, reporter, fetchImpl, liveAccessToken) {
22815
+ const accessToken = liveAccessToken ?? inputs.postmanAccessToken;
22445
22816
  await runCredentialPreflight({
22446
22817
  apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22447
22818
  iapubBaseUrl: inputs.postmanIapubBase || DEFAULT_POSTMAN_IAPUB_BASE,
22448
22819
  pmak,
22449
- postmanAccessToken: inputs.postmanAccessToken,
22820
+ postmanAccessToken: accessToken,
22450
22821
  explicitTeamId: inputs.postmanTeamId || void 0,
22451
22822
  mode: inputs.credentialPreflight,
22452
- mask: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken]),
22823
+ mask: createSecretMasker([inputs.postmanApiKey, accessToken]),
22453
22824
  log: reporter,
22454
22825
  fetchImpl
22455
22826
  });
22456
22827
  }
22828
+ function createInsightsTokenProvider(inputs, reporter, apiKey = inputs.postmanApiKey) {
22829
+ return new AccessTokenProvider({
22830
+ accessToken: inputs.postmanAccessToken,
22831
+ apiKey,
22832
+ apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22833
+ onToken: (token) => reporter.setSecret(token)
22834
+ });
22835
+ }
22836
+ function createInsightsBifrostClient(inputs, tokenProvider, teamId, apiKey) {
22837
+ return new BifrostCatalogClient({
22838
+ tokenProvider,
22839
+ accessToken: tokenProvider.current(),
22840
+ teamId,
22841
+ apiKey,
22842
+ bifrostBaseUrl: inputs.postmanBifrostBase,
22843
+ observabilityBaseUrl: inputs.postmanObservabilityBase,
22844
+ observabilityEnv: inputs.postmanObservabilityEnv
22845
+ });
22846
+ }
22457
22847
 
22458
22848
  // src/cli.ts
22459
22849
  var ConsoleReporter = class {
@@ -22534,13 +22924,13 @@ async function writeOptionalFile(filePath, content) {
22534
22924
  if (!filePath) {
22535
22925
  return;
22536
22926
  }
22537
- const workspaceRoot = import_node_path.default.resolve(process.cwd());
22538
- const resolved = import_node_path.default.resolve(workspaceRoot, filePath);
22539
- const relative2 = import_node_path.default.relative(workspaceRoot, resolved);
22540
- if (relative2.startsWith("..") || import_node_path.default.isAbsolute(relative2)) {
22927
+ const workspaceRoot = import_node_path2.default.resolve(process.cwd());
22928
+ const resolved = import_node_path2.default.resolve(workspaceRoot, filePath);
22929
+ const relative2 = import_node_path2.default.relative(workspaceRoot, resolved);
22930
+ if (relative2.startsWith("..") || import_node_path2.default.isAbsolute(relative2)) {
22541
22931
  throw new Error(`Output path must stay within workspace: ${filePath}`);
22542
22932
  }
22543
- await (0, import_promises.mkdir)(import_node_path.default.dirname(resolved), { recursive: true });
22933
+ await (0, import_promises.mkdir)(import_node_path2.default.dirname(resolved), { recursive: true });
22544
22934
  await (0, import_promises.writeFile)(resolved, content, "utf8");
22545
22935
  }
22546
22936
  function toOutputs(result) {
@@ -22558,42 +22948,53 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
22558
22948
  const config = parseCliArgs(argv, env);
22559
22949
  const inputs = resolveInputs(config.inputEnv);
22560
22950
  const reporter = new ConsoleReporter();
22561
- reporter.setSecret(inputs.postmanAccessToken);
22951
+ const mintHolder = {
22952
+ postmanAccessToken: inputs.postmanAccessToken,
22953
+ postmanApiKey: inputs.postmanApiKey,
22954
+ postmanApiBase: inputs.postmanApiBase
22955
+ };
22956
+ await mintAccessTokenIfNeeded(mintHolder, reporter, (secret) => reporter.setSecret(secret));
22957
+ inputs.postmanAccessToken = mintHolder.postmanAccessToken;
22958
+ if (inputs.postmanAccessToken) reporter.setSecret(inputs.postmanAccessToken);
22562
22959
  if (inputs.postmanApiKey) {
22563
22960
  reporter.setSecret(inputs.postmanApiKey);
22564
22961
  }
22565
22962
  if (inputs.githubToken) {
22566
22963
  reporter.setSecret(inputs.githubToken);
22567
22964
  }
22568
- const preliminaryClient = new BifrostCatalogClient({
22569
- accessToken: inputs.postmanAccessToken,
22570
- teamId: inputs.postmanTeamId,
22571
- apiKey: inputs.postmanApiKey,
22572
- bifrostBaseUrl: inputs.postmanBifrostBase,
22573
- observabilityBaseUrl: inputs.postmanObservabilityBase,
22574
- observabilityEnv: inputs.postmanObservabilityEnv
22575
- });
22965
+ const tokenProvider = createInsightsTokenProvider(inputs, reporter);
22966
+ const preliminaryClient = createInsightsBifrostClient(
22967
+ inputs,
22968
+ tokenProvider,
22969
+ inputs.postmanTeamId,
22970
+ inputs.postmanApiKey
22971
+ );
22576
22972
  const { apiKey, teamId, pmakIdentity } = await resolveApiKeyAndTeamId(
22577
22973
  inputs,
22578
22974
  preliminaryClient,
22579
22975
  reporter
22580
22976
  );
22581
- const telemetry = createTelemetryContext({ action: "postman-insights-onboarding-action", logger: reporter });
22977
+ const activeTokenProvider = apiKey !== inputs.postmanApiKey ? new AccessTokenProvider({
22978
+ accessToken: tokenProvider.current(),
22979
+ apiKey,
22980
+ apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22981
+ onToken: (token) => reporter.setSecret(token)
22982
+ }) : tokenProvider;
22983
+ const telemetry = createTelemetryContext({ action: "postman-insights-onboarding-action", actionVersion: resolveActionVersion2(), logger: reporter });
22582
22984
  telemetry.setTeamId(inputs.postmanTeamId || pmakIdentity?.teamId);
22583
22985
  if (apiKey) {
22584
22986
  reporter.setSecret(apiKey);
22585
22987
  }
22586
22988
  let result;
22587
22989
  try {
22588
- await runCredentialPreflightForInputs(inputs, pmakIdentity, reporter);
22589
- const client = new BifrostCatalogClient({
22590
- accessToken: inputs.postmanAccessToken,
22591
- teamId,
22592
- apiKey,
22593
- bifrostBaseUrl: inputs.postmanBifrostBase,
22594
- observabilityBaseUrl: inputs.postmanObservabilityBase,
22595
- observabilityEnv: inputs.postmanObservabilityEnv
22596
- });
22990
+ await runCredentialPreflightForInputs(
22991
+ inputs,
22992
+ pmakIdentity,
22993
+ reporter,
22994
+ void 0,
22995
+ activeTokenProvider.current()
22996
+ );
22997
+ const client = createInsightsBifrostClient(inputs, activeTokenProvider, teamId, apiKey);
22597
22998
  result = await (runtime.executeOnboarding ?? runOnboarding)(
22598
22999
  inputs,
22599
23000
  client,
@@ -22624,9 +23025,9 @@ function isEntrypoint(currentPath, entrypointPath) {
22624
23025
  return false;
22625
23026
  }
22626
23027
  try {
22627
- return (0, import_node_fs.realpathSync)(currentPath) === (0, import_node_fs.realpathSync)(entrypointPath);
23028
+ return (0, import_node_fs2.realpathSync)(currentPath) === (0, import_node_fs2.realpathSync)(entrypointPath);
22628
23029
  } catch {
22629
- return import_node_path.default.resolve(currentPath) === import_node_path.default.resolve(entrypointPath);
23030
+ return import_node_path2.default.resolve(currentPath) === import_node_path2.default.resolve(entrypointPath);
22630
23031
  }
22631
23032
  }
22632
23033
  if (isEntrypoint(currentModulePath, entrypoint)) {