@mondaydotcomorg/monday-authorization 3.5.0 → 3.5.1-debug-getprofile-not-resolving-to-internal-ba14ff5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA4CnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAwCZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAiFnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
@@ -17,7 +17,6 @@ const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
17
17
  const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
18
18
  const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
19
19
  const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
20
- const NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF = 'navigate-can-action-in-scope-to-graph';
21
20
  function setRequestFetchOptions(customMondayFetchOptions) {
22
21
  authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
23
22
  }
@@ -96,46 +95,88 @@ class AuthorizationService {
96
95
  authorizationInternalService.logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
97
96
  throw new Error('AuthorizationService: igniteClient is not set, failing request');
98
97
  }
99
- if (this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []).includes(appName)) {
100
- return attributionsService.getProfile();
98
+ const allowedApps = this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []);
99
+ const inReleaseApps = this.igniteClient.configuration.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, []);
100
+ const isInAllowedApps = allowedApps.includes(appName);
101
+ const isInReleaseApps = inReleaseApps.includes(appName);
102
+ const isFeatureFlagReleased = this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId });
103
+ const debugInfo = {
104
+ appName,
105
+ allowedApps,
106
+ inReleaseApps,
107
+ isInAllowedApps,
108
+ isInReleaseApps,
109
+ isFeatureFlagReleased,
110
+ accountId,
111
+ userId,
112
+ };
113
+ authorizationInternalService.logger.info({ tag: 'authorization-service', ...debugInfo }, 'AuthorizationService.getProfile debug info');
114
+ if (isInAllowedApps) {
115
+ const profile = attributionsService.getProfile();
116
+ authorizationInternalService.logger.info({ tag: 'authorization-service', profile }, 'Returning profile from ALLOWED_SDK_PLATFORM_PROFILES_KEY');
117
+ return profile;
101
118
  }
102
- if (this.igniteClient.configuration
103
- .getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
104
- .includes(appName) &&
105
- this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
106
- return attributionsService.getProfile();
119
+ if (isInReleaseApps && isFeatureFlagReleased) {
120
+ const profile = attributionsService.getProfile();
121
+ authorizationInternalService.logger.info({ tag: 'authorization-service', profile }, 'Returning profile from IN_RELEASE_SDK_PLATFORM_PROFILES_KEY');
122
+ return profile;
107
123
  }
124
+ authorizationInternalService.logger.info({ tag: 'authorization-service', profile: attributionsService.PlatformProfile.APP }, 'Returning default PlatformProfile.APP');
108
125
  return attributionsService.PlatformProfile.APP;
109
126
  }
110
127
  static async canActionInScopeMultiple(accountId, userId, scopedActions) {
111
128
  if (scopedActions.length === 0) {
112
129
  return [];
113
130
  }
114
- const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
115
131
  const startTime = perf_hooks.performance.now();
116
- let scopedActionResponseObjects;
117
- let apiType;
118
- if (shouldNavigateToGraph) {
119
- apiType = 'graph';
120
- scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
121
- }
122
- else {
123
- apiType = 'platform';
124
- const profile = this.getProfile(accountId, userId);
125
- const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
126
- scopedActionResponseObjects = await this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
127
- }
132
+ // Always call both APIs for comparison
133
+ const graphApiPromise = this.graphApi.checkPermissions(accountId, userId, scopedActions);
134
+ const profile = this.getProfile(accountId, userId);
135
+ const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
136
+ const platformApiPromise = this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
137
+ const [graphApiResponse, platformApiResponse] = await Promise.all([graphApiPromise, platformApiPromise]);
128
138
  const endTime = perf_hooks.performance.now();
129
139
  const time = endTime - startTime;
130
- // Record metrics for each authorization check
131
- for (const obj of scopedActionResponseObjects) {
140
+ // Compare responses and log differences
141
+ const differences = [];
142
+ for (let i = 0; i < scopedActions.length; i++) {
143
+ const graphResult = graphApiResponse[i];
144
+ const platformResult = platformApiResponse[i];
145
+ const graphCan = graphResult?.permit?.can;
146
+ const platformCan = platformResult?.permit?.can;
147
+ if (graphCan !== platformCan) {
148
+ differences.push({
149
+ action: scopedActions[i].action,
150
+ scope: scopedActions[i].scope,
151
+ graphResult: graphResult?.permit,
152
+ platformResult: platformResult?.permit,
153
+ });
154
+ }
155
+ }
156
+ const isSame = differences.length === 0;
157
+ authorizationInternalService.logger.info({
158
+ tag: 'authorization-service-api-comparison',
159
+ accountId,
160
+ userId,
161
+ profile,
162
+ scopedActionsCount: scopedActions.length,
163
+ isSame,
164
+ differencesCount: differences.length,
165
+ differences: differences.length > 0 ? differences : undefined,
166
+ graphApiResponse,
167
+ platformApiResponse,
168
+ timeMs: time,
169
+ }, `API comparison: graphApi vs platformApi - ${isSame ? 'SAME' : 'DIFFERENT'}`);
170
+ // Record metrics for each authorization check (using platform response)
171
+ for (const obj of platformApiResponse) {
132
172
  const { action, scope } = obj.scopedAction;
133
173
  const { resourceType } = utils_authorization_utils.scopeToResource(scope);
134
174
  const isAuthorized = obj.permit.can;
135
175
  prometheusService.sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
136
- metricsService.recordAuthorizationTiming(apiType, time, 'canActionInScopeMultiple');
176
+ metricsService.recordAuthorizationTiming('platform', time, 'canActionInScopeMultiple');
137
177
  }
138
- return scopedActionResponseObjects;
178
+ // Return platform API response
179
+ return platformApiResponse;
139
180
  }
140
181
  static async isAuthorizedSingular(accountId, userId, resources, action) {
141
182
  const { authorizationObjects } = createAuthorizationParams(resources, action);
@@ -1 +1 @@
1
- {"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AAQlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;;IAezC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgCzG;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAMxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
1
+ {"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AAQlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;;IAezC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAiCzG;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAMxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
@@ -65,6 +65,7 @@ class GraphApi {
65
65
  url: {
66
66
  appName: constants.GRAPH_APP_NAME,
67
67
  path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
68
+ profile: constants.GraphApiProfile.PERMISSION,
68
69
  },
69
70
  method: 'POST',
70
71
  headers: {
@@ -2,6 +2,9 @@ import { RecursivePartial } from '@mondaydotcomorg/monday-fetch-api';
2
2
  import { FetcherConfig } from '@mondaydotcomorg/trident-backend-api';
3
3
  export declare const APP_NAME = "authorization";
4
4
  export declare const GRAPH_APP_NAME = "authorization-graph";
5
+ export declare enum GraphApiProfile {
6
+ PERMISSION = "authorization-graph-permission"
7
+ }
5
8
  export declare const ERROR_MESSAGES: {
6
9
  readonly HTTP_CLIENT_NOT_INITIALIZED: "MondayAuthorization: HTTP client is not initialized";
7
10
  readonly REQUEST_FAILED: (method: string, status: number, reason: string) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,oBAAY,eAAe;IACzB,UAAU,mCAAmC;CAC9C;AAED,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
package/dist/constants.js CHANGED
@@ -2,6 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const APP_NAME = 'authorization';
4
4
  const GRAPH_APP_NAME = 'authorization-graph';
5
+ exports.GraphApiProfile = void 0;
6
+ (function (GraphApiProfile) {
7
+ GraphApiProfile["PERMISSION"] = "authorization-graph-permission";
8
+ })(exports.GraphApiProfile || (exports.GraphApiProfile = {}));
5
9
  const ERROR_MESSAGES = {
6
10
  HTTP_CLIENT_NOT_INITIALIZED: 'MondayAuthorization: HTTP client is not initialized',
7
11
  REQUEST_FAILED: (method, status, reason) => `MondayAuthorization: [${method}] request failed with status ${status} with reason: ${reason}`,
@@ -1 +1 @@
1
- {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA4CnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAwCZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAiFnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
@@ -15,7 +15,6 @@ const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
15
15
  const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
16
16
  const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
17
17
  const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
18
- const NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF = 'navigate-can-action-in-scope-to-graph';
19
18
  function setRequestFetchOptions(customMondayFetchOptions) {
20
19
  AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
21
20
  }
@@ -94,46 +93,88 @@ class AuthorizationService {
94
93
  logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
95
94
  throw new Error('AuthorizationService: igniteClient is not set, failing request');
96
95
  }
97
- if (this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []).includes(appName)) {
98
- return getProfile();
96
+ const allowedApps = this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []);
97
+ const inReleaseApps = this.igniteClient.configuration.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, []);
98
+ const isInAllowedApps = allowedApps.includes(appName);
99
+ const isInReleaseApps = inReleaseApps.includes(appName);
100
+ const isFeatureFlagReleased = this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId });
101
+ const debugInfo = {
102
+ appName,
103
+ allowedApps,
104
+ inReleaseApps,
105
+ isInAllowedApps,
106
+ isInReleaseApps,
107
+ isFeatureFlagReleased,
108
+ accountId,
109
+ userId,
110
+ };
111
+ logger.info({ tag: 'authorization-service', ...debugInfo }, 'AuthorizationService.getProfile debug info');
112
+ if (isInAllowedApps) {
113
+ const profile = getProfile();
114
+ logger.info({ tag: 'authorization-service', profile }, 'Returning profile from ALLOWED_SDK_PLATFORM_PROFILES_KEY');
115
+ return profile;
99
116
  }
100
- if (this.igniteClient.configuration
101
- .getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
102
- .includes(appName) &&
103
- this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
104
- return getProfile();
117
+ if (isInReleaseApps && isFeatureFlagReleased) {
118
+ const profile = getProfile();
119
+ logger.info({ tag: 'authorization-service', profile }, 'Returning profile from IN_RELEASE_SDK_PLATFORM_PROFILES_KEY');
120
+ return profile;
105
121
  }
122
+ logger.info({ tag: 'authorization-service', profile: PlatformProfile.APP }, 'Returning default PlatformProfile.APP');
106
123
  return PlatformProfile.APP;
107
124
  }
108
125
  static async canActionInScopeMultiple(accountId, userId, scopedActions) {
109
126
  if (scopedActions.length === 0) {
110
127
  return [];
111
128
  }
112
- const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
113
129
  const startTime = performance.now();
114
- let scopedActionResponseObjects;
115
- let apiType;
116
- if (shouldNavigateToGraph) {
117
- apiType = 'graph';
118
- scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
119
- }
120
- else {
121
- apiType = 'platform';
122
- const profile = this.getProfile(accountId, userId);
123
- const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
124
- scopedActionResponseObjects = await this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
125
- }
130
+ // Always call both APIs for comparison
131
+ const graphApiPromise = this.graphApi.checkPermissions(accountId, userId, scopedActions);
132
+ const profile = this.getProfile(accountId, userId);
133
+ const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
134
+ const platformApiPromise = this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
135
+ const [graphApiResponse, platformApiResponse] = await Promise.all([graphApiPromise, platformApiPromise]);
126
136
  const endTime = performance.now();
127
137
  const time = endTime - startTime;
128
- // Record metrics for each authorization check
129
- for (const obj of scopedActionResponseObjects) {
138
+ // Compare responses and log differences
139
+ const differences = [];
140
+ for (let i = 0; i < scopedActions.length; i++) {
141
+ const graphResult = graphApiResponse[i];
142
+ const platformResult = platformApiResponse[i];
143
+ const graphCan = graphResult?.permit?.can;
144
+ const platformCan = platformResult?.permit?.can;
145
+ if (graphCan !== platformCan) {
146
+ differences.push({
147
+ action: scopedActions[i].action,
148
+ scope: scopedActions[i].scope,
149
+ graphResult: graphResult?.permit,
150
+ platformResult: platformResult?.permit,
151
+ });
152
+ }
153
+ }
154
+ const isSame = differences.length === 0;
155
+ logger.info({
156
+ tag: 'authorization-service-api-comparison',
157
+ accountId,
158
+ userId,
159
+ profile,
160
+ scopedActionsCount: scopedActions.length,
161
+ isSame,
162
+ differencesCount: differences.length,
163
+ differences: differences.length > 0 ? differences : undefined,
164
+ graphApiResponse,
165
+ platformApiResponse,
166
+ timeMs: time,
167
+ }, `API comparison: graphApi vs platformApi - ${isSame ? 'SAME' : 'DIFFERENT'}`);
168
+ // Record metrics for each authorization check (using platform response)
169
+ for (const obj of platformApiResponse) {
130
170
  const { action, scope } = obj.scopedAction;
131
171
  const { resourceType } = scopeToResource(scope);
132
172
  const isAuthorized = obj.permit.can;
133
173
  sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
134
- recordAuthorizationTiming(apiType, time, 'canActionInScopeMultiple');
174
+ recordAuthorizationTiming('platform', time, 'canActionInScopeMultiple');
135
175
  }
136
- return scopedActionResponseObjects;
176
+ // Return platform API response
177
+ return platformApiResponse;
137
178
  }
138
179
  static async isAuthorizedSingular(accountId, userId, resources, action) {
139
180
  const { authorizationObjects } = createAuthorizationParams(resources, action);
@@ -1 +1 @@
1
- {"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AAQlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;;IAezC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgCzG;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAMxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
1
+ {"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AAQlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;;IAezC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAiCzG;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAMxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
@@ -4,7 +4,7 @@ import { PermitTechnicalReason } from '../types/scoped-actions-contracts.mjs';
4
4
  import { AuthorizationInternalService } from '../authorization-internal-service.mjs';
5
5
  import { getAttributionsFromApi } from '../attributions-service.mjs';
6
6
  import { scopeToResource } from '../utils/authorization.utils.mjs';
7
- import { GRAPH_APP_NAME } from '../constants.mjs';
7
+ import { GRAPH_APP_NAME, GraphApiProfile } from '../constants.mjs';
8
8
  import { handleApiError } from '../utils/api-error-handler.mjs';
9
9
 
10
10
  const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
@@ -63,6 +63,7 @@ class GraphApi {
63
63
  url: {
64
64
  appName: GRAPH_APP_NAME,
65
65
  path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
66
+ profile: GraphApiProfile.PERMISSION,
66
67
  },
67
68
  method: 'POST',
68
69
  headers: {
@@ -2,6 +2,9 @@ import { RecursivePartial } from '@mondaydotcomorg/monday-fetch-api';
2
2
  import { FetcherConfig } from '@mondaydotcomorg/trident-backend-api';
3
3
  export declare const APP_NAME = "authorization";
4
4
  export declare const GRAPH_APP_NAME = "authorization-graph";
5
+ export declare enum GraphApiProfile {
6
+ PERMISSION = "authorization-graph-permission"
7
+ }
5
8
  export declare const ERROR_MESSAGES: {
6
9
  readonly HTTP_CLIENT_NOT_INITIALIZED: "MondayAuthorization: HTTP client is not initialized";
7
10
  readonly REQUEST_FAILED: (method: string, status: number, reason: string) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,oBAAY,eAAe;IACzB,UAAU,mCAAmC;CAC9C;AAED,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
@@ -1,5 +1,9 @@
1
1
  const APP_NAME = 'authorization';
2
2
  const GRAPH_APP_NAME = 'authorization-graph';
3
+ var GraphApiProfile;
4
+ (function (GraphApiProfile) {
5
+ GraphApiProfile["PERMISSION"] = "authorization-graph-permission";
6
+ })(GraphApiProfile || (GraphApiProfile = {}));
3
7
  const ERROR_MESSAGES = {
4
8
  HTTP_CLIENT_NOT_INITIALIZED: 'MondayAuthorization: HTTP client is not initialized',
5
9
  REQUEST_FAILED: (method, status, reason) => `MondayAuthorization: [${method}] request failed with status ${status} with reason: ${reason}`,
@@ -16,4 +20,4 @@ const DEFAULT_FETCH_OPTIONS = {
16
20
  },
17
21
  };
18
22
 
19
- export { APP_NAME, DEFAULT_FETCH_OPTIONS, ERROR_MESSAGES, GRAPH_APP_NAME };
23
+ export { APP_NAME, DEFAULT_FETCH_OPTIONS, ERROR_MESSAGES, GRAPH_APP_NAME, GraphApiProfile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mondaydotcomorg/monday-authorization",
3
- "version": "3.5.0",
3
+ "version": "3.5.1-debug-getprofile-not-resolving-to-internal-ba14ff5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "BSD-3-Clause",
@@ -155,19 +155,37 @@ export class AuthorizationService {
155
155
  logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
156
156
  throw new Error('AuthorizationService: igniteClient is not set, failing request');
157
157
  }
158
- if (
159
- this.igniteClient.configuration.getObjectValue<string[]>(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []).includes(appName)
160
- ) {
161
- return getProfile();
158
+
159
+ const allowedApps = this.igniteClient.configuration.getObjectValue<string[]>(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []);
160
+ const inReleaseApps = this.igniteClient.configuration.getObjectValue<string[]>(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, []);
161
+ const isInAllowedApps = allowedApps.includes(appName);
162
+ const isInReleaseApps = inReleaseApps.includes(appName);
163
+ const isFeatureFlagReleased = this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId });
164
+
165
+ const debugInfo = {
166
+ appName,
167
+ allowedApps,
168
+ inReleaseApps,
169
+ isInAllowedApps,
170
+ isInReleaseApps,
171
+ isFeatureFlagReleased,
172
+ accountId,
173
+ userId,
174
+ };
175
+
176
+ logger.info({ tag: 'authorization-service', ...debugInfo }, 'AuthorizationService.getProfile debug info');
177
+
178
+ if (isInAllowedApps) {
179
+ const profile = getProfile();
180
+ logger.info({ tag: 'authorization-service', profile }, 'Returning profile from ALLOWED_SDK_PLATFORM_PROFILES_KEY');
181
+ return profile;
162
182
  }
163
- if (
164
- this.igniteClient.configuration
165
- .getObjectValue<string[]>(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
166
- .includes(appName) &&
167
- this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })
168
- ) {
169
- return getProfile();
183
+ if (isInReleaseApps && isFeatureFlagReleased) {
184
+ const profile = getProfile();
185
+ logger.info({ tag: 'authorization-service', profile }, 'Returning profile from IN_RELEASE_SDK_PLATFORM_PROFILES_KEY');
186
+ return profile;
170
187
  }
188
+ logger.info({ tag: 'authorization-service', profile: PlatformProfile.APP }, 'Returning default PlatformProfile.APP');
171
189
  return PlatformProfile.APP;
172
190
  }
173
191
 
@@ -180,43 +198,80 @@ export class AuthorizationService {
180
198
  return [];
181
199
  }
182
200
 
183
- const shouldNavigateToGraph = Boolean(
184
- this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId })
185
- );
186
-
187
201
  const startTime = performance.now();
188
- let scopedActionResponseObjects: ScopedActionResponseObject[];
189
- let apiType: 'graph' | 'platform';
190
202
 
191
- if (shouldNavigateToGraph) {
192
- apiType = 'graph';
193
- scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
194
- } else {
195
- apiType = 'platform';
196
- const profile = this.getProfile(accountId, userId);
197
- const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
203
+ // Always call both APIs for comparison
204
+ const graphApiPromise = this.graphApi.checkPermissions(accountId, userId, scopedActions);
198
205
 
199
- scopedActionResponseObjects = await this.platformApi.checkPermissions(
200
- profile,
201
- internalAuthToken,
202
- userId,
203
- scopedActions
204
- );
205
- }
206
+ const profile = this.getProfile(accountId, userId);
207
+ const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
208
+ const platformApiPromise = this.platformApi.checkPermissions(
209
+ profile,
210
+ internalAuthToken,
211
+ userId,
212
+ scopedActions
213
+ );
214
+
215
+ const [graphApiResponse, platformApiResponse] = await Promise.all([graphApiPromise, platformApiPromise]);
206
216
 
207
217
  const endTime = performance.now();
208
218
  const time = endTime - startTime;
209
219
 
210
- // Record metrics for each authorization check
211
- for (const obj of scopedActionResponseObjects) {
220
+ // Compare responses and log differences
221
+ const differences: Array<{
222
+ action: string;
223
+ scope: ScopeOptions;
224
+ graphResult: ScopedActionPermit;
225
+ platformResult: ScopedActionPermit;
226
+ }> = [];
227
+
228
+ for (let i = 0; i < scopedActions.length; i++) {
229
+ const graphResult = graphApiResponse[i];
230
+ const platformResult = platformApiResponse[i];
231
+
232
+ const graphCan = graphResult?.permit?.can;
233
+ const platformCan = platformResult?.permit?.can;
234
+
235
+ if (graphCan !== platformCan) {
236
+ differences.push({
237
+ action: scopedActions[i].action,
238
+ scope: scopedActions[i].scope,
239
+ graphResult: graphResult?.permit,
240
+ platformResult: platformResult?.permit,
241
+ });
242
+ }
243
+ }
244
+
245
+ const isSame = differences.length === 0;
246
+
247
+ logger.info(
248
+ {
249
+ tag: 'authorization-service-api-comparison',
250
+ accountId,
251
+ userId,
252
+ profile,
253
+ scopedActionsCount: scopedActions.length,
254
+ isSame,
255
+ differencesCount: differences.length,
256
+ differences: differences.length > 0 ? differences : undefined,
257
+ graphApiResponse,
258
+ platformApiResponse,
259
+ timeMs: time,
260
+ },
261
+ `API comparison: graphApi vs platformApi - ${isSame ? 'SAME' : 'DIFFERENT'}`
262
+ );
263
+
264
+ // Record metrics for each authorization check (using platform response)
265
+ for (const obj of platformApiResponse) {
212
266
  const { action, scope } = obj.scopedAction;
213
267
  const { resourceType } = scopeToResource(scope);
214
268
  const isAuthorized = obj.permit.can;
215
269
  sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
216
- recordAuthorizationTiming(apiType, time, 'canActionInScopeMultiple');
270
+ recordAuthorizationTiming('platform', time, 'canActionInScopeMultiple');
217
271
  }
218
272
 
219
- return scopedActionResponseObjects;
273
+ // Return platform API response
274
+ return platformApiResponse;
220
275
  }
221
276
 
222
277
  private static async isAuthorizedSingular(
@@ -18,7 +18,7 @@ import {
18
18
  GraphPermissionReason,
19
19
  } from '../types/graph-api.types';
20
20
  import { scopeToResource } from '../utils/authorization.utils';
21
- import { GRAPH_APP_NAME } from '../constants';
21
+ import { GRAPH_APP_NAME, GraphApiProfile } from '../constants';
22
22
  import { handleApiError } from '../utils/api-error-handler';
23
23
 
24
24
  const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
@@ -85,6 +85,7 @@ export class GraphApi {
85
85
  url: {
86
86
  appName: GRAPH_APP_NAME,
87
87
  path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
88
+ profile: GraphApiProfile.PERMISSION,
88
89
  },
89
90
  method: 'POST',
90
91
  headers: {
package/src/constants.ts CHANGED
@@ -4,6 +4,10 @@ import { FetcherConfig } from '@mondaydotcomorg/trident-backend-api';
4
4
  export const APP_NAME = 'authorization';
5
5
  export const GRAPH_APP_NAME = 'authorization-graph';
6
6
 
7
+ export enum GraphApiProfile {
8
+ PERMISSION = 'authorization-graph-permission',
9
+ }
10
+
7
11
  export const ERROR_MESSAGES = {
8
12
  HTTP_CLIENT_NOT_INITIALIZED: 'MondayAuthorization: HTTP client is not initialized',
9
13
  REQUEST_FAILED: (method: string, status: number, reason: string) =>