fix: surface permission sync issues requiring user action#1484
Conversation
WalkthroughPermission synchronization now persists classified account issues, clears cached permissions on permanent failures, exposes issue status through APIs, retries after reauthentication, and presents actionable banner and linked-account recovery states. ChangesPermission sync issue lifecycle
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant WebAuth
participant WorkerApi
participant PermissionSyncer
participant Database
participant PermissionSyncBanner
User->>WebAuth: reauthenticate linked account
WebAuth->>WorkerApi: request account permission sync
WorkerApi->>PermissionSyncer: start sync job
PermissionSyncer->>Database: record or clear permission-sync issue
PermissionSyncBanner->>Database: poll permission-sync status
Database-->>PermissionSyncBanner: issue or syncing status
PermissionSyncBanner-->>User: show recovery or progress banner
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This comment has been minimized.
This comment has been minimized.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)
64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winLog the underlying error before returning a generic failure.
The catch block discards the actual error (network failure, timeout, schema mismatch), unlike the equivalent scheduling path in
auth.tswhich logs it. This makes production failures hard to diagnose.♻️ Suggested fix
export const triggerAccountPermissionSync = async (accountId: string) => sew(() => withAuth(({ role }) => withMinimumOrgRole(role, OrgRole.MEMBER, async () => { try { return await requestAccountPermissionSync(accountId); - } catch { + } catch (error) { + logger.error(`Failed to trigger account permission sync for account ${accountId}: ${error instanceof Error ? error.message : String(error)}`); return unexpectedError('Failed to trigger account permission sync'); } }) ) );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/features/workerApi/actions.ts` around lines 64 - 74, Update the catch block in triggerAccountPermissionSync to capture the underlying error and log it before returning the existing generic unexpectedError response, matching the diagnostic behavior used by the equivalent scheduling path in auth.ts.packages/web/src/auth.ts (1)
228-240: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winConsider not awaiting the recovery sync inside
events.signIn.
requestAccountPermissionSyncis awaited directly in the sign-in event, which Auth.js awaits before completing the response — this can add up to the client's 5s timeout to sign-in latency for accounts with an existing permission issue if the worker is slow. Since this is a fire-and-forget scheduling call (errors are already caught/logged and don't affect sign-in outcome), consider not awaiting it so sign-in isn't delayed by worker availability.♻️ Suggested fix
if ( updatedAccount.permissionSyncIssue !== null && env.PERMISSION_SYNC_ENABLED === 'true' ) { - try { - if (await hasEntitlement('permission-syncing')) { - await requestAccountPermissionSync(updatedAccount.id); - } - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - logger.error(`Failed to schedule permission sync after reauthentication for account ${updatedAccount.id}: ${message}`); - } + hasEntitlement('permission-syncing') + .then((entitled) => entitled ? requestAccountPermissionSync(updatedAccount.id) : undefined) + .catch((error) => { + const message = error instanceof Error ? error.message : String(error); + logger.error(`Failed to schedule permission sync after reauthentication for account ${updatedAccount.id}: ${message}`); + }); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/auth.ts` around lines 228 - 240, Update the recovery sync block in the events.signIn flow to invoke requestAccountPermissionSync without awaiting its completion, while retaining the existing error capture and logger.error handling so failures remain logged without delaying sign-in.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/backend/src/ee/accountPermissionSyncer.ts`:
- Around line 259-273: Update the fail-closed cleanup warning in the account
permission sync flow to remove account.user.email from the log message,
retaining the account.id and existing cleanup details and error message. Do not
alter the transaction or cleanup behavior.
---
Nitpick comments:
In `@packages/web/src/auth.ts`:
- Around line 228-240: Update the recovery sync block in the events.signIn flow
to invoke requestAccountPermissionSync without awaiting its completion, while
retaining the existing error capture and logger.error handling so failures
remain logged without delaying sign-in.
In `@packages/web/src/features/workerApi/actions.ts`:
- Around line 64-74: Update the catch block in triggerAccountPermissionSync to
capture the underlying error and log it before returning the existing generic
unexpectedError response, matching the diagnostic behavior used by the
equivalent scheduling path in auth.ts.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 99b97fda-b5b7-47a9-a62e-c231dc3cc2ad
📒 Files selected for processing (19)
CHANGELOG.mdpackages/backend/src/ee/accountPermissionSyncer.test.tspackages/backend/src/ee/accountPermissionSyncer.tspackages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sqlpackages/db/prisma/schema.prismapackages/web/src/app/(app)/components/banners/bannerResolver.test.tspackages/web/src/app/(app)/components/banners/bannerResolver.tsxpackages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsxpackages/web/src/app/(app)/components/banners/permissionSyncBanner.tsxpackages/web/src/app/(app)/layout.tsxpackages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.tspackages/web/src/app/api/(server)/ee/permissionSyncStatus/api.tspackages/web/src/auth.tspackages/web/src/ee/features/sso/actions.tspackages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsxpackages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsxpackages/web/src/features/workerApi/actions.tspackages/web/src/features/workerApi/client.server.test.tspackages/web/src/features/workerApi/client.server.ts
a985fac to
3cc17b8
Compare
2c03c15 to
5873631
Compare
3cc17b8 to
515ad7e
Compare
5873631 to
a962821
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a962821. Configure here.

Stack created with GitHub Stacks CLI
Fixes SOU-1560
Fixes SOU-1177
Summary
Testing
yarn workspace @sourcebot/backend test --run(201 tests)yarn workspace @sourcebot/web test --run(1,095 tests)Part of stack #1483. Depends on #1482.
Note
Medium Risk
Changes how repository access is represented and communicated after permanent sync failures (security-sensitive), plus a DB migration and auth-time sync scheduling, but behavior is scoped to classified fail-closed cases with tests.
Overview
When permission sync fails closed and clears cached repo access, the backend now persists a structured
permissionSyncIssueon the account (REAUTHENTICATION_REQUIREDorINSUFFICIENT_SCOPE) in the same transaction as the permission wipe, and clears it only after a successful sync completes.The web app surfaces this through a non-dismissible permission-sync banner (action required vs. still syncing), enriches
getPermissionSyncStatuswith per-account issues, and updates linked accounts to show “needs attention” with reconnect/reauthorize instead of “refresh permissions.” OAuth reauthentication schedules an automatic permission-sync retry via a shared worker client; manual refresh polling now keys off full job status (including failed toasts).Linked-account UX no longer drives recovery from
tokenRefreshErrorMessage; transient refresh failures stay out of the reconnect flow.Reviewed by Cursor Bugbot for commit a962821. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation