@postman-cse/onboarding-insights 2.1.0 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/action.cjs CHANGED
@@ -21540,6 +21540,42 @@ async function retry(operation, options = {}) {
21540
21540
  }
21541
21541
  throw new Error("Retry exhausted without returning or throwing");
21542
21542
  }
21543
+ function isTransientHttpStatus(status) {
21544
+ return status === 408 || status === 429 || status >= 500;
21545
+ }
21546
+ function extractStatus(error2) {
21547
+ if (error2 instanceof HttpError) {
21548
+ return error2.status;
21549
+ }
21550
+ if (error2 && typeof error2 === "object" && "status" in error2) {
21551
+ const status = error2.status;
21552
+ return typeof status === "number" ? status : void 0;
21553
+ }
21554
+ if (error2 && typeof error2 === "object" && "cause" in error2) {
21555
+ return extractStatus(error2.cause);
21556
+ }
21557
+ return void 0;
21558
+ }
21559
+ function shouldRetryReadError(error2) {
21560
+ const status = extractStatus(error2);
21561
+ if (status === void 0) {
21562
+ return true;
21563
+ }
21564
+ return isTransientHttpStatus(status);
21565
+ }
21566
+ function isAmbiguousMutationFailure(error2) {
21567
+ const status = extractStatus(error2);
21568
+ if (status === void 0) {
21569
+ return true;
21570
+ }
21571
+ return isTransientHttpStatus(status);
21572
+ }
21573
+ var SAFE_READ_RETRY = {
21574
+ maxAttempts: 3,
21575
+ delayMs: 2e3,
21576
+ backoffMultiplier: 2,
21577
+ shouldRetry: (error2) => shouldRetryReadError(error2)
21578
+ };
21543
21579
 
21544
21580
  // src/lib/postman/base-urls.ts
21545
21581
  var POSTMAN_ENDPOINT_PROFILES = {
@@ -21754,6 +21790,27 @@ var MAX_PROVIDER_SERVICE_PAGES = 100;
21754
21790
  function isExpiredAuthError(status, body) {
21755
21791
  return status === 401 || body.includes("UNAUTHENTICATED") || body.includes("authenticationError");
21756
21792
  }
21793
+ function normalizeRepoUrl(url) {
21794
+ return url.trim().replace(/\/+$/, "").toLowerCase();
21795
+ }
21796
+ async function mutateOnceThenReconcile(options) {
21797
+ const existing = await options.findExisting();
21798
+ if (existing !== null) {
21799
+ return existing;
21800
+ }
21801
+ try {
21802
+ return await options.mutate();
21803
+ } catch (error2) {
21804
+ if (!isAmbiguousMutationFailure(error2)) {
21805
+ throw error2;
21806
+ }
21807
+ const adopted = await options.findExisting();
21808
+ if (adopted !== null) {
21809
+ return adopted;
21810
+ }
21811
+ throw error2;
21812
+ }
21813
+ }
21757
21814
  var BifrostCatalogClient = class {
21758
21815
  tokenProvider;
21759
21816
  teamId;
@@ -21790,8 +21847,9 @@ var BifrostCatalogClient = class {
21790
21847
  }
21791
21848
  /**
21792
21849
  * Build Bifrost proxy headers.
21793
- * x-entity-team-id is ONLY included when teamId is present (org-mode tokens).
21794
- * Non-org-mode tokens must OMIT it so Bifrost resolves team from the access token.
21850
+ * x-entity-team-id is ONLY included when teamId is present (explicit input /
21851
+ * POSTMAN_TEAM_ID). Non-org-mode tokens must OMIT it so Bifrost resolves team
21852
+ * from the access token. Team is never inferred from PMAK.
21795
21853
  */
21796
21854
  headers() {
21797
21855
  const h = {
@@ -21819,7 +21877,7 @@ var BifrostCatalogClient = class {
21819
21877
  mask: createSecretMasker(this.secretValues)
21820
21878
  };
21821
21879
  }
21822
- async proxyRequest(method, path6, body = {}, operation = "api-catalog request") {
21880
+ async proxyRequest(method, path6, body = {}, operation = "api-catalog request", allowAuthReplay = false) {
21823
21881
  const send2 = async () => this.fetchFn(this.bifrostProxyUrl, {
21824
21882
  method: "POST",
21825
21883
  headers: this.headers(),
@@ -21833,7 +21891,7 @@ var BifrostCatalogClient = class {
21833
21891
  let response = await send2();
21834
21892
  if (!response.ok) {
21835
21893
  const bodyText = await response.text().catch(() => "");
21836
- if (isExpiredAuthError(response.status, bodyText) && this.tokenProvider.canRefresh()) {
21894
+ if (allowAuthReplay && isExpiredAuthError(response.status, bodyText) && this.tokenProvider.canRefresh()) {
21837
21895
  try {
21838
21896
  const refreshed = await this.tokenProvider.refresh();
21839
21897
  this.registerAccessToken(refreshed);
@@ -21884,7 +21942,7 @@ var BifrostCatalogClient = class {
21884
21942
  }
21885
21943
  return data;
21886
21944
  }
21887
- async akitaProxyRequest(method, path6, body = {}, operation = "Insights request") {
21945
+ async akitaProxyRequest(method, path6, body = {}, operation = "Insights request", allowAuthReplay = false) {
21888
21946
  const send2 = async () => this.fetchFn(this.bifrostProxyUrl, {
21889
21947
  method: "POST",
21890
21948
  headers: this.headers(),
@@ -21898,7 +21956,7 @@ var BifrostCatalogClient = class {
21898
21956
  let response = await send2();
21899
21957
  if (!response.ok) {
21900
21958
  const text = await response.text().catch(() => "");
21901
- if (isExpiredAuthError(response.status, text) && this.tokenProvider.canRefresh()) {
21959
+ if (allowAuthReplay && isExpiredAuthError(response.status, text) && this.tokenProvider.canRefresh()) {
21902
21960
  try {
21903
21961
  const refreshed = await this.tokenProvider.refresh();
21904
21962
  this.registerAccessToken(refreshed);
@@ -21927,6 +21985,17 @@ ${advised.message}` : advised.message : text;
21927
21985
  const data = await response.json();
21928
21986
  return { ok: true, status: response.status, data, errorText: "" };
21929
21987
  }
21988
+ throwAkitaFailure(status, errorText, operation, path6) {
21989
+ const httpErr = new HttpError({
21990
+ method: "POST",
21991
+ url: `bifrost:akita:${path6}`,
21992
+ status,
21993
+ statusText: status >= 500 ? "Error" : "Client Error",
21994
+ responseBody: errorText
21995
+ });
21996
+ const advised = adviseFromHttpError(httpErr, this.adviceContext(operation));
21997
+ throw advised ?? httpErr;
21998
+ }
21930
21999
  async listDiscoveredServices() {
21931
22000
  return retry(
21932
22001
  async () => {
@@ -21954,26 +22023,80 @@ ${advised.message}` : advised.message : text;
21954
22023
  }
21955
22024
  return allItems;
21956
22025
  },
21957
- { maxAttempts: 3, delayMs: 2e3, backoffMultiplier: 2 }
22026
+ SAFE_READ_RETRY
21958
22027
  );
21959
22028
  }
21960
- async prepareCollection(serviceId, workspaceId) {
22029
+ /** List discovered + integrated services for exact link reconciliation. */
22030
+ async listServicesForReconcile() {
21961
22031
  return retry(
21962
22032
  async () => {
22033
+ const allItems = [];
22034
+ let cursor = null;
22035
+ const seenCursors = /* @__PURE__ */ new Set();
22036
+ for (let page = 0; page < MAX_DISCOVERED_SERVICE_PAGES; page += 1) {
22037
+ const query = cursor ? `?cursor=${encodeURIComponent(cursor)}` : "";
22038
+ const data = await this.proxyRequest(
22039
+ "GET",
22040
+ `/api/v1/onboarding/discovered-services${query}`,
22041
+ {},
22042
+ "service link reconciliation"
22043
+ );
22044
+ allItems.push(...data.items || []);
22045
+ if (data.total && allItems.length >= data.total) {
22046
+ break;
22047
+ }
22048
+ const nextCursor = data.nextCursor || null;
22049
+ if (!nextCursor || seenCursors.has(nextCursor)) {
22050
+ break;
22051
+ }
22052
+ seenCursors.add(nextCursor);
22053
+ cursor = nextCursor;
22054
+ }
22055
+ return allItems;
22056
+ },
22057
+ SAFE_READ_RETRY
22058
+ );
22059
+ }
22060
+ async findPreparedCollection(serviceId, workspaceId) {
22061
+ const services = await this.listServicesForReconcile();
22062
+ const match = services.find(
22063
+ (service) => service.id === serviceId && Boolean(service.collectionId) && service.workspaceId === workspaceId
22064
+ );
22065
+ return match?.collectionId ? String(match.collectionId) : null;
22066
+ }
22067
+ async findGitLink(params) {
22068
+ const services = await this.listServicesForReconcile();
22069
+ const match = services.find((service) => {
22070
+ if (service.id !== params.serviceId) return false;
22071
+ if (service.workspaceId !== params.workspaceId) return false;
22072
+ if (service.environmentId !== params.environmentId) return false;
22073
+ if (!service.gitRepositoryUrl) return false;
22074
+ return normalizeRepoUrl(service.gitRepositoryUrl) === normalizeRepoUrl(params.gitRepositoryUrl);
22075
+ });
22076
+ return match ? true : null;
22077
+ }
22078
+ async prepareCollection(serviceId, workspaceId) {
22079
+ return mutateOnceThenReconcile({
22080
+ findExisting: () => this.findPreparedCollection(serviceId, workspaceId),
22081
+ mutate: async () => {
21963
22082
  const data = await this.proxyRequest(
21964
22083
  "POST",
21965
22084
  "/api/v1/onboarding/prepare-collection",
21966
22085
  { service_id: String(serviceId), workspace_id: workspaceId },
21967
- "collection preparation"
22086
+ "collection preparation",
22087
+ false
21968
22088
  );
22089
+ if (!data?.id) {
22090
+ throw new Error("prepare-collection succeeded without a collection id");
22091
+ }
21969
22092
  return data.id;
21970
- },
21971
- { maxAttempts: 3, delayMs: 2e3, backoffMultiplier: 2 }
21972
- );
22093
+ }
22094
+ });
21973
22095
  }
21974
22096
  async onboardGit(params) {
21975
- await retry(
21976
- async () => {
22097
+ await mutateOnceThenReconcile({
22098
+ findExisting: () => this.findGitLink(params),
22099
+ mutate: async () => {
21977
22100
  const body = {
21978
22101
  via_integrations: false,
21979
22102
  git_service_name: "github",
@@ -21989,24 +22112,32 @@ ${advised.message}` : advised.message : text;
21989
22112
  "POST",
21990
22113
  "/api/v1/onboarding/git",
21991
22114
  body,
21992
- "git onboarding"
22115
+ "git onboarding",
22116
+ false
21993
22117
  );
21994
- },
21995
- { maxAttempts: 2, delayMs: 3e3 }
21996
- );
22118
+ return true;
22119
+ }
22120
+ });
21997
22121
  }
21998
- async resolveProviderServiceId(projectName, clusterName) {
22122
+ async listProviderServices() {
21999
22123
  const allServices = [];
22000
22124
  let page = 1;
22001
22125
  const pageSize = 100;
22002
22126
  for (let pageCount = 0; pageCount < MAX_PROVIDER_SERVICE_PAGES; pageCount += 1) {
22003
22127
  const result = await this.akitaProxyRequest(
22004
22128
  "GET",
22005
- `/v2/api-catalog/services?status=discovered&populate_endpoints=false&populate_discovery_metadata=true&page=${page}&page_size=${pageSize}`,
22129
+ `/v2/api-catalog/services?populate_endpoints=false&populate_discovery_metadata=true&page=${page}&page_size=${pageSize}`,
22006
22130
  {},
22007
22131
  "provider service resolution"
22008
22132
  );
22009
- if (!result.ok || !result.data) return null;
22133
+ if (!result.ok || !result.data) {
22134
+ this.throwAkitaFailure(
22135
+ result.status,
22136
+ result.errorText,
22137
+ "provider service resolution",
22138
+ "GET /v2/api-catalog/services"
22139
+ );
22140
+ }
22010
22141
  const services = result.data.services || [];
22011
22142
  allServices.push(...services);
22012
22143
  if (result.data.total && allServices.length >= result.data.total) {
@@ -22017,86 +22148,225 @@ ${advised.message}` : advised.message : text;
22017
22148
  }
22018
22149
  page++;
22019
22150
  }
22151
+ return allServices;
22152
+ }
22153
+ async resolveProviderServiceId(projectName, clusterName) {
22154
+ const allServices = await retry(
22155
+ async () => this.listProviderServices(),
22156
+ SAFE_READ_RETRY
22157
+ );
22020
22158
  if (clusterName) {
22021
22159
  const fullName = `${clusterName}/${projectName}`;
22022
22160
  const exactMatch = allServices.find((s) => s.name === fullName);
22023
22161
  return exactMatch?.id || null;
22024
22162
  }
22025
- const finalSegmentMatch = allServices.find(
22163
+ const finalSegmentMatches = allServices.filter(
22026
22164
  (s) => getFinalServiceSegment(s.name) === projectName
22027
22165
  );
22028
- if (finalSegmentMatch) return finalSegmentMatch.id;
22029
- const bracketedMatch = allServices.find(
22166
+ if (finalSegmentMatches.length > 1) {
22167
+ throw new Error(
22168
+ `Ambiguous Insights provider service "${projectName}": multiple final-segment matches (${finalSegmentMatches.map((s) => s.name).join(", ")}). Provide cluster-name to select the canonical service identity.`
22169
+ );
22170
+ }
22171
+ if (finalSegmentMatches.length === 1) return finalSegmentMatches[0].id;
22172
+ const bracketedMatches = allServices.filter(
22030
22173
  (s) => getFinalServiceSegment(s.name).includes(`[${projectName}]`)
22031
22174
  );
22032
- return bracketedMatch?.id || null;
22175
+ if (bracketedMatches.length > 1) {
22176
+ throw new Error(
22177
+ `Ambiguous Insights provider service "${projectName}": multiple bracketed matches. Provide cluster-name to select the canonical service identity.`
22178
+ );
22179
+ }
22180
+ return bracketedMatches[0]?.id || null;
22181
+ }
22182
+ async findAcknowledgedOnboarding(providerServiceId, workspaceId, systemEnvironmentId) {
22183
+ const services = await this.listProviderServices();
22184
+ const match = services.find(
22185
+ (service) => service.id === providerServiceId && service.workspace_id === workspaceId && service.system_env === systemEnvironmentId && (service.status === "onboarded" || service.status === "integrated" || Boolean(service.workspace_id))
22186
+ );
22187
+ return match ? true : null;
22033
22188
  }
22034
22189
  async acknowledgeOnboarding(providerServiceId, workspaceId, systemEnvironmentId) {
22035
- const result = await this.akitaProxyRequest(
22036
- "POST",
22037
- "/v2/api-catalog/services/onboard",
22038
- {
22039
- services: [{
22040
- service_id: providerServiceId,
22041
- workspace_id: workspaceId,
22042
- system_env: systemEnvironmentId
22043
- }]
22190
+ await mutateOnceThenReconcile({
22191
+ findExisting: () => this.findAcknowledgedOnboarding(providerServiceId, workspaceId, systemEnvironmentId),
22192
+ mutate: async () => {
22193
+ const result = await this.akitaProxyRequest(
22194
+ "POST",
22195
+ "/v2/api-catalog/services/onboard",
22196
+ {
22197
+ services: [{
22198
+ service_id: providerServiceId,
22199
+ workspace_id: workspaceId,
22200
+ system_env: systemEnvironmentId
22201
+ }]
22202
+ },
22203
+ "Insights onboarding acknowledgment",
22204
+ false
22205
+ );
22206
+ if (!result.ok) {
22207
+ this.throwAkitaFailure(
22208
+ result.status,
22209
+ result.errorText,
22210
+ "Insights onboarding acknowledgment",
22211
+ "POST /v2/api-catalog/services/onboard"
22212
+ );
22213
+ }
22214
+ return true;
22215
+ }
22216
+ });
22217
+ }
22218
+ async findWorkspaceAcknowledged(workspaceId) {
22219
+ const result = await retry(
22220
+ async () => {
22221
+ const response = await this.akitaProxyRequest(
22222
+ "GET",
22223
+ `/v2/workspaces/${workspaceId}/onboarding/acknowledge`,
22224
+ {},
22225
+ "workspace onboarding acknowledgment status"
22226
+ );
22227
+ if (!response.ok) {
22228
+ this.throwAkitaFailure(
22229
+ response.status,
22230
+ response.errorText,
22231
+ "workspace onboarding acknowledgment status",
22232
+ `GET /v2/workspaces/${workspaceId}/onboarding/acknowledge`
22233
+ );
22234
+ }
22235
+ return response;
22044
22236
  },
22045
- "Insights onboarding acknowledgment"
22237
+ SAFE_READ_RETRY
22046
22238
  );
22047
- if (!result.ok) {
22048
- throw new Error(`Insights acknowledge failed: ${result.status} ${result.errorText}`);
22049
- }
22239
+ return result.data?.onboarding_acknowledged ? true : null;
22050
22240
  }
22051
22241
  async acknowledgeWorkspace(workspaceId) {
22052
- const result = await this.akitaProxyRequest(
22053
- "POST",
22054
- `/v2/workspaces/${workspaceId}/onboarding/acknowledge`,
22055
- {},
22056
- "workspace onboarding acknowledgment"
22057
- );
22058
- if (!result.ok) {
22059
- throw new Error(`Workspace acknowledge failed: ${result.status} ${result.errorText}`);
22060
- }
22242
+ await mutateOnceThenReconcile({
22243
+ findExisting: () => this.findWorkspaceAcknowledged(workspaceId),
22244
+ mutate: async () => {
22245
+ const result = await this.akitaProxyRequest(
22246
+ "POST",
22247
+ `/v2/workspaces/${workspaceId}/onboarding/acknowledge`,
22248
+ {},
22249
+ "workspace onboarding acknowledgment",
22250
+ false
22251
+ );
22252
+ if (!result.ok) {
22253
+ this.throwAkitaFailure(
22254
+ result.status,
22255
+ result.errorText,
22256
+ "workspace onboarding acknowledgment",
22257
+ `POST /v2/workspaces/${workspaceId}/onboarding/acknowledge`
22258
+ );
22259
+ }
22260
+ return true;
22261
+ }
22262
+ });
22061
22263
  }
22062
- // PMAK-only by proven exception. A live probe against the observability
22063
- // application-binding endpoint (POST /v2/agent/api-catalog/workspaces/:id/
22064
- // applications) showed x-access-token is rejected identically to the x-api-key
22065
- // control: both return 401 {"message":"Postman User not found"} for a
22066
- // service-account credential, because the observability service has no
22067
- // "Postman User" for a service account. The access token offers no improvement
22068
- // over the API key here, so this route is not migrated to access-token-primary
22069
- // (the suite-wide migration explicitly leaves probe-failed routes on PMAK).
22070
- async createApplication(workspaceId, systemEnv) {
22264
+ async findApplication(workspaceId, systemEnv, expectedServiceId) {
22071
22265
  const response = await this.fetchFn(
22072
22266
  `${this.observabilityBaseUrl}/v2/agent/api-catalog/workspaces/${workspaceId}/applications`,
22073
22267
  {
22074
- method: "POST",
22268
+ method: "GET",
22075
22269
  headers: {
22076
22270
  "x-api-key": this.apiKey,
22077
22271
  "x-postman-env": this.observabilityEnv,
22078
22272
  "Content-Type": "application/json"
22079
- },
22080
- body: JSON.stringify({ system_env: systemEnv })
22273
+ }
22081
22274
  }
22082
22275
  );
22083
22276
  if (!response.ok) {
22084
22277
  const httpErr = await HttpError.fromResponse(response, {
22085
- method: "POST",
22086
- url: `observability:createApplication(${workspaceId})`,
22278
+ method: "GET",
22279
+ url: `observability:listApplications(${workspaceId})`,
22087
22280
  secretValues: this.secretValues
22088
22281
  });
22089
- const advised = adviseFromHttpError(httpErr, this.adviceContext("application binding"));
22282
+ const advised = adviseFromHttpError(httpErr, this.adviceContext("application binding lookup"));
22090
22283
  throw advised ?? httpErr;
22091
22284
  }
22092
- return response.json();
22285
+ const data = await response.json();
22286
+ const matches = (data.applications || []).filter(
22287
+ (app) => app.application_id && app.service_id && app.system_env === systemEnv && (!expectedServiceId || app.service_id === expectedServiceId)
22288
+ );
22289
+ if (matches.length > 1) {
22290
+ throw new Error(
22291
+ `Multiple application bindings match workspace ${workspaceId}, system environment ${systemEnv}, and service ${expectedServiceId || "(unspecified)"}`
22292
+ );
22293
+ }
22294
+ const match = matches[0];
22295
+ if (!match?.application_id || !match.service_id) {
22296
+ return null;
22297
+ }
22298
+ return {
22299
+ application_id: String(match.application_id),
22300
+ service_id: String(match.service_id)
22301
+ };
22302
+ }
22303
+ // PMAK-only by proven exception. A live probe against the observability
22304
+ // application-binding endpoint (POST /v2/agent/api-catalog/workspaces/:id/
22305
+ // applications) showed x-access-token is rejected identically to the x-api-key
22306
+ // control: both return 401 {"message":"Postman User not found"} for a
22307
+ // service-account credential, because the observability service has no
22308
+ // "Postman User" for a service account. The access token offers no improvement
22309
+ // over the API key here, so this route is not migrated to access-token-primary
22310
+ // (the suite-wide migration explicitly leaves probe-failed routes on PMAK).
22311
+ async createApplication(workspaceId, systemEnv, expectedServiceId) {
22312
+ return mutateOnceThenReconcile({
22313
+ findExisting: () => retry(
22314
+ () => this.findApplication(workspaceId, systemEnv, expectedServiceId),
22315
+ SAFE_READ_RETRY
22316
+ ),
22317
+ mutate: async () => {
22318
+ const response = await this.fetchFn(
22319
+ `${this.observabilityBaseUrl}/v2/agent/api-catalog/workspaces/${workspaceId}/applications`,
22320
+ {
22321
+ method: "POST",
22322
+ headers: {
22323
+ "x-api-key": this.apiKey,
22324
+ "x-postman-env": this.observabilityEnv,
22325
+ "Content-Type": "application/json"
22326
+ },
22327
+ body: JSON.stringify({ system_env: systemEnv })
22328
+ }
22329
+ );
22330
+ if (!response.ok) {
22331
+ const httpErr = await HttpError.fromResponse(response, {
22332
+ method: "POST",
22333
+ url: `observability:createApplication(${workspaceId})`,
22334
+ secretValues: this.secretValues
22335
+ });
22336
+ const advised = adviseFromHttpError(httpErr, this.adviceContext("application binding"));
22337
+ throw advised ?? httpErr;
22338
+ }
22339
+ const created = await response.json();
22340
+ if (expectedServiceId && created.service_id !== expectedServiceId) {
22341
+ throw new Error(
22342
+ `Application binding credential/scope mismatch: expected service ${expectedServiceId}, received ${created.service_id}`
22343
+ );
22344
+ }
22345
+ return created;
22346
+ }
22347
+ });
22093
22348
  }
22094
22349
  async getTeamVerificationToken(workspaceId) {
22095
- const result = await this.akitaProxyRequest(
22096
- "GET",
22097
- `/v2/workspaces/${workspaceId}/team-verification-token`,
22098
- {},
22099
- "team verification token retrieval"
22350
+ const result = await retry(
22351
+ async () => {
22352
+ const page = await this.akitaProxyRequest(
22353
+ "GET",
22354
+ `/v2/workspaces/${workspaceId}/team-verification-token`,
22355
+ {},
22356
+ "team verification token retrieval"
22357
+ );
22358
+ if (!page.ok && (page.status === 408 || page.status === 429 || page.status >= 500)) {
22359
+ throw new HttpError({
22360
+ method: "GET",
22361
+ url: `bifrost:akita:GET /v2/workspaces/${workspaceId}/team-verification-token`,
22362
+ status: page.status,
22363
+ statusText: "Error",
22364
+ responseBody: page.errorText
22365
+ });
22366
+ }
22367
+ return page;
22368
+ },
22369
+ SAFE_READ_RETRY
22100
22370
  );
22101
22371
  if (!result.ok || !result.data) return null;
22102
22372
  return result.data.team_verification_token || null;
@@ -22129,24 +22399,87 @@ ${advised.message}` : advised.message : text;
22129
22399
  return String(apikey.key);
22130
22400
  }
22131
22401
  };
22402
+ function buildCanonicalServiceIdentity(service, projectName, clusterName, providerServiceId) {
22403
+ const derivedCluster = clusterName || (service.name.includes("/") ? service.name.slice(0, service.name.lastIndexOf("/")) : null);
22404
+ return {
22405
+ serviceId: service.id,
22406
+ serviceName: service.name,
22407
+ clusterName: derivedCluster,
22408
+ projectName,
22409
+ ...providerServiceId ? { providerServiceId } : {}
22410
+ };
22411
+ }
22132
22412
  function findDiscoveredService(services, projectName, clusterName) {
22133
22413
  if (clusterName) {
22134
22414
  const fullName = `${clusterName}/${projectName}`;
22135
- return services.find((s) => s.name === fullName);
22415
+ const match = services.find((s) => s.name === fullName);
22416
+ if (match) {
22417
+ match.canonicalIdentity = buildCanonicalServiceIdentity(match, projectName, clusterName);
22418
+ }
22419
+ return match;
22136
22420
  }
22137
- const finalSegmentMatch = services.find(
22421
+ const finalSegmentMatches = services.filter(
22138
22422
  (service) => getFinalServiceSegment(service.name) === projectName
22139
22423
  );
22140
- if (finalSegmentMatch) return finalSegmentMatch;
22141
- return services.find(
22424
+ if (finalSegmentMatches.length > 1) {
22425
+ throw new Error(
22426
+ `Ambiguous discovered service "${projectName}": multiple final-segment matches (${finalSegmentMatches.map((s) => s.name).join(", ")}). cluster-name is required to select the canonical service identity.`
22427
+ );
22428
+ }
22429
+ if (finalSegmentMatches.length === 1) {
22430
+ const match = finalSegmentMatches[0];
22431
+ match.canonicalIdentity = buildCanonicalServiceIdentity(match, projectName);
22432
+ return match;
22433
+ }
22434
+ const bracketedMatches = services.filter(
22142
22435
  (service) => getFinalServiceSegment(service.name).includes(`[${projectName}]`)
22143
22436
  );
22437
+ if (bracketedMatches.length > 1) {
22438
+ throw new Error(
22439
+ `Ambiguous discovered service "${projectName}": multiple bracketed matches. cluster-name is required to select the canonical service identity.`
22440
+ );
22441
+ }
22442
+ if (bracketedMatches.length === 1) {
22443
+ const match = bracketedMatches[0];
22444
+ match.canonicalIdentity = buildCanonicalServiceIdentity(match, projectName);
22445
+ return match;
22446
+ }
22447
+ return void 0;
22144
22448
  }
22145
22449
  function getFinalServiceSegment(serviceName) {
22146
22450
  const lastSlash = serviceName.lastIndexOf("/");
22147
22451
  return lastSlash === -1 ? serviceName : serviceName.slice(lastSlash + 1);
22148
22452
  }
22149
22453
 
22454
+ // src/lib/input.ts
22455
+ function normalizeInputValue(value) {
22456
+ return String(value ?? "").trim();
22457
+ }
22458
+ function runnerInputEnvName(name) {
22459
+ return `INPUT_${name.replace(/ /g, "_").toUpperCase()}`;
22460
+ }
22461
+ function normalizedInputEnvName(name) {
22462
+ return `INPUT_${name.replace(/-/g, "_").toUpperCase()}`;
22463
+ }
22464
+ function getInput2(name, env = process.env) {
22465
+ const normalizedName = normalizedInputEnvName(name);
22466
+ const runnerName = runnerInputEnvName(name);
22467
+ const normalizedRaw = env[normalizedName];
22468
+ const runnerRaw = runnerName === normalizedName ? void 0 : env[runnerName];
22469
+ const hasNormalized = normalizedRaw !== void 0;
22470
+ const hasRunner = runnerRaw !== void 0;
22471
+ if (hasNormalized && hasRunner) {
22472
+ const normalizedValue = normalizeInputValue(normalizedRaw);
22473
+ const runnerValue = normalizeInputValue(runnerRaw);
22474
+ if (normalizedValue !== runnerValue) {
22475
+ throw new Error(
22476
+ `Conflicting values for ${name}: ${normalizedName}=${JSON.stringify(normalizedValue)} vs ${runnerName}=${JSON.stringify(runnerValue)}`
22477
+ );
22478
+ }
22479
+ }
22480
+ return normalizeInputValue(hasNormalized ? normalizedRaw : runnerRaw);
22481
+ }
22482
+
22150
22483
  // node_modules/@postman-cse/automation-telemetry-core/dist/ci-context.js
22151
22484
  function norm(value) {
22152
22485
  const trimmed = (value ?? "").trim();
@@ -22303,7 +22636,7 @@ function normalize(value) {
22303
22636
  const trimmed = (value ?? "").trim();
22304
22637
  return trimmed.length > 0 ? trimmed : void 0;
22305
22638
  }
22306
- function normalizeRepoUrl(url) {
22639
+ function normalizeRepoUrl2(url) {
22307
22640
  const raw = normalize(url);
22308
22641
  if (!raw) {
22309
22642
  return void 0;
@@ -22371,7 +22704,7 @@ function classifyRefKind(env = process.env) {
22371
22704
  return "unknown";
22372
22705
  }
22373
22706
  function detectRepoContext(input, env = process.env) {
22374
- 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);
22707
+ const repoUrl = normalizeRepoUrl2(input.repoUrl) ?? normalizeRepoUrl2(env.GITHUB_SERVER_URL && env.GITHUB_REPOSITORY ? `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}` : void 0) ?? normalizeRepoUrl2(env.CI_PROJECT_URL) ?? normalizeRepoUrl2(env.BITBUCKET_GIT_HTTP_ORIGIN) ?? normalizeRepoUrl2(env.BUILD_REPOSITORY_URI);
22375
22708
  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);
22376
22709
  const ref = normalize(input.ref) ?? normalize(env.GITHUB_REF_NAME) ?? normalize(env.CI_COMMIT_REF_NAME) ?? normalize(env.BITBUCKET_BRANCH) ?? normalize(env.BUILD_SOURCEBRANCHNAME);
22377
22710
  const sha = normalize(input.sha) ?? normalize(env.GITHUB_SHA) ?? normalize(env.CI_COMMIT_SHA) ?? normalize(env.BITBUCKET_COMMIT) ?? normalize(env.BUILD_SOURCEVERSION);
@@ -22548,7 +22881,7 @@ var DEFAULT_POSTMAN_BIFROST_BASE = PROD_ENDPOINTS.bifrostBaseUrl;
22548
22881
  var DEFAULT_POSTMAN_IAPUB_BASE = PROD_ENDPOINTS.iapubBaseUrl;
22549
22882
  var DEFAULT_POSTMAN_OBSERVABILITY_BASE = PROD_ENDPOINTS.observabilityBaseUrl;
22550
22883
  function parsePreflightMode(value) {
22551
- const normalized = String(value || "warn").trim().toLowerCase();
22884
+ const normalized = String(value || "enforce").trim().toLowerCase();
22552
22885
  if (normalized === "enforce" || normalized === "warn") {
22553
22886
  return normalized;
22554
22887
  }
@@ -22556,6 +22889,27 @@ function parsePreflightMode(value) {
22556
22889
  `Unsupported credential-preflight "${value}". Supported values: enforce, warn`
22557
22890
  );
22558
22891
  }
22892
+ function parseServiceNotFoundPolicy(value) {
22893
+ const normalized = String(value || "fail").trim().toLowerCase();
22894
+ if (normalized === "fail" || normalized === "warn") {
22895
+ return normalized;
22896
+ }
22897
+ throw new Error(
22898
+ `Unsupported service-not-found-policy "${value}". Supported values: fail, warn`
22899
+ );
22900
+ }
22901
+ function parseCreateApiKey(value) {
22902
+ const normalized = String(value || "false").trim().toLowerCase();
22903
+ if (normalized === "true") {
22904
+ return true;
22905
+ }
22906
+ if (normalized === "false" || normalized === "") {
22907
+ return false;
22908
+ }
22909
+ throw new Error(
22910
+ `Unsupported create-api-key "${value}". Supported values: true, false`
22911
+ );
22912
+ }
22559
22913
  function trimTrailingSlash(value) {
22560
22914
  return value.replace(/\/+$/, "");
22561
22915
  }
@@ -22574,29 +22928,12 @@ async function validateApiKey(apiKey, apiBase = DEFAULT_POSTMAN_API_BASE) {
22574
22928
  const teamId = data?.user?.teamId ? String(data.user.teamId) : void 0;
22575
22929
  return { valid: true, teamId };
22576
22930
  }
22577
- async function getTeams(apiKey, apiBase = DEFAULT_POSTMAN_API_BASE) {
22578
- try {
22579
- const res = await fetch(`${trimTrailingSlash(apiBase)}/teams`, {
22580
- method: "GET",
22581
- headers: { "x-api-key": apiKey }
22582
- });
22583
- if (!res.ok) return [];
22584
- const data = await res.json();
22585
- return (data?.data ?? []).filter((t) => t?.id && t?.name).map((t) => ({
22586
- id: Number(t.id),
22587
- name: String(t.name),
22588
- ...t.organizationId != null ? { organizationId: Number(t.organizationId) } : {}
22589
- }));
22590
- } catch {
22591
- return [];
22592
- }
22593
- }
22594
22931
  function clamp(value, min, max, fallback) {
22595
22932
  const parsed = Number.isFinite(value) ? value : fallback;
22596
22933
  return Math.min(max, Math.max(min, parsed));
22597
22934
  }
22598
22935
  function resolveInputs(env = process.env) {
22599
- const get = (name, fallback = "") => env[`INPUT_${name.toUpperCase().replace(/-/g, "_")}`]?.trim() || fallback;
22936
+ const get = (name, fallback = "") => getInput2(name, env) || fallback;
22600
22937
  const projectName = get("project-name");
22601
22938
  if (!projectName) throw new Error("project-name is required");
22602
22939
  const postmanAccessToken = get("postman-access-token");
@@ -22637,7 +22974,9 @@ function resolveInputs(env = process.env) {
22637
22974
  postmanApiKey,
22638
22975
  postmanTeamId,
22639
22976
  githubToken: get("github-token", env.GITHUB_TOKEN || ""),
22640
- credentialPreflight: parsePreflightMode(get("credential-preflight", "warn")),
22977
+ credentialPreflight: parsePreflightMode(get("credential-preflight", "enforce")),
22978
+ createApiKey: parseCreateApiKey(get("create-api-key", "false")),
22979
+ serviceNotFoundPolicy: parseServiceNotFoundPolicy(get("service-not-found-policy", "fail")),
22641
22980
  pollTimeoutSeconds: clamp(rawTimeout, POLL_TIMEOUT_MIN, POLL_TIMEOUT_MAX, POLL_TIMEOUT_DEFAULT),
22642
22981
  pollIntervalSeconds: clamp(rawInterval, POLL_INTERVAL_MIN, POLL_INTERVAL_MAX, POLL_INTERVAL_DEFAULT),
22643
22982
  postmanRegion,
@@ -22663,6 +23002,7 @@ async function runOnboarding(inputs, client, sleepFn = sleep, reporter = core_ex
22663
23002
  const timeoutMs = inputs.pollTimeoutSeconds * 1e3;
22664
23003
  const intervalMs = inputs.pollIntervalSeconds * 1e3;
22665
23004
  const startTime = Date.now();
23005
+ const policy = inputs.serviceNotFoundPolicy ?? "fail";
22666
23006
  reporter.info(`Looking for discovered service matching "${inputs.clusterName ? `${inputs.clusterName}/` : ""}${inputs.projectName}"...`);
22667
23007
  let match = void 0;
22668
23008
  while (Date.now() - startTime < timeoutMs) {
@@ -22677,15 +23017,35 @@ async function runOnboarding(inputs, client, sleepFn = sleep, reporter = core_ex
22677
23017
  await sleepFn(intervalMs);
22678
23018
  }
22679
23019
  if (!match) {
22680
- reporter.warning(`Service "${inputs.projectName}" not found in discovered services after ${inputs.pollTimeoutSeconds}s`);
22681
- return {
22682
- discoveredServiceId: 0,
22683
- discoveredServiceName: "",
22684
- collectionId: "",
22685
- applicationId: "",
22686
- verificationToken: null,
22687
- status: "not-found"
22688
- };
23020
+ const message = `Service "${inputs.projectName}" not found in discovered services after ${inputs.pollTimeoutSeconds}s`;
23021
+ if (policy === "warn") {
23022
+ reporter.warning(message);
23023
+ return {
23024
+ discoveredServiceId: 0,
23025
+ discoveredServiceName: "",
23026
+ collectionId: "",
23027
+ applicationId: "",
23028
+ verificationToken: null,
23029
+ status: "not-found"
23030
+ };
23031
+ }
23032
+ throw new Error(`${message}. Full linking requires a discovered service (service-not-found-policy=fail).`);
23033
+ }
23034
+ const canonicalBase = match.canonicalIdentity ?? buildCanonicalServiceIdentity(match, inputs.projectName, inputs.clusterName || void 0);
23035
+ const providerServiceId = await client.resolveProviderServiceId(
23036
+ inputs.projectName,
23037
+ inputs.clusterName || void 0
23038
+ );
23039
+ if (!providerServiceId) {
23040
+ throw new Error(
23041
+ `Insights provider service "${canonicalBase.serviceName}" was not found. Full linking requires one exact canonical service identity.`
23042
+ );
23043
+ }
23044
+ const sysEnvId = inputs.systemEnvironmentId || match.systemEnvironmentId || "";
23045
+ if (!sysEnvId) {
23046
+ throw new Error(
23047
+ `No system environment id is available for "${canonicalBase.serviceName}"; refusing partial linking writes.`
23048
+ );
22689
23049
  }
22690
23050
  reporter.info(`Preparing collection for service ${match.id} in workspace ${inputs.workspaceId}...`);
22691
23051
  const collectionId = await client.prepareCollection(match.id, inputs.workspaceId);
@@ -22705,27 +23065,12 @@ async function runOnboarding(inputs, client, sleepFn = sleep, reporter = core_ex
22705
23065
  } else {
22706
23066
  reporter.info(`Skipping git onboarding for non-GitHub repo: ${repoUrl}`);
22707
23067
  }
22708
- const providerServiceId = await client.resolveProviderServiceId(
22709
- inputs.projectName,
22710
- inputs.clusterName || void 0
22711
- );
22712
- let applicationId = "";
22713
- if (providerServiceId) {
22714
- const sysEnvId = inputs.systemEnvironmentId || match.systemEnvironmentId || "";
22715
- if (sysEnvId) {
22716
- reporter.info(`Acknowledging Insights onboarding for ${providerServiceId}...`);
22717
- await client.acknowledgeOnboarding(providerServiceId, inputs.workspaceId, sysEnvId);
22718
- reporter.info(`Insights acknowledged: ${providerServiceId}`);
22719
- reporter.info(`Creating application binding for workspace ${inputs.workspaceId} with system_env ${sysEnvId}...`);
22720
- const appResult = await client.createApplication(inputs.workspaceId, sysEnvId);
22721
- applicationId = appResult.application_id;
22722
- reporter.info(`Application binding created: ${appResult.application_id} for service ${appResult.service_id}`);
22723
- } else {
22724
- reporter.warning("No systemEnvironmentId available; skipping Insights acknowledgment and application binding");
22725
- }
22726
- } else {
22727
- reporter.warning("Could not resolve Akita provider service ID; skipping acknowledgment and application binding");
22728
- }
23068
+ reporter.info(`Acknowledging Insights onboarding for ${providerServiceId}...`);
23069
+ await client.acknowledgeOnboarding(providerServiceId, inputs.workspaceId, sysEnvId);
23070
+ reporter.info(`Insights acknowledged: ${providerServiceId}`);
23071
+ reporter.info(`Creating application binding for workspace ${inputs.workspaceId} with system_env ${sysEnvId}...`);
23072
+ const appResult = await client.createApplication(inputs.workspaceId, sysEnvId, providerServiceId);
23073
+ reporter.info(`Application binding created: ${appResult.application_id} for service ${appResult.service_id}`);
22729
23074
  reporter.info(`Acknowledging workspace onboarding for ${inputs.workspaceId}...`);
22730
23075
  await client.acknowledgeWorkspace(inputs.workspaceId);
22731
23076
  reporter.info("Workspace onboarding acknowledged");
@@ -22741,9 +23086,13 @@ async function runOnboarding(inputs, client, sleepFn = sleep, reporter = core_ex
22741
23086
  discoveredServiceId: match.id,
22742
23087
  discoveredServiceName: match.name,
22743
23088
  collectionId,
22744
- applicationId,
23089
+ applicationId: appResult.application_id,
22745
23090
  verificationToken,
22746
- status: "success"
23091
+ status: "success",
23092
+ canonicalIdentity: {
23093
+ ...canonicalBase,
23094
+ ...providerServiceId ? { providerServiceId } : {}
23095
+ }
22747
23096
  };
22748
23097
  }
22749
23098
  async function resolveApiKeyAndTeamId(inputs, client, reporter = core_exports) {
@@ -22752,6 +23101,7 @@ async function resolveApiKeyAndTeamId(inputs, client, reporter = core_exports) {
22752
23101
  let keyValid = false;
22753
23102
  let pmakIdentity;
22754
23103
  const apiBase = inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE;
23104
+ const createApiKey = inputs.createApiKey === true;
22755
23105
  if (apiKey) {
22756
23106
  const result = await validateApiKey(apiKey, apiBase);
22757
23107
  keyValid = result.valid;
@@ -22762,49 +23112,36 @@ async function resolveApiKeyAndTeamId(inputs, client, reporter = core_exports) {
22762
23112
  }
22763
23113
  }
22764
23114
  if (!keyValid) {
22765
- reporter.info("Generating a new Postman API key via Bifrost identity service...");
22766
- const keyName = `insights-onboarding-action-${Date.now()}`;
23115
+ if (!createApiKey) {
23116
+ if (apiKey) {
23117
+ throw new Error(
23118
+ "postman-api-key is invalid or expired. Provide a valid key, or set create-api-key=true to opt in to durable Bifrost API-key creation."
23119
+ );
23120
+ }
23121
+ throw new Error(
23122
+ "postman-api-key is required for application binding. Provide a valid key, or set create-api-key=true to opt in to durable Bifrost API-key creation."
23123
+ );
23124
+ }
23125
+ reporter.info("create-api-key=true: generating a durable Postman API key via Bifrost identity service...");
23126
+ const keyName = `insights-onboarding-${inputs.projectName}`;
22767
23127
  apiKey = await client.createApiKey(keyName);
22768
23128
  reporter.setSecret(apiKey);
22769
23129
  client.setApiKey(apiKey);
22770
- reporter.info("New API key created successfully.");
22771
- }
22772
- let resolvedTeamId = teamId;
22773
- if (!resolvedTeamId && apiKey) {
22774
- try {
22775
- const teams = await getTeams(apiKey, apiBase);
22776
- if (teams.length > 1 && teams.every((t) => t.organizationId == null)) {
22777
- reporter.warning(
22778
- "GET /teams returned multiple teams but none include organizationId. Org-mode auto-detection may be degraded due to an upstream API change. Set postman-team-id explicitly if Bifrost calls fail."
22779
- );
22780
- }
22781
- const isOrgMode = teams.some((t) => t.organizationId != null);
22782
- if (isOrgMode) {
22783
- if (teams.length === 1) {
22784
- resolvedTeamId = String(teams[0].id);
22785
- reporter.info(
22786
- `Org-mode account detected. Using sub-team ${teams[0].id} (${teams[0].name ?? "unknown"}) for Bifrost calls.`
22787
- );
22788
- } else {
22789
- const meResult = await validateApiKey(apiKey, apiBase);
22790
- const meTeamId = meResult.teamId ? parseInt(meResult.teamId, 10) : NaN;
22791
- if (!Number.isNaN(meTeamId) && teams.some((t) => t.id === meTeamId)) {
22792
- resolvedTeamId = String(meTeamId);
22793
- reporter.info(
22794
- `Org-mode account detected. Using sub-team ${meTeamId} (from /me) for Bifrost calls.`
22795
- );
22796
- }
22797
- }
22798
- }
22799
- } catch {
23130
+ const createdIdentity = await validateApiKey(apiKey, apiBase);
23131
+ if (!createdIdentity.valid) {
23132
+ throw new Error("The explicitly created postman-api-key could not be validated; refusing linking writes.");
22800
23133
  }
23134
+ pmakIdentity = { source: "pmak/me", teamId: createdIdentity.teamId };
23135
+ reporter.info(`New API key created successfully (${keyName}).`);
22801
23136
  }
22802
- if (resolvedTeamId) {
22803
- reporter.info(`Using postman-team-id for Bifrost headers: ${resolvedTeamId}`);
23137
+ if (teamId) {
23138
+ reporter.info(`Using explicit postman-team-id for Bifrost headers: ${teamId}`);
22804
23139
  } else {
22805
- reporter.info("No postman-team-id resolved; omitting x-entity-team-id so Bifrost resolves team from the access token.");
23140
+ reporter.info(
23141
+ "No postman-team-id / POSTMAN_TEAM_ID provided; omitting x-entity-team-id so Bifrost resolves team from the access token."
23142
+ );
22806
23143
  }
22807
- return { apiKey, teamId: resolvedTeamId, pmakIdentity };
23144
+ return { apiKey, teamId, pmakIdentity };
22808
23145
  }
22809
23146
  async function runCredentialPreflightForInputs(inputs, pmak, reporter, fetchImpl, liveAccessToken) {
22810
23147
  const accessToken = liveAccessToken ?? inputs.postmanAccessToken;
@@ -22862,24 +23199,54 @@ async function runAction() {
22862
23199
  inputs.postmanTeamId,
22863
23200
  inputs.postmanApiKey
22864
23201
  );
22865
- const { apiKey, teamId, pmakIdentity } = await resolveApiKeyAndTeamId(inputs, preliminaryClient, core_exports);
22866
- const activeTokenProvider = apiKey !== inputs.postmanApiKey ? new AccessTokenProvider({
22867
- accessToken: tokenProvider.current(),
22868
- apiKey,
22869
- apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
22870
- onToken: (token) => setSecret(token)
22871
- }) : tokenProvider;
22872
23202
  const telemetry = createTelemetryContext({ action: "postman-insights-onboarding-action", actionVersion: resolveActionVersion2(), logger: core_exports });
22873
- telemetry.setTeamId(inputs.postmanTeamId || pmakIdentity?.teamId);
23203
+ telemetry.setTeamId(inputs.postmanTeamId);
22874
23204
  let result;
22875
23205
  try {
23206
+ let apiKey = inputs.postmanApiKey;
23207
+ let pmakIdentity;
23208
+ const apiBase = inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE;
23209
+ if (apiKey) {
23210
+ const validated = await validateApiKey(apiKey, apiBase);
23211
+ if (validated.valid) {
23212
+ pmakIdentity = { source: "pmak/me", teamId: validated.teamId };
23213
+ } else if (!inputs.createApiKey) {
23214
+ throw new Error(
23215
+ "postman-api-key is invalid or expired. Provide a valid key, or set create-api-key=true to opt in to durable Bifrost API-key creation."
23216
+ );
23217
+ } else {
23218
+ warning("Provided postman-api-key is invalid or expired.");
23219
+ }
23220
+ } else if (!inputs.createApiKey) {
23221
+ throw new Error(
23222
+ "postman-api-key is required for application binding. Provide a valid key, or set create-api-key=true to opt in to durable Bifrost API-key creation."
23223
+ );
23224
+ }
22876
23225
  await runCredentialPreflightForInputs(
22877
23226
  inputs,
22878
23227
  pmakIdentity,
22879
23228
  core_exports,
22880
23229
  void 0,
22881
- activeTokenProvider.current()
23230
+ tokenProvider.current()
22882
23231
  );
23232
+ const resolved = await resolveApiKeyAndTeamId(inputs, preliminaryClient, core_exports);
23233
+ apiKey = resolved.apiKey;
23234
+ const teamId = resolved.teamId;
23235
+ if (resolved.pmakIdentity?.teamId !== pmakIdentity?.teamId) {
23236
+ await runCredentialPreflightForInputs(
23237
+ inputs,
23238
+ resolved.pmakIdentity,
23239
+ core_exports,
23240
+ void 0,
23241
+ tokenProvider.current()
23242
+ );
23243
+ }
23244
+ const activeTokenProvider = apiKey !== inputs.postmanApiKey ? new AccessTokenProvider({
23245
+ accessToken: tokenProvider.current(),
23246
+ apiKey,
23247
+ apiBaseUrl: inputs.postmanApiBase || DEFAULT_POSTMAN_API_BASE,
23248
+ onToken: (token) => setSecret(token)
23249
+ }) : tokenProvider;
22883
23250
  const client = createInsightsBifrostClient(inputs, activeTokenProvider, teamId, apiKey);
22884
23251
  result = await runOnboarding(inputs, client, sleep, core_exports);
22885
23252
  } catch (error2) {