Skip to content

fix(account): enforce unique GitHub links - #2829

Open
WcaleNieWolny wants to merge 8 commits into
mainfrom
wolny/unique-github-account-link
Open

fix(account): enforce unique GitHub links#2829
WcaleNieWolny wants to merge 8 commits into
mainfrom
wolny/unique-github-account-link

Conversation

@WcaleNieWolny

@WcaleNieWolny WcaleNieWolny commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary (AI generated)

  • Enforce a one-to-one relationship between Capgo users and non-null GitHub account IDs.
  • Show a dedicated account-linking error when another Capgo user already claimed the GitHub account.
  • Prebuild the production uniqueness index concurrently, then attach it as a constraint with a short table lock.
  • Cover the database constraint, transfer behavior, and PostgREST error mapping with focused tests.

Motivation (AI generated)

Premium GitHub support routing needs one GitHub account to resolve to exactly one Capgo user. Without a database constraint, concurrent or repeated links could make entitlement lookup ambiguous.

Business Impact (AI generated)

This protects premium support entitlement from duplicate account associations and gives customers a clear recovery path instead of a generic save failure. The pre-deploy index step avoids a write-blocking index build on the production users table.

Test Plan (AI generated)

  • bun test:db (21 files, 270 tests)
  • bunx vitest run tests/github-profile.unit.test.ts (8/8)
  • bunx oxlint src/services/githubProfile.ts src/pages/settings/account/index.vue tests/github-profile.unit.test.ts
  • bunx eslint src/services/githubProfile.ts src/pages/settings/account/index.vue tests/github-profile.unit.test.ts
  • bun run typecheck:frontend
  • GitHub Actions database, backend, unit, lint, typecheck, security, and visual-diff checks
  • Spec-compliance and code-quality reviews approved

Before applying the migration in production, run scripts/ops/users_github_id_unique_index.sql as a standalone pre-deploy step so PostgreSQL builds the unique index concurrently.

The complete local unit suite currently has one unrelated failure in tests/org-statistics-bandwidth-pagination.unit.test.ts; the same failure was reproduced on origin/main. The GitHub Actions unit suite passed.

Generated with AI

Review in cubic

Summary by CodeRabbit

  • New Features

    • GitHub IDs are now unique across user accounts.
    • Multiple accounts may remain without a GitHub ID.
    • Users can update or clear their own GitHub ID, allowing it to be reassigned.
  • Bug Fixes

    • Duplicate GitHub IDs are now rejected with a clear error.
  • Chores

    • Added deployment safeguards and validation for applying the uniqueness requirement.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e3e1d159-0962-4454-8ca5-fabd60975903

📥 Commits

Reviewing files that changed from the base of the PR and between 4c7d69b and 9efa001.

📒 Files selected for processing (3)
  • scripts/ops/users_github_id_unique_index.sql
  • supabase/migrations/20260802171300_enforce_unique_github_id.sql
  • supabase/tests/65_test_github_user_id.sql
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

📝 Walkthrough

Walkthrough

The PR adds operational index preparation, migration-time duplicate detection, and the users_github_id_key unique constraint. SQL tests verify index metadata, duplicate rejection, multiple null values, re-saving IDs, and ID reassignment.

Changes

GitHub account linking

Layer / File(s) Summary
Prepare the unique GitHub ID index
scripts/ops/users_github_id_unique_index.sql
The deployment script locks index processing, removes invalid indexes, creates the unique index concurrently, validates its properties, and releases the lock.
Attach and validate the unique constraint
supabase/migrations/20260802171300_enforce_unique_github_id.sql, supabase/tests/65_test_github_user_id.sql
The migration detects duplicate non-null IDs, handles populated and empty databases, validates the index, and attaches it as a unique constraint. Tests verify constraint metadata and GitHub ID assignment behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • Cap-go/capgo.app#2819: This PR builds on the existing public.users.github_id behavior and extends its test coverage.

Suggested labels: codex

Suggested reviewers: riderx

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: enforcing unique GitHub links for accounts.
Description check ✅ Passed The description includes a detailed summary and test plan; the missing checklist and screenshots section are non-critical for this backend change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

@codspeed-hq

codspeed-hq Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing wolny/unique-github-account-link (9efa001) with main (62fdcfc)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Visual diff passed

Visual changes

Generated at 2026-08-02T19:49:53.502Z. Threshold: 0.1% pixel difference.

Route Diff % Status
login 0.000 unchanged
dashboard 3.392 changed
apps 0.025 unchanged
app-overview 1.218 changed
app-settings 0.000 unchanged
app-settings-access 2.473 changed
channels 0.012 unchanged
devices 0.066 unchanged
observe 0.000 unchanged
observe-logs 0.234 changed
observe-native 0.000 unchanged
observe-compatibility 0.000 unchanged
observe-plugins 0.000 unchanged
api-keys-app-preview 0.000 unchanged

Commit: 9efa0016cadb0b1734aa70aef29eae01f443648b
Download the HTML report from workflow artifacts (artifact: visual-diff-report-9efa0016cadb0b1734aa70aef29eae01f443648b).

Open index.html from the artifact for side-by-side before/after/diff screenshots.

@WcaleNieWolny
WcaleNieWolny marked this pull request as ready for review August 2, 2026 18:30
@coderabbitai coderabbitai Bot added the codex label Aug 2, 2026
@cursor
cursor Bot requested a review from riderx August 2, 2026 18:31

@cursor cursor Bot 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.

Stale comment

Risk: high. Left a non-blocking comment — this change adds a unique GitHub-account identity constraint via a database migration, which is above the low-risk auto-approval threshold. Assigned a reviewer for human review; Cursor Bugbot was not present on this PR after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@coderabbitai coderabbitai Bot 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

🤖 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 `@supabase/migrations/20260802171300_enforce_unique_github_id.sql`:
- Around line 24-25: The migration must not build the unique constraint directly
on public.users. Use a pre-created unique index built concurrently outside this
transactional migration, then replace the ALTER TABLE users_github_id_key
operation with a short-lock attachment of that existing index; do not add CREATE
INDEX CONCURRENTLY to this migration.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: d36caa71-da39-4f28-9ded-9e81bd6159fd

📥 Commits

Reviewing files that changed from the base of the PR and between 62fdcfc and 4de93b1.

📒 Files selected for processing (6)
  • messages/en.json
  • src/pages/settings/account/index.vue
  • src/services/githubProfile.ts
  • supabase/migrations/20260802171300_enforce_unique_github_id.sql
  • supabase/tests/65_test_github_user_id.sql
  • tests/github-profile.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread supabase/migrations/20260802171300_enforce_unique_github_id.sql Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread supabase/migrations/20260802171300_enforce_unique_github_id.sql Outdated

@cursor cursor Bot 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.

Stale comment

Risk: high. Left a non-blocking comment — this PR adds a unique GitHub identity constraint via DB migration/ops index work, above the low-risk auto-approval threshold. Human review is still needed; a reviewer is already assigned. Cursor Bugbot was not present after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@coderabbitai coderabbitai Bot 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: 2

🤖 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 `@scripts/ops/users_github_id_unique_index.sql`:
- Line 1: Wrap the comments in users_github_id_unique_index.sql that exceed
SQLFluff’s 80-character limit, including the pre-deploy comment and the comment
on line 7, while preserving their wording and meaning.
- Around line 9-10: Validate the existing users_github_id_key before reusing it:
require that it is valid, ready, unique, and exactly indexes
public.users(github_id); otherwise rebuild it after duplicate cleanup or raise
an actionable error. Apply this correction in
scripts/ops/users_github_id_unique_index.sql lines 9-10 and
supabase/migrations/20260802171300_enforce_unique_github_id.sql lines 29-30,
preserving the subsequent UNIQUE USING INDEX flow only for a validated index.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 4adaa612-cd85-4738-b7e3-fe9f9f5d95c5

📥 Commits

Reviewing files that changed from the base of the PR and between 4de93b1 and 746849e.

📒 Files selected for processing (2)
  • scripts/ops/users_github_id_unique_index.sql
  • supabase/migrations/20260802171300_enforce_unique_github_id.sql
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread scripts/ops/users_github_id_unique_index.sql Outdated
Comment thread scripts/ops/users_github_id_unique_index.sql

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.

Re-trigger cubic

Comment thread scripts/ops/users_github_id_unique_index.sql
Comment thread scripts/ops/users_github_id_unique_index.sql Outdated

@cursor cursor Bot 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.

Stale comment

Risk: high. Left a non-blocking comment — this PR adds a unique GitHub identity constraint via DB migration/ops index work, above the low-risk auto-approval threshold. Human review is still needed; a reviewer is already assigned. Cursor Bugbot was not present after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cursor cursor Bot 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.

Stale comment

Risk: high. Left a non-blocking comment — this PR adds a unique GitHub identity constraint via DB migration/ops index work, above the low-risk auto-approval threshold. Human review is still needed; a reviewer is already assigned. Cursor Bugbot was not present after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/ops/users_github_id_unique_index.sql
Comment thread supabase/migrations/20260802171300_enforce_unique_github_id.sql

@cursor cursor Bot 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.

Stale comment

Risk: high. Left a non-blocking comment — this PR adds a unique GitHub identity constraint via DB migration/ops index work, above the low-risk auto-approval threshold. Human review is still needed; a reviewer is already assigned. Cursor Bugbot was not present after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cursor cursor Bot 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.

Stale comment

Comment thread src/pages/settings/account/index.vue Outdated

@cursor cursor Bot 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.

Stale comment

Risk: high. Left a non-blocking comment — this PR adds a unique GitHub identity constraint via DB migration/ops index work, above the low-risk auto-approval threshold. Human review is still needed; a reviewer is already assigned. Cursor Bugbot was not present after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@coderabbitai coderabbitai Bot 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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
supabase/tests/65_test_github_user_id.sql (1)

65-74: 📐 Maintainability & Code Quality | 🔵 Trivial

Optional: qualify pg_constraint for consistency.

Line 68 references pg_constraint unqualified, while the adjacent new block (Lines 76-105) uses pg_catalog.pg_constraint. Qualify it for consistency within the same file.

🤖 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 `@supabase/tests/65_test_github_user_id.sql` around lines 65 - 74, Update the
pg_constraint reference in the users.github_id constraint assertion to use the
pg_catalog-qualified relation, matching the adjacent constraint checks while
preserving the existing query and assertion.
🤖 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 `@scripts/ops/users_github_id_unique_index.sql`:
- Around line 21-34: Update the recovery query joins to use explicit INNER JOIN
syntax and reorder the index namespace join condition so the earlier-referenced
table appears first, resolving SQLFluff AM05/ST09 violations while preserving
the query’s behavior.

In `@supabase/migrations/20260802171300_enforce_unique_github_id.sql`:
- Around line 27-41: Ensure the deployment pipeline runs
scripts/ops/users_github_id_unique_index.sql to successful completion and waits
for its advisory lock to release before applying this migration. Preserve the
existing populated-database guard and validation behavior, but enforce this
sequencing so an index still being built is never mistaken for an invalid
completed index.
- Around line 46-88: The index-validation block in the migration duplicates the
logic in users_github_id_unique_index.sql and can drift out of sync. Add a clear
SQL comment immediately above the DO block referencing that sibling script and
instructing future changes to keep both validation implementations synchronized;
do not alter the validation behavior.

In `@supabase/tests/65_test_github_user_id.sql`:
- Around line 76-105: Update the index-shape check’s joins in the EXISTS query
to use explicit INNER JOIN syntax instead of bare JOIN, and reorder the
index_meta/access relationship in the affected ON clause so the earlier-listed
table is referenced first per SQLFluff ST09. Preserve the existing join
relationships and constraint validation predicates.

---

Outside diff comments:
In `@supabase/tests/65_test_github_user_id.sql`:
- Around line 65-74: Update the pg_constraint reference in the users.github_id
constraint assertion to use the pg_catalog-qualified relation, matching the
adjacent constraint checks while preserving the existing query and assertion.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 26c6148c-7c27-4c9e-9bcc-59c586efaacf

📥 Commits

Reviewing files that changed from the base of the PR and between 746849e and 4c7d69b.

📒 Files selected for processing (3)
  • scripts/ops/users_github_id_unique_index.sql
  • supabase/migrations/20260802171300_enforce_unique_github_id.sql
  • supabase/tests/65_test_github_user_id.sql
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread scripts/ops/users_github_id_unique_index.sql
Comment thread supabase/migrations/20260802171300_enforce_unique_github_id.sql
Comment thread supabase/migrations/20260802171300_enforce_unique_github_id.sql
Comment thread supabase/tests/65_test_github_user_id.sql

@cursor cursor Bot 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.

Risk: high. Left a non-blocking comment — this PR adds a unique GitHub identity constraint via DB migration/ops index work, above the low-risk auto-approval threshold. Human review is still needed; a reviewer is already assigned. Cursor Bugbot was not present after the initial check poll.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cubic-dev-ai cubic-dev-ai Bot 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.

1 issue found across 7 files (changes from recent commits).

Confidence score: 4/5

  • In src/pages/settings/account/index.vue, the GitHub-link flow appears to treat a DB unique-constraint collision (GitHub ID already linked to another user) as a generic failure, which can confuse users and hide the real resolution path. Handle that specific constraint error explicitly and return a clear “account already linked” message so users aren’t stuck retrying a failing action.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/pages/settings/account/index.vue">

<violation number="1">
P2: With the new unique GitHub-ID constraint now enforced at the DB, a user who tries to link a GitHub account already claimed by another Capgo user will hit a uniqueness violation, but this change collapses that case into the generic "Error while updating your account". That contradicts the PR's stated goal of clear messaging for already-claimed IDs and leaves users with no explanation for the failure. If hiding the conflict is intentional (e.g. to avoid leaking whether a GitHub account has a Capgo account), consider documenting that tradeoff or, alternatively, surfacing a message like "This GitHub account is already linked to another Capgo account".</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

@sonarqubecloud

sonarqubecloud Bot commented Aug 2, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant