chore: improve monitoring for fix: handle stale API key role cache gracefully in

**Monitoring fix in `permission-graphql-api-exception-handler.util.ts`:** Moved `API_KEY_ROLE_NOT_FOUND` and `APPLICATION_ROLE_NOT_FOUND` from the raw re-throw group (line 74) to a new `ForbiddenError` mapping. This ensures these exceptions are converted to proper GraphQL errors before reaching the client, matching the pattern used for similar auth/permission errors (e.g., `PERMISSION_DENIED`, `NO_AUTHENTICATION_CONTEXT`).

Previously, these two codes fell through to `throw error` which propagated the raw `PermissionsException` up the stack, causing Sentry to capture it as an unhandled error. Now they're wrapped as `ForbiddenError` GraphQL responses, which:
1. Return a clean, structured error to the API consumer
2. Prevent unnecessary Sentry noise since `ForbiddenError` is a handled GraphQL error type
3. Are consistent with how `API_KEY_NO_ROLE_ASSIGNED` is handled in `api-key-graphql-api-exception-handler.util.ts`
This commit is contained in:
Sonarly Claude Code
2026-04-06 18:25:37 +00:00
parent 431b197d05
commit 70e22ce10b
@@ -51,6 +51,9 @@ export const permissionGraphqlApiExceptionHandler = (
case PermissionsExceptionCode.FIELD_PERMISSION_NOT_FOUND:
case PermissionsExceptionCode.PERMISSION_NOT_FOUND:
throw new NotFoundError(error);
case PermissionsExceptionCode.API_KEY_ROLE_NOT_FOUND:
case PermissionsExceptionCode.APPLICATION_ROLE_NOT_FOUND:
throw new ForbiddenError(error);
case PermissionsExceptionCode.UPSERT_FIELD_PERMISSION_FAILED:
case PermissionsExceptionCode.DEFAULT_ROLE_NOT_FOUND:
case PermissionsExceptionCode.WORKSPACE_ID_ROLE_USER_WORKSPACE_MISMATCH:
@@ -66,11 +69,9 @@ export const permissionGraphqlApiExceptionHandler = (
case PermissionsExceptionCode.METHOD_NOT_ALLOWED:
case PermissionsExceptionCode.RAW_SQL_NOT_ALLOWED:
case PermissionsExceptionCode.OBJECT_PERMISSION_NOT_FOUND:
case PermissionsExceptionCode.API_KEY_ROLE_NOT_FOUND:
case PermissionsExceptionCode.JOIN_COLUMN_NAME_REQUIRED:
case PermissionsExceptionCode.COMPOSITE_TYPE_NOT_FOUND:
case PermissionsExceptionCode.USER_WORKSPACE_NOT_FOUND:
case PermissionsExceptionCode.APPLICATION_ROLE_NOT_FOUND:
throw error;
default: {
return assertUnreachable(error.code);