@postman-cse/onboarding-insights 1.0.3 → 2.0.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/index.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
  );
@@ -18682,6 +18682,8 @@ __export(index_exports, {
18682
18682
  DEFAULT_POSTMAN_BIFROST_BASE: () => DEFAULT_POSTMAN_BIFROST_BASE,
18683
18683
  DEFAULT_POSTMAN_IAPUB_BASE: () => DEFAULT_POSTMAN_IAPUB_BASE,
18684
18684
  DEFAULT_POSTMAN_OBSERVABILITY_BASE: () => DEFAULT_POSTMAN_OBSERVABILITY_BASE,
18685
+ createInsightsBifrostClient: () => createInsightsBifrostClient,
18686
+ createInsightsTokenProvider: () => createInsightsTokenProvider,
18685
18687
  createPlannedOutputs: () => createPlannedOutputs,
18686
18688
  getTeams: () => getTeams,
18687
18689
  parsePreflightMode: () => parsePreflightMode,
@@ -21501,6 +21503,117 @@ function resolvePostmanEndpointProfile(stack, region = "us") {
21501
21503
  return profile;
21502
21504
  }
21503
21505
 
21506
+ // src/lib/postman/token-provider.ts
21507
+ var MintError = class extends Error {
21508
+ permanent;
21509
+ constructor(message, permanent) {
21510
+ super(message);
21511
+ this.name = "MintError";
21512
+ this.permanent = permanent;
21513
+ }
21514
+ };
21515
+ function extractAccessToken(payload) {
21516
+ if (!payload || typeof payload !== "object") return void 0;
21517
+ const record = payload;
21518
+ const direct = record.access_token;
21519
+ if (typeof direct === "string" && direct.trim()) return direct.trim();
21520
+ const session = record.session;
21521
+ if (session && typeof session === "object") {
21522
+ const token = session.token;
21523
+ if (typeof token === "string" && token.trim()) return token.trim();
21524
+ }
21525
+ return void 0;
21526
+ }
21527
+ var AccessTokenProvider = class {
21528
+ token;
21529
+ apiKey;
21530
+ apiBaseUrl;
21531
+ fetchImpl;
21532
+ maxAttempts;
21533
+ onToken;
21534
+ sleep;
21535
+ inflight;
21536
+ constructor(options) {
21537
+ this.token = String(options.accessToken || "").trim();
21538
+ this.apiKey = String(options.apiKey || "").trim();
21539
+ this.apiBaseUrl = String(
21540
+ options.apiBaseUrl || POSTMAN_ENDPOINT_PROFILES.prod.apiBaseUrl
21541
+ ).replace(/\/+$/, "");
21542
+ this.fetchImpl = options.fetchImpl ?? fetch;
21543
+ this.maxAttempts = Math.max(1, options.maxAttempts ?? 2);
21544
+ this.onToken = options.onToken;
21545
+ this.sleep = options.sleep;
21546
+ }
21547
+ current() {
21548
+ return this.token;
21549
+ }
21550
+ /** True when a PMAK is present, so an expired token can be re-minted. */
21551
+ canRefresh() {
21552
+ return Boolean(this.apiKey);
21553
+ }
21554
+ refresh() {
21555
+ this.inflight ??= this.mintWithRetry().finally(() => {
21556
+ this.inflight = void 0;
21557
+ });
21558
+ return this.inflight;
21559
+ }
21560
+ async mintWithRetry() {
21561
+ if (!this.apiKey) {
21562
+ throw new Error(
21563
+ "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."
21564
+ );
21565
+ }
21566
+ const token = await retry(() => this.mintOnce(), {
21567
+ maxAttempts: this.maxAttempts,
21568
+ delayMs: 1e3,
21569
+ backoffMultiplier: 2,
21570
+ ...this.sleep ? { sleep: this.sleep } : {},
21571
+ shouldRetry: (error2) => !(error2 instanceof MintError && error2.permanent)
21572
+ });
21573
+ this.token = token;
21574
+ this.onToken?.(token);
21575
+ return token;
21576
+ }
21577
+ async mintOnce() {
21578
+ const response = await this.fetchImpl(`${this.apiBaseUrl}/service-account-tokens`, {
21579
+ method: "POST",
21580
+ headers: {
21581
+ "Content-Type": "application/json",
21582
+ "x-api-key": this.apiKey
21583
+ },
21584
+ body: JSON.stringify({ apiKey: this.apiKey })
21585
+ });
21586
+ const body = await response.text().catch(() => "");
21587
+ if (!response.ok) {
21588
+ const status = response.status;
21589
+ if (status === 401 || status === 403) {
21590
+ throw new MintError(
21591
+ `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.`,
21592
+ true
21593
+ );
21594
+ }
21595
+ if (status === 400 && body.toLowerCase().includes("service accounts not enabled")) {
21596
+ throw new MintError(
21597
+ "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.",
21598
+ true
21599
+ );
21600
+ }
21601
+ throw new MintError(`postman: re-mint failed (service-account-tokens HTTP ${status}).`, false);
21602
+ }
21603
+ let parsed;
21604
+ try {
21605
+ parsed = JSON.parse(body);
21606
+ } catch {
21607
+ parsed = void 0;
21608
+ }
21609
+ const token = extractAccessToken(parsed);
21610
+ if (!token) {
21611
+ throw new MintError("postman: re-mint succeeded but no access token was returned.", false);
21612
+ }
21613
+ return token;
21614
+ }
21615
+ };
21616
+
21504
21617
  // src/lib/bifrost-client.ts
21505
21618
  var DEFAULT_BIFROST_BASE_URL = POSTMAN_ENDPOINT_PROFILES.prod.bifrostBaseUrl;
21506
21619
  var BIFROST_PROXY_PATH = "/ws/proxy";
@@ -21508,8 +21621,11 @@ var DEFAULT_OBSERVABILITY_BASE_URL = POSTMAN_ENDPOINT_PROFILES.prod.observabilit
21508
21621
  var DEFAULT_OBSERVABILITY_ENV = POSTMAN_ENDPOINT_PROFILES.prod.observabilityEnv;
21509
21622
  var MAX_DISCOVERED_SERVICE_PAGES = 100;
21510
21623
  var MAX_PROVIDER_SERVICE_PAGES = 100;
21624
+ function isExpiredAuthError(status, body) {
21625
+ return status === 401 || body.includes("UNAUTHENTICATED") || body.includes("authenticationError");
21626
+ }
21511
21627
  var BifrostCatalogClient = class {
21512
- accessToken;
21628
+ tokenProvider;
21513
21629
  teamId;
21514
21630
  apiKey;
21515
21631
  fetchFn;
@@ -21518,11 +21634,14 @@ var BifrostCatalogClient = class {
21518
21634
  observabilityBaseUrl;
21519
21635
  observabilityEnv;
21520
21636
  constructor(options) {
21521
- this.accessToken = options.accessToken;
21637
+ this.tokenProvider = options.tokenProvider ?? new AccessTokenProvider({
21638
+ accessToken: options.accessToken,
21639
+ apiKey: options.apiKey
21640
+ });
21522
21641
  this.teamId = options.teamId;
21523
21642
  this.apiKey = options.apiKey;
21524
21643
  this.fetchFn = options.fetchFn ?? globalThis.fetch;
21525
- this.secretValues = [options.accessToken, options.apiKey].filter(Boolean);
21644
+ this.secretValues = [this.tokenProvider.current(), options.apiKey].filter(Boolean);
21526
21645
  const base = (options.bifrostBaseUrl || DEFAULT_BIFROST_BASE_URL).replace(/\/+$/, "");
21527
21646
  this.bifrostProxyUrl = `${base}${BIFROST_PROXY_PATH}`;
21528
21647
  this.observabilityBaseUrl = (options.observabilityBaseUrl || DEFAULT_OBSERVABILITY_BASE_URL).replace(/\/+$/, "");
@@ -21534,6 +21653,11 @@ var BifrostCatalogClient = class {
21534
21653
  this.secretValues.push(apiKey);
21535
21654
  }
21536
21655
  }
21656
+ registerAccessToken(token) {
21657
+ if (token && !this.secretValues.includes(token)) {
21658
+ this.secretValues.push(token);
21659
+ }
21660
+ }
21537
21661
  /**
21538
21662
  * Build Bifrost proxy headers.
21539
21663
  * x-entity-team-id is ONLY included when teamId is present (org-mode tokens).
@@ -21541,7 +21665,7 @@ var BifrostCatalogClient = class {
21541
21665
  */
21542
21666
  headers() {
21543
21667
  const h = {
21544
- "x-access-token": this.accessToken,
21668
+ "x-access-token": this.tokenProvider.current(),
21545
21669
  "Content-Type": "application/json"
21546
21670
  };
21547
21671
  if (this.teamId) {
@@ -21557,7 +21681,7 @@ var BifrostCatalogClient = class {
21557
21681
  const session = getMemoizedSessionIdentity();
21558
21682
  return {
21559
21683
  operation,
21560
- hasAccessToken: Boolean(this.accessToken),
21684
+ hasAccessToken: Boolean(this.tokenProvider.current()),
21561
21685
  sessionTeamId: session?.teamId,
21562
21686
  sessionRoles: session?.roles,
21563
21687
  sessionConsumerType: session?.consumerType,
@@ -21566,7 +21690,7 @@ var BifrostCatalogClient = class {
21566
21690
  };
21567
21691
  }
21568
21692
  async proxyRequest(method, path6, body = {}, operation = "api-catalog request") {
21569
- const response = await this.fetchFn(this.bifrostProxyUrl, {
21693
+ const send2 = async () => this.fetchFn(this.bifrostProxyUrl, {
21570
21694
  method: "POST",
21571
21695
  headers: this.headers(),
21572
21696
  body: JSON.stringify({
@@ -21576,6 +21700,39 @@ var BifrostCatalogClient = class {
21576
21700
  body
21577
21701
  })
21578
21702
  });
21703
+ let response = await send2();
21704
+ if (!response.ok) {
21705
+ const bodyText = await response.text().catch(() => "");
21706
+ if (isExpiredAuthError(response.status, bodyText) && this.tokenProvider.canRefresh()) {
21707
+ try {
21708
+ const refreshed = await this.tokenProvider.refresh();
21709
+ this.registerAccessToken(refreshed);
21710
+ response = await send2();
21711
+ } catch {
21712
+ const httpErr = await HttpError.fromResponse(
21713
+ new Response(bodyText, { status: response.status, headers: response.headers }),
21714
+ {
21715
+ method: "POST",
21716
+ url: `bifrost:api-catalog:${method} ${path6}`,
21717
+ secretValues: this.secretValues
21718
+ }
21719
+ );
21720
+ const advised = adviseFromHttpError(httpErr, this.adviceContext(operation));
21721
+ throw advised ?? httpErr;
21722
+ }
21723
+ } else {
21724
+ const httpErr = await HttpError.fromResponse(
21725
+ new Response(bodyText, { status: response.status, headers: response.headers }),
21726
+ {
21727
+ method: "POST",
21728
+ url: `bifrost:api-catalog:${method} ${path6}`,
21729
+ secretValues: this.secretValues
21730
+ }
21731
+ );
21732
+ const advised = adviseFromHttpError(httpErr, this.adviceContext(operation));
21733
+ throw advised ?? httpErr;
21734
+ }
21735
+ }
21579
21736
  if (!response.ok) {
21580
21737
  const httpErr = await HttpError.fromResponse(response, {
21581
21738
  method: "POST",
@@ -21598,7 +21755,7 @@ var BifrostCatalogClient = class {
21598
21755
  return data;
21599
21756
  }
21600
21757
  async akitaProxyRequest(method, path6, body = {}, operation = "Insights request") {
21601
- const response = await this.fetchFn(this.bifrostProxyUrl, {
21758
+ const send2 = async () => this.fetchFn(this.bifrostProxyUrl, {
21602
21759
  method: "POST",
21603
21760
  headers: this.headers(),
21604
21761
  body: JSON.stringify({
@@ -21608,8 +21765,30 @@ var BifrostCatalogClient = class {
21608
21765
  body
21609
21766
  })
21610
21767
  });
21768
+ let response = await send2();
21611
21769
  if (!response.ok) {
21612
21770
  const text = await response.text().catch(() => "");
21771
+ if (isExpiredAuthError(response.status, text) && this.tokenProvider.canRefresh()) {
21772
+ try {
21773
+ const refreshed = await this.tokenProvider.refresh();
21774
+ this.registerAccessToken(refreshed);
21775
+ response = await send2();
21776
+ if (response.ok) {
21777
+ const data2 = await response.json();
21778
+ return { ok: true, status: response.status, data: data2, errorText: "" };
21779
+ }
21780
+ const retryText = await response.text().catch(() => "");
21781
+ const advised2 = adviseFromBifrostBody(response.status, retryText, this.adviceContext(operation));
21782
+ const errorText2 = advised2 ? retryText ? `${retryText}
21783
+ ${advised2.message}` : advised2.message : retryText;
21784
+ return { ok: false, status: response.status, data: null, errorText: errorText2 };
21785
+ } catch {
21786
+ const advised2 = adviseFromBifrostBody(response.status, text, this.adviceContext(operation));
21787
+ const errorText2 = advised2 ? text ? `${text}
21788
+ ${advised2.message}` : advised2.message : text;
21789
+ return { ok: false, status: response.status, data: null, errorText: errorText2 };
21790
+ }
21791
+ }
21613
21792
  const advised = adviseFromBifrostBody(response.status, text, this.adviceContext(operation));
21614
21793
  const errorText = advised ? text ? `${text}
21615
21794
  ${advised.message}` : advised.message : text;
@@ -21708,12 +21887,19 @@ ${advised.message}` : advised.message : text;
21708
21887
  }
21709
21888
  page++;
21710
21889
  }
21711
- const fullName = clusterName ? `${clusterName}/${projectName}` : projectName;
21712
- const exactMatch = allServices.find((s) => s.name === fullName);
21713
- if (exactMatch) return exactMatch.id;
21714
- if (clusterName) return null;
21715
- const suffixMatch = allServices.find((s) => s.name.endsWith(`/${projectName}`));
21716
- return suffixMatch?.id || null;
21890
+ if (clusterName) {
21891
+ const fullName = `${clusterName}/${projectName}`;
21892
+ const exactMatch = allServices.find((s) => s.name === fullName);
21893
+ return exactMatch?.id || null;
21894
+ }
21895
+ const finalSegmentMatch = allServices.find(
21896
+ (s) => getFinalServiceSegment(s.name) === projectName
21897
+ );
21898
+ if (finalSegmentMatch) return finalSegmentMatch.id;
21899
+ const bracketedMatch = allServices.find(
21900
+ (s) => getFinalServiceSegment(s.name).includes(`[${projectName}]`)
21901
+ );
21902
+ return bracketedMatch?.id || null;
21717
21903
  }
21718
21904
  async acknowledgeOnboarding(providerServiceId, workspaceId, systemEnvironmentId) {
21719
21905
  const result = await this.akitaProxyRequest(
@@ -21743,6 +21929,14 @@ ${advised.message}` : advised.message : text;
21743
21929
  throw new Error(`Workspace acknowledge failed: ${result.status} ${result.errorText}`);
21744
21930
  }
21745
21931
  }
21932
+ // PMAK-only by proven exception. A live probe against the observability
21933
+ // application-binding endpoint (POST /v2/agent/api-catalog/workspaces/:id/
21934
+ // applications) showed x-access-token is rejected identically to the x-api-key
21935
+ // control: both return 401 {"message":"Postman User not found"} for a
21936
+ // service-account credential, because the observability service has no
21937
+ // "Postman User" for a service account. The access token offers no improvement
21938
+ // over the API key here, so this route is not migrated to access-token-primary
21939
+ // (the suite-wide migration explicitly leaves probe-failed routes on PMAK).
21746
21940
  async createApplication(workspaceId, systemEnv) {
21747
21941
  const response = await this.fetchFn(
21748
21942
  `${this.observabilityBaseUrl}/v2/agent/api-catalog/workspaces/${workspaceId}/applications`,
@@ -21810,7 +22004,17 @@ function findDiscoveredService(services, projectName, clusterName) {
21810
22004
  const fullName = `${clusterName}/${projectName}`;
21811
22005
  return services.find((s) => s.name === fullName);
21812
22006
  }
21813
- return services.find((s) => s.name.endsWith(`/${projectName}`));
22007
+ const finalSegmentMatch = services.find(
22008
+ (service) => getFinalServiceSegment(service.name) === projectName
22009
+ );
22010
+ if (finalSegmentMatch) return finalSegmentMatch;
22011
+ return services.find(
22012
+ (service) => getFinalServiceSegment(service.name).includes(`[${projectName}]`)
22013
+ );
22014
+ }
22015
+ function getFinalServiceSegment(serviceName) {
22016
+ const lastSlash = serviceName.lastIndexOf("/");
22017
+ return lastSlash === -1 ? serviceName : serviceName.slice(lastSlash + 1);
21814
22018
  }
21815
22019
 
21816
22020
  // node_modules/@postman-cse/automation-telemetry-core/dist/ci-context.js
@@ -21818,7 +22022,65 @@ function norm(value) {
21818
22022
  const trimmed = (value ?? "").trim();
21819
22023
  return trimmed.length > 0 ? trimmed : void 0;
21820
22024
  }
22025
+ function detectEventTrigger(env = process.env) {
22026
+ const ghEvent = norm(env.GITHUB_EVENT_NAME)?.toLowerCase();
22027
+ if (ghEvent) {
22028
+ if (ghEvent === "push")
22029
+ return "push";
22030
+ if (ghEvent === "pull_request" || ghEvent === "pull_request_target")
22031
+ return "pull_request";
22032
+ if (ghEvent === "schedule")
22033
+ return "schedule";
22034
+ if (ghEvent === "workflow_dispatch" || ghEvent === "repository_dispatch")
22035
+ return "manual";
22036
+ return "other";
22037
+ }
22038
+ const glSource = norm(env.CI_PIPELINE_SOURCE)?.toLowerCase();
22039
+ if (glSource) {
22040
+ if (glSource === "push")
22041
+ return "push";
22042
+ if (glSource === "merge_request_event")
22043
+ return "pull_request";
22044
+ if (glSource === "schedule")
22045
+ return "schedule";
22046
+ if (glSource === "web" || glSource === "api" || glSource === "trigger" || glSource === "pipeline") {
22047
+ return "manual";
22048
+ }
22049
+ return "other";
22050
+ }
22051
+ if (norm(env.BITBUCKET_PR_ID))
22052
+ return "pull_request";
22053
+ if (norm(env.CI) || norm(env.BUILD_BUILDID) || norm(env.JENKINS_URL) || norm(env.TEAMCITY_VERSION)) {
22054
+ return "other";
22055
+ }
22056
+ return "unknown";
22057
+ }
22058
+ function detectRunnerOs(env = process.env) {
22059
+ const runnerOs = norm(env.RUNNER_OS)?.toLowerCase();
22060
+ if (runnerOs === "linux")
22061
+ return "linux";
22062
+ if (runnerOs === "macos")
22063
+ return "macos";
22064
+ if (runnerOs === "windows")
22065
+ return "windows";
22066
+ const platform2 = typeof process !== "undefined" ? process.platform : void 0;
22067
+ if (platform2 === "linux")
22068
+ return "linux";
22069
+ if (platform2 === "darwin")
22070
+ return "macos";
22071
+ if (platform2 === "win32")
22072
+ return "windows";
22073
+ return "unknown";
22074
+ }
21821
22075
  function detectCiContext(env = process.env) {
22076
+ const provider = detectCiProviderContext(env);
22077
+ return {
22078
+ ...provider,
22079
+ eventTrigger: detectEventTrigger(env),
22080
+ runnerOs: detectRunnerOs(env)
22081
+ };
22082
+ }
22083
+ function detectCiProviderContext(env = process.env) {
21822
22084
  if (norm(env.GITHUB_ACTIONS)) {
21823
22085
  const runnerEnv = norm(env.RUNNER_ENVIRONMENT);
21824
22086
  const runnerKind = runnerEnv === "github-hosted" ? "hosted" : runnerEnv === "self-hosted" ? "self-hosted" : "unknown";
@@ -21956,25 +22218,49 @@ function parseProvider(explicitProvider, repoUrl, env) {
21956
22218
  }
21957
22219
  return "unknown";
21958
22220
  }
22221
+ function classifyRefKind(env = process.env) {
22222
+ const githubRefType = normalize(env.GITHUB_REF_TYPE)?.toLowerCase();
22223
+ const githubRef = normalize(env.GITHUB_REF);
22224
+ const azureRef = normalize(env.BUILD_SOURCEBRANCH);
22225
+ if (githubRefType === "tag" || githubRef?.startsWith("refs/tags/") || normalize(env.CI_COMMIT_TAG) || normalize(env.BITBUCKET_TAG) || azureRef?.startsWith("refs/tags/")) {
22226
+ return "tag";
22227
+ }
22228
+ const githubRefName = normalize(env.GITHUB_REF_NAME);
22229
+ const githubDefault = normalize(env.GITHUB_DEFAULT_BRANCH);
22230
+ if (githubRefName && githubDefault) {
22231
+ return githubRefName === githubDefault ? "default-branch" : "branch";
22232
+ }
22233
+ const gitlabRef = normalize(env.CI_COMMIT_REF_NAME);
22234
+ const gitlabDefault = normalize(env.CI_DEFAULT_BRANCH);
22235
+ if (gitlabRef && gitlabDefault) {
22236
+ return gitlabRef === gitlabDefault ? "default-branch" : "branch";
22237
+ }
22238
+ if (githubRefName || githubRef?.startsWith("refs/heads/") || gitlabRef || normalize(env.BITBUCKET_BRANCH) || normalize(env.BUILD_SOURCEBRANCHNAME) || azureRef?.startsWith("refs/heads/")) {
22239
+ return "branch";
22240
+ }
22241
+ return "unknown";
22242
+ }
21959
22243
  function detectRepoContext(input, env = process.env) {
21960
22244
  const repoUrl = normalizeRepoUrl(input.repoUrl) ?? normalizeRepoUrl(env.GITHUB_SERVER_URL && env.GITHUB_REPOSITORY ? `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}` : void 0) ?? normalizeRepoUrl(env.CI_PROJECT_URL) ?? normalizeRepoUrl(env.BITBUCKET_GIT_HTTP_ORIGIN) ?? normalizeRepoUrl(env.BUILD_REPOSITORY_URI);
21961
22245
  const repoSlug = normalize(input.repoSlug) ?? normalize(env.GITHUB_REPOSITORY) ?? normalize(env.CI_PROJECT_PATH) ?? (env.BITBUCKET_WORKSPACE && env.BITBUCKET_REPO_SLUG ? normalize(`${env.BITBUCKET_WORKSPACE}/${env.BITBUCKET_REPO_SLUG}`) : void 0) ?? normalize(env.BUILD_REPOSITORY_NAME);
21962
22246
  const ref = normalize(input.ref) ?? normalize(env.GITHUB_REF_NAME) ?? normalize(env.CI_COMMIT_REF_NAME) ?? normalize(env.BITBUCKET_BRANCH) ?? normalize(env.BUILD_SOURCEBRANCHNAME);
21963
22247
  const sha = normalize(input.sha) ?? normalize(env.GITHUB_SHA) ?? normalize(env.CI_COMMIT_SHA) ?? normalize(env.BITBUCKET_COMMIT) ?? normalize(env.BUILD_SOURCEVERSION);
21964
22248
  const provider = parseProvider(input.gitProvider, repoUrl, env);
22249
+ const refKind = classifyRefKind(env);
21965
22250
  return {
21966
22251
  provider,
21967
22252
  repoUrl,
21968
22253
  repoSlug,
21969
22254
  ref,
21970
- sha
22255
+ sha,
22256
+ refKind
21971
22257
  };
21972
22258
  }
21973
22259
 
21974
22260
  // node_modules/@postman-cse/automation-telemetry-core/dist/telemetry.js
21975
22261
  var import_node_crypto = require("node:crypto");
21976
22262
  var import_undici2 = __toESM(require_undici(), 1);
21977
- var SCHEMA_VERSION = 2;
22263
+ var SCHEMA_VERSION = 3;
21978
22264
  var DEFAULT_TIMEOUT_MS = 1500;
21979
22265
  var DEFAULT_ENDPOINT = "https://events.pm-cse.dev/v1/events";
21980
22266
  var proxyDispatcher;
@@ -21985,7 +22271,7 @@ function resolveActionVersion(explicit) {
21985
22271
  if (explicit) {
21986
22272
  return explicit;
21987
22273
  }
21988
- return "1.0.3" ? "1.0.3" : "unknown";
22274
+ return "2.0.0" ? "2.0.0" : "unknown";
21989
22275
  }
21990
22276
  function telemetryDisabled(env) {
21991
22277
  const flag = String(env.POSTMAN_ACTIONS_TELEMETRY ?? "").trim().toLowerCase();
@@ -22014,7 +22300,7 @@ function maybeNotice(logger) {
22014
22300
  return;
22015
22301
  }
22016
22302
  noticeShown = true;
22017
- logger.info("note: postman-actions sends anonymous usage data (team id, action, CI provider, account type). Disable with POSTMAN_ACTIONS_TELEMETRY=off or DO_NOT_TRACK=1.");
22303
+ logger.info("note: postman-actions sends anonymous usage data (team id, action, CI provider, account type, run trigger, runner OS). Disable with POSTMAN_ACTIONS_TELEMETRY=off or DO_NOT_TRACK=1.");
22018
22304
  }
22019
22305
  function buildTelemetryEvent(params) {
22020
22306
  const { action, actionVersion, teamId, accountType, outcome, env, now } = params;
@@ -22036,6 +22322,9 @@ function buildTelemetryEvent(params) {
22036
22322
  repo_id: repoSource ? sha256(repoSource) : void 0,
22037
22323
  org_id: owner ? sha256(owner) : void 0,
22038
22324
  account_type: accountType,
22325
+ event_trigger: ci.eventTrigger,
22326
+ runner_os: ci.runnerOs,
22327
+ ref_kind: repo.refKind,
22039
22328
  outcome,
22040
22329
  ts: now()
22041
22330
  };
@@ -22371,19 +22660,39 @@ async function resolveApiKeyAndTeamId(inputs, client, reporter = core_exports) {
22371
22660
  }
22372
22661
  return { apiKey, teamId: resolvedTeamId, pmakIdentity };
22373
22662
  }
22374
- async function runCredentialPreflightForInputs(inputs, pmak, reporter, fetchImpl) {
22663
+ async function runCredentialPreflightForInputs(inputs, pmak, reporter, fetchImpl, liveAccessToken) {
22664
+ const accessToken = liveAccessToken ?? inputs.postmanAccessToken;
22375
22665
  await runCredentialPreflight({
22376
22666
  apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22377
22667
  iapubBaseUrl: inputs.postmanIapubBase || DEFAULT_POSTMAN_IAPUB_BASE,
22378
22668
  pmak,
22379
- postmanAccessToken: inputs.postmanAccessToken,
22669
+ postmanAccessToken: accessToken,
22380
22670
  explicitTeamId: inputs.postmanTeamId || void 0,
22381
22671
  mode: inputs.credentialPreflight,
22382
- mask: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken]),
22672
+ mask: createSecretMasker([inputs.postmanApiKey, accessToken]),
22383
22673
  log: reporter,
22384
22674
  fetchImpl
22385
22675
  });
22386
22676
  }
22677
+ function createInsightsTokenProvider(inputs, reporter, apiKey = inputs.postmanApiKey) {
22678
+ return new AccessTokenProvider({
22679
+ accessToken: inputs.postmanAccessToken,
22680
+ apiKey,
22681
+ apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22682
+ onToken: (token) => reporter.setSecret(token)
22683
+ });
22684
+ }
22685
+ function createInsightsBifrostClient(inputs, tokenProvider, teamId, apiKey) {
22686
+ return new BifrostCatalogClient({
22687
+ tokenProvider,
22688
+ accessToken: tokenProvider.current(),
22689
+ teamId,
22690
+ apiKey,
22691
+ bifrostBaseUrl: inputs.postmanBifrostBase,
22692
+ observabilityBaseUrl: inputs.postmanObservabilityBase,
22693
+ observabilityEnv: inputs.postmanObservabilityEnv
22694
+ });
22695
+ }
22387
22696
  async function runAction() {
22388
22697
  const inputs = resolveInputs();
22389
22698
  const planned = createPlannedOutputs(inputs);
@@ -22393,28 +22702,32 @@ async function runAction() {
22393
22702
  setSecret(inputs.postmanAccessToken);
22394
22703
  if (inputs.postmanApiKey) setSecret(inputs.postmanApiKey);
22395
22704
  if (inputs.githubToken) setSecret(inputs.githubToken);
22396
- const preliminaryClient = new BifrostCatalogClient({
22397
- accessToken: inputs.postmanAccessToken,
22398
- teamId: inputs.postmanTeamId,
22399
- apiKey: inputs.postmanApiKey,
22400
- bifrostBaseUrl: inputs.postmanBifrostBase,
22401
- observabilityBaseUrl: inputs.postmanObservabilityBase,
22402
- observabilityEnv: inputs.postmanObservabilityEnv
22403
- });
22705
+ const tokenProvider = createInsightsTokenProvider(inputs, core_exports);
22706
+ const preliminaryClient = createInsightsBifrostClient(
22707
+ inputs,
22708
+ tokenProvider,
22709
+ inputs.postmanTeamId,
22710
+ inputs.postmanApiKey
22711
+ );
22404
22712
  const { apiKey, teamId, pmakIdentity } = await resolveApiKeyAndTeamId(inputs, preliminaryClient, core_exports);
22713
+ const activeTokenProvider = apiKey !== inputs.postmanApiKey ? new AccessTokenProvider({
22714
+ accessToken: tokenProvider.current(),
22715
+ apiKey,
22716
+ apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22717
+ onToken: (token) => setSecret(token)
22718
+ }) : tokenProvider;
22405
22719
  const telemetry = createTelemetryContext({ action: "postman-insights-onboarding-action", logger: core_exports });
22406
22720
  telemetry.setTeamId(inputs.postmanTeamId || pmakIdentity?.teamId);
22407
22721
  let result;
22408
22722
  try {
22409
- await runCredentialPreflightForInputs(inputs, pmakIdentity, core_exports);
22410
- const client = new BifrostCatalogClient({
22411
- accessToken: inputs.postmanAccessToken,
22412
- teamId,
22413
- apiKey,
22414
- bifrostBaseUrl: inputs.postmanBifrostBase,
22415
- observabilityBaseUrl: inputs.postmanObservabilityBase,
22416
- observabilityEnv: inputs.postmanObservabilityEnv
22417
- });
22723
+ await runCredentialPreflightForInputs(
22724
+ inputs,
22725
+ pmakIdentity,
22726
+ core_exports,
22727
+ void 0,
22728
+ activeTokenProvider.current()
22729
+ );
22730
+ const client = createInsightsBifrostClient(inputs, activeTokenProvider, teamId, apiKey);
22418
22731
  result = await runOnboarding(inputs, client, sleep, core_exports);
22419
22732
  } catch (error2) {
22420
22733
  const message = error2 instanceof Error ? error2.message : String(error2);
@@ -22445,6 +22758,8 @@ async function runAction() {
22445
22758
  DEFAULT_POSTMAN_BIFROST_BASE,
22446
22759
  DEFAULT_POSTMAN_IAPUB_BASE,
22447
22760
  DEFAULT_POSTMAN_OBSERVABILITY_BASE,
22761
+ createInsightsBifrostClient,
22762
+ createInsightsTokenProvider,
22448
22763
  createPlannedOutputs,
22449
22764
  getTeams,
22450
22765
  parsePreflightMode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postman-cse/onboarding-insights",
3
- "version": "1.0.3",
3
+ "version": "2.0.0",
4
4
  "description": "GitHub Action to onboard Postman Insights discovered services to API Catalog workspaces.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@actions/core": "^3.0.1",
38
- "@postman-cse/automation-telemetry-core": "^0.1.0",
38
+ "@postman-cse/automation-telemetry-core": "^0.2.0",
39
39
  "undici": "^6.24.0"
40
40
  },
41
41
  "overrides": {
@@ -43,8 +43,8 @@
43
43
  "picomatch": ">=4.0.4"
44
44
  },
45
45
  "devDependencies": {
46
- "@commitlint/cli": "^20.5.3",
47
- "@commitlint/config-conventional": "^20.5.3",
46
+ "@commitlint/cli": "^21.0.2",
47
+ "@commitlint/config-conventional": "^21.0.2",
48
48
  "@eslint/js": "^10.0.1",
49
49
  "@types/node": "^24.12.4",
50
50
  "esbuild": "^0.28.0",