fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: surface permission sync issues requiring user action - #1484

Merged
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux
Jul 23, 2026
Merged

fix: surface permission sync issues requiring user action#1484
brendan-kellam merged 5 commits into
brendan/classify-permission-sync-errorsfrom
brendan/permission-sync-action-required-ux

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLI

Fixes SOU-1560
Fixes SOU-1177

imageimageimage

Summary

  • persist a structured account issue when permission sync fails closed
  • clear the issue only after permissions sync successfully
  • show a persistent action-required banner and unhealthy linked-account state
  • schedule permission recovery immediately after OAuth reauthentication
  • stop treating transient token refresh errors as reconnect-required UX

Testing

  • yarn workspace @sourcebot/backend test --run (201 tests)
  • yarn workspace @sourcebot/web test --run (1,095 tests)
  • backend and database package builds
  • Prisma schema validation
  • ESLint on touched web files

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 permissionSyncIssue on the account (REAUTHENTICATION_REQUIRED or INSUFFICIENT_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 getPermissionSyncStatus with 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

    • Added clear warnings when permission synchronization requires reauthentication or additional access.
    • Added guided recovery through linked-account settings, including reconnect and permission-review actions.
    • Permission sync status now updates automatically and clears after successful recovery.
    • Successful reauthentication can automatically retry permission synchronization.
  • Bug Fixes

    • Improved handling of permanent versus temporary synchronization failures.
    • Prevented stale repository access from remaining available after permanent permission failures.
  • Documentation

    • Updated the unreleased changelog with the new warnings and recovery guidance.

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Permission 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.

Changes

Permission sync issue lifecycle

Layer / File(s)Summary
Persist and classify sync issues
packages/db/prisma/schema.prisma, packages/db/prisma/migrations/..., packages/backend/src/ee/accountPermissionSyncer.ts, packages/backend/src/ee/accountPermissionSyncer.test.ts
Adds issue enum and account fields; classified failures transactionally clear cached permissions and record issue metadata, while successful syncs clear it.
Expose status and trigger recovery
packages/web/src/app/api/(server)/ee/permissionSyncStatus/*, packages/web/src/features/workerApi/*, packages/web/src/auth.ts
Returns structured account issues, centralizes worker requests, and schedules permission sync after reauthentication.
Render permission-sync banners
packages/web/src/app/(app)/components/banners/*, packages/web/src/app/(app)/layout.tsx
Passes issue status into the banner, which displays syncing or recovery guidance and refreshes when issues resolve.
Show linked-account recovery actions
packages/web/src/ee/features/sso/actions.ts, packages/web/src/ee/features/sso/components/linkedAccountProviderCard.*
Replaces token-refresh error state with permission-sync issue state and renders reconnect or scope guidance.
Document the behavior
CHANGELOG.md
Adds an Unreleased changelog entry for action-required warnings and guided recovery.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: surfacing permission sync issues that require user action.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/permission-sync-action-required-ux

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

This comment has been minimized.

@brendan-kellambrendan-kellam changed the title brendan/permission sync action required uxfix: surface permission sync issues requiring user actionJul 22, 2026
Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam

Copy link
Copy Markdown
ContributorAuthor

@coderabbitai review

@coderabbitai

coderabbitaiBot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/web/src/features/workerApi/actions.ts (1)

64-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log 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.ts which 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 win

Consider not awaiting the recovery sync inside events.signIn.

requestAccountPermissionSync is 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

📥 Commits

Reviewing files that changed from the base of the PR and between a985fac and 2c03c15.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • packages/backend/src/ee/accountPermissionSyncer.test.ts
  • packages/backend/src/ee/accountPermissionSyncer.ts
  • packages/db/prisma/migrations/20260722144824_add_account_permission_sync_issue/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/web/src/app/(app)/components/banners/bannerResolver.test.ts
  • packages/web/src/app/(app)/components/banners/bannerResolver.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.test.tsx
  • packages/web/src/app/(app)/components/banners/permissionSyncBanner.tsx
  • packages/web/src/app/(app)/layout.tsx
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.test.ts
  • packages/web/src/app/api/(server)/ee/permissionSyncStatus/api.ts
  • packages/web/src/auth.ts
  • packages/web/src/ee/features/sso/actions.ts
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.test.tsx
  • packages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsx
  • packages/web/src/features/workerApi/actions.ts
  • packages/web/src/features/workerApi/client.server.test.ts
  • packages/web/src/features/workerApi/client.server.ts

Comment threadpackages/backend/src/ee/accountPermissionSyncer.ts
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 2c03c15 to 5873631CompareJuly 23, 2026 18:02
@brendan-kellam
brendan-kellamforce-pushed the brendan/permission-sync-action-required-ux branch from 5873631 to a962821CompareJuly 23, 2026 20:01

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

@brendan-kellam
brendan-kellam merged commit afe1994 into mainJul 23, 2026
16 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/permission-sync-action-required-ux branch July 23, 2026 20:28
@github-actionsgithub-actionsBot mentioned this pull request Jul 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@brendan-kellam@msukkari