Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- Migrate all org API keys to personal account fb678396-a68f-4294-ae50-b8cacf9ce77b
--
-- Background: Org API keys are being deprecated in favor of personal API keys.
-- Org API keys are identified by their `account` column pointing to an organization
-- account (i.e., any account that appears as `organization_id` in
-- account_organization_ids, meaning it has members).
--
-- This migration reassigns all such keys to the personal account
-- fb678396-a68f-4294-ae50-b8cacf9ce77b so they remain usable.

UPDATE public.account_api_keys
SET account = 'fb678396-a68f-4294-ae50-b8cacf9ce77b'
WHERE account IN (
SELECT DISTINCT organization_id
FROM public.account_organization_ids
WHERE organization_id IS NOT NULL
)
AND account != 'fb678396-a68f-4294-ae50-b8cacf9ce77b';
Comment on lines +11 to +18
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add a precondition check that the target personal account exists.

If fb678396-a68f-4294-ae50-b8cacf9ce77b is missing in any environment, this update can fail on FK enforcement and block the migration.

🔧 Proposed fix
+DO $$
+BEGIN
+  IF NOT EXISTS (
+    SELECT 1
+    FROM public.accounts
+    WHERE id = 'fb678396-a68f-4294-ae50-b8cacf9ce77b'::uuid
+  ) THEN
+    RAISE EXCEPTION
+      'Target personal account % does not exist',
+      'fb678396-a68f-4294-ae50-b8cacf9ce77b';
+  END IF;
+END $$;
+
 UPDATE public.account_api_keys
 SET account = 'fb678396-a68f-4294-ae50-b8cacf9ce77b'
 WHERE account IN (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
UPDATE public.account_api_keys
SET account = 'fb678396-a68f-4294-ae50-b8cacf9ce77b'
WHERE account IN (
SELECT DISTINCT organization_id
FROM public.account_organization_ids
WHERE organization_id IS NOT NULL
)
AND account != 'fb678396-a68f-4294-ae50-b8cacf9ce77b';
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM public.accounts
WHERE id = 'fb678396-a68f-4294-ae50-b8cacf9ce77b'::uuid
) THEN
RAISE EXCEPTION
'Target personal account % does not exist',
'fb678396-a68f-4294-ae50-b8cacf9ce77b';
END IF;
END $$;
UPDATE public.account_api_keys
SET account = 'fb678396-a68f-4294-ae50-b8cacf9ce77b'
WHERE account IN (
SELECT DISTINCT organization_id
FROM public.account_organization_ids
WHERE organization_id IS NOT NULL
)
AND account != 'fb678396-a68f-4294-ae50-b8cacf9ce77b';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@supabase/migrations/20260318000000_migrate_org_api_keys_to_personal_account.sql`
around lines 11 - 18, Add a precondition that the target personal account ID
'fb678396-a68f-4294-ae50-b8cacf9ce77b' exists before running the UPDATE against
public.account_api_keys; check existence in the accounts table (or equivalent
primary account table) and RAISE EXCEPTION (or abort the migration) if it's
missing so the UPDATE won't fail due to FK constraints; reference the target ID
and the tables account_api_keys and account_organization_ids when adding this
check.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find SQL objects referencing account_api_keys
rg -n -C3 --type=sql '\baccount_api_keys\b'

# Find account-scoping logic tied to account_api_keys.account
rg -n -C4 --type=sql 'account_api_keys\.account|USING\s*\(|WITH\s+CHECK\s*\(|\baccount\s*='

Repository: recoupable/database

Length of output: 6245


🏁 Script executed:

rg -n "CREATE POLICY.*account_api_keys|ON.*account_api_keys" --type=sql

Repository: recoupable/database

Length of output: 725


🏁 Script executed:

rg -n "CREATE POLICY" --type=sql -A 3 | head -100

Repository: recoupable/database

Length of output: 1316


🏁 Script executed:

cat -n supabase/migrations/20251206000000_create_account_api_keys.sql

Repository: recoupable/database

Length of output: 1222


🏁 Script executed:

find supabase/migrations -name "*.sql" -type f | xargs grep -l "account_api_keys\|account.*policy" | xargs cat | grep -n "CREATE POLICY\|account_api_keys" | head -50

Repository: recoupable/database

Length of output: 646


🏁 Script executed:

cat -n supabase/migrations/20260318000000_migrate_org_api_keys_to_personal_account.sql

Repository: recoupable/database

Length of output: 964


🏁 Script executed:

rg -n "account_api_keys" --type=sql -A 5 -B 2 | grep -E "FUNCTION|CREATE|SELECT|WHERE" | head -50

Repository: recoupable/database

Length of output: 934


🏁 Script executed:

rg "account_api_keys.*POLICY|POLICY.*account_api_keys" --type=sql

Repository: recoupable/database

Length of output: 45


🏁 Script executed:

find supabase/migrations -name "*.sql" -type f -exec grep -l "POLICY" {} \; | xargs basename -a

Repository: recoupable/database

Length of output: 115


Verify whether reassigning all org keys to one account breaks application logic.

No RLS policies are defined for account_api_keys, so authorization is not scoped via the account column at the database level. However, the migration still consolidates keys from multiple organization accounts into a single personal account (fb678396-a68f-4294-ae50-b8cacf9ce77b). Confirm that application-level authorization correctly handles this consolidation and that keys don't gain unintended access to other organizations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@supabase/migrations/20260318000000_migrate_org_api_keys_to_personal_account.sql`
around lines 11 - 18, This migration updates the account_api_keys table by
setting account = 'fb678396-a68f-4294-ae50-b8cacf9ce77b' for multiple
organization-derived keys (see account_api_keys.account and
account_organization_ids.organization_id); you must verify and fix
application-level authorization to ensure keys don't gain access to other
organizations: review all code paths that authorize by account (e.g., API
handlers, service methods, middleware) and either (a) preserve original
organization ownership in the migration or map each key to a specific personal
account with an explicit tenant linkage, (b) add application checks that enforce
organization-scoped access for keys now consolidated, or (c) implement
RLS/policies on account_api_keys to enforce tenant scoping; update the migration
to include the chosen approach and add unit/integration tests to cover
authorization behavior for account_api_keys after migration.