Skip to content

Conversation

@maparent
Copy link
Collaborator

@maparent maparent commented Jan 1, 2026

https://linear.app/discourse-graphs/issue/ENG-1231/migrate-spaceaccess-to-use-user-ids-not-platformaccount-ids

Currently, SpaceAccess uses PlatformAccounts. This was a mistake, as access is granted to users (cross-accounts) not PlatformAccounts.

OTH, we still need to know which PlatformAccounts have access to a given space, even before the corresponding user is created; for this reason I have created a separate LocalAccess table.

Eventually (separate PR) when the user account is created from a platformAccount, we will create the SpaceAccess from the LocalAccess entries for that PlatformAccount. (Separate issue for now.)

Note: db diff uses migra, which gets confused about views, so the db diff is not empty after migration, but it's clearly an artefact. This is something to keep an eye on. pg_schema_diff is the newer tool that supabase is pushing, but it's less complete for now.

Loom: https://www.loom.com/share/d410830db7bc413e96ae38774da998d0

Summary by CodeRabbit

  • New Features

    • Added a local access layer to track per-account access to spaces and a view for accounts you can access.
  • Refactor

    • Migrated space-sharing to use user identity (uid) for more accurate anonymous/user linkage and tightened row-level security and access-control logic.
  • Bug Fixes

    • Fixed anonymous-user space association so newly created/anonymous users are correctly linked to spaces.

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Jan 1, 2026

@supabase
Copy link

supabase bot commented Jan 1, 2026

Updates to Preview Branch (eng-1231-migrate-spaceaccess-to-use-user-ids-not-platformaccount-ids) ↗︎

Deployments Status Updated
Database Thu, 01 Jan 2026 19:53:19 UTC
Services Thu, 01 Jan 2026 19:53:19 UTC
APIs Thu, 01 Jan 2026 19:53:19 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Thu, 01 Jan 2026 19:53:20 UTC
Migrations Thu, 01 Jan 2026 19:53:21 UTC
Seeding Thu, 01 Jan 2026 19:53:21 UTC
Edge Functions Thu, 01 Jan 2026 19:53:22 UTC

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

@maparent maparent marked this pull request as draft January 1, 2026 16:47
@maparent
Copy link
Collaborator Author

maparent commented Jan 1, 2026

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

✅ Actions performed

Review triggered.

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

📝 Walkthrough

Walkthrough

Migrates space-access from platform-account IDs to auth-user IDs: adds a LocalAccess table, rewrites SpaceAccess to use account_uid (auth.users.id), updates DB functions/views/policies (many to auth.uid()), removes legacy my_account(), and updates application upserts to use account_uid with corresponding migration SQL and test updates.

Changes

Cohort / File(s) Summary
DB Types
packages/database/src/dbTypes.ts
Added LocalAccess table types; updated SpaceAccess types to replace account_id (number) with account_uid (string/UUID); removed my_account() function declaration; added LocalAccess entry under content area.
App function
packages/database/supabase/functions/create-space/index.ts
Updated SpaceAccess upsert payload to use anonymousUser.idaccount_uid and changed onConflict key from "space_id,account_id" to "account_uid,space_id".
Migration SQL
packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
Recreated/redefined SpaceAccess with primary key (account_uid, space_id) referencing auth.users(id); added LocalAccess table; added functions: is_my_account, my_space_ids, in_space, account_in_shared_space, unowned_account_in_shared_space, upsert_account_in_space; added my_accounts view; introduced RLS policies and data migration steps; dropped legacy my_account.
Schema
packages/database/supabase/schemas/account.sql
Added public.LocalAccess (account_id, space_id composite PK); refactored SpaceAccess to use account_uid FK to auth.users; rewrote function bodies, view (my_accounts), and RLS policies to be account_uid/auth.uid()-centric; adjusted upsert flows to populate both SpaceAccess (account_uid) and LocalAccess (account_id).
Tests / Features
packages/database/features/getContext.feature
Updated expectations to reflect new model: replaced counts of "2 SpaceAccess" with "1 SpaceAccess" and added "1 LocalAccess" assertions across scenarios.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AppFn as create-space (supabase function)
  participant Auth as auth.users
  participant DB as Public DB (SpaceAccess, LocalAccess, PlatformAccount)

  rect rgba(200,230,255,0.4)
  Client->>AppFn: request create space (anonymousUser.id)
  AppFn->>Auth: use anonymousUser.id (account_uid)
  AppFn->>DB: upsert SpaceAccess {account_uid, space_id, editor}
  DB-->>DB: ON CONFLICT (account_uid,space_id) apply update
  AppFn->>DB: insert LocalAccess {account_id, space_id} DO NOTHING on conflict
  DB-->>Client: return space & account identifiers
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: migrating SpaceAccess to use user IDs instead of PlatformAccount IDs, which is the primary objective of this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/database/supabase/schemas/account.sql (3)

94-96: Consider restricting anon privileges on LocalAccess.

Currently GRANT ALL ON TABLE public."LocalAccess" TO anon gives anonymous users full table access (before RLS). While RLS will still apply, the anon role typically shouldn't need INSERT/UPDATE/DELETE privileges. Consider restricting to SELECT only for defense in depth.

This matches the pattern used for PlatformAccount (line 43) where anon is revoked.

🔎 Suggested change
-GRANT ALL ON TABLE public."LocalAccess" TO anon;
+REVOKE ALL ON TABLE public."LocalAccess" FROM anon;

128-130: Same privilege concern for SpaceAccess.

Consider restricting anon privileges here as well, matching the pattern suggested for LocalAccess.

🔎 Suggested change
-GRANT ALL ON TABLE public."SpaceAccess" TO anon;
+REVOKE ALL ON TABLE public."SpaceAccess" FROM anon;

169-171: Minor: Alias sa is misleading for LocalAccess insert.

The alias sa (typically suggesting SpaceAccess) is used for the LocalAccess insert. Consider renaming to la for clarity.

🔎 Suggested change
-    INSERT INTO public."LocalAccess" as sa (space_id, account_id) values (space_id_, account_id_)
+    INSERT INTO public."LocalAccess" as la (space_id, account_id) values (space_id_, account_id_)
         ON CONFLICT (space_id, account_id)
         DO NOTHING;
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0734588 and 9658205.

📒 Files selected for processing (4)
  • packages/database/src/dbTypes.ts
  • packages/database/supabase/functions/create-space/index.ts
  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
  • packages/database/supabase/schemas/account.sql
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/main.mdc)

**/*.{ts,tsx}: Use Tailwind CSS for styling where possible
When refactoring inline styles, use tailwind classes
Prefer type over interface in TypeScript
Use explicit return types for functions
Avoid any types when possible
Prefer arrow functions over regular function declarations
Use named parameters (object destructuring) when a function has more than 2 parameters
Use PascalCase for components and types
Use camelCase for variables and functions
Use UPPERCASE for constants
Function names should describe their purpose clearly
Prefer early returns over nested conditionals for better readability

Files:

  • packages/database/src/dbTypes.ts
  • packages/database/supabase/functions/create-space/index.ts
🧠 Learnings (8)
📚 Learning: 2025-05-30T14:49:24.016Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 182
File: apps/website/app/utils/supabase/dbUtils.ts:22-28
Timestamp: 2025-05-30T14:49:24.016Z
Learning: In apps/website/app/utils/supabase/dbUtils.ts, expanding the KNOWN_EMBEDDINGS and DEFAULT_DIMENSIONS mappings to support additional embedding models requires corresponding database model changes (creating new embedding tables), which should be scoped as separate work from API route implementations.

Applied to files:

  • packages/database/src/dbTypes.ts
📚 Learning: 2025-07-13T16:47:14.352Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-07-13T16:47:14.352Z
Learning: In the discourse-graph codebase, types.gen.ts contains automatically generated database function type definitions that may have reordered signatures between versions. This reordering is expected behavior from the code generation process and should not be flagged as an issue requiring fixes.

Applied to files:

  • packages/database/src/dbTypes.ts
📚 Learning: 2025-06-09T16:57:14.681Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 198
File: packages/database/supabase/migrations/20250605083319_alpha_upload.sql:157-337
Timestamp: 2025-06-09T16:57:14.681Z
Learning: Migration files in packages/database/supabase/migrations/ are historical snapshots that preserve database schema and functions as they existed at the time of creation. These files should not be updated to reflect current schema changes, even if they reference tables or columns that have since been modified or removed. Schema incompatibilities in migration files are expected and acceptable as they represent the valid state at the time of migration.

Applied to files:

  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-10-15T00:12:54.623Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 482
File: packages/database/supabase/schemas/access_token.sql:43-43
Timestamp: 2025-10-15T00:12:54.623Z
Learning: In PostgreSQL RLS policies, you cannot combine multiple operations like `FOR SELECT, UPDATE, DELETE` in a single CREATE POLICY statement. Use `FOR ALL` to cover all operations, or create separate policies for each operation type (FOR SELECT, FOR INSERT, FOR UPDATE, FOR DELETE).

Applied to files:

  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-07-08T14:48:38.048Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 272
File: packages/ui/src/lib/supabase/contextFunctions.ts:50-111
Timestamp: 2025-07-08T14:48:38.048Z
Learning: The Supabase client does not offer transaction support, so idempotent upserts with proper conflict resolution (using onConflict with ignoreDuplicates: false) are the preferred approach for multi-step database operations in packages/ui/src/lib/supabase/contextFunctions.ts. This pattern prevents orphaned records when retrying operations.

Applied to files:

  • packages/database/supabase/functions/create-space/index.ts
📚 Learning: 2025-05-22T23:50:23.771Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 165
File: packages/database/supabase/migrations/20250513173724_content_concept_key.sql:37-60
Timestamp: 2025-05-22T23:50:23.771Z
Learning: For the discourse-graph project, database schema management focuses on the final state in the supabase/schemas directory, not on the individual migration files. When reviewing database changes, consider only the schema definitions in this directory, not potential duplications or conflicts across migration files.

Applied to files:

  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-10-08T18:55:18.029Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-10-08T18:55:18.029Z
Learning: In PostgreSQL queries within the discourse-graph project, adding `LIMIT 1` to `auth.uid()` lookups provides positive performance impact and should be retained as an optimization technique.

Applied to files:

  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-07-14T05:51:46.322Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-07-14T05:51:46.322Z
Learning: The concept_in_space function in the discourse-graph project is slower than using a more direct approach with in_space(space_id) directly in RLS policies, which is why a more direct approach is sometimes preferred for performance reasons.

Applied to files:

  • packages/database/supabase/schemas/account.sql
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Supabase Preview
  • GitHub Check: Supabase Preview
  • GitHub Check: Supabase Preview
🔇 Additional comments (10)
packages/database/src/dbTypes.ts (1)

1-1: Auto-generated types correctly reflect schema migration.

The generated types properly capture the new LocalAccess table and the SpaceAccess migration from account_id (number) to account_uid (string/UUID). The relationship definitions are consistent with the schema changes.

packages/database/supabase/functions/create-space/index.ts (1)

165-181: SpaceAccess upsert correctly migrated to use account_uid.

The upsert now uses anonymousUser.id (UUID from auth.users) for account_uid, and the onConflict key correctly matches the new composite primary key (account_uid, space_id). The idempotent pattern is preserved.

packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql (5)

55-65: Data migration logic is sound.

The migration correctly:

  1. Transfers access records to SpaceAccess only for accounts with a linked auth user (dg_account IS NOT NULL)
  2. Removes the editor column from LocalAccess (now only in SpaceAccess)
  3. Cleans up anonymous platform accounts from LocalAccess since they now live in SpaceAccess

189-192: Verify LocalAccess insert policy for new platform accounts.

The local_access_insert_policy requires unowned_account_in_shared_space(account_id) OR is_my_account(account_id). For a brand-new platform account (not yet in LocalAccess), unowned_account_in_shared_space would return false since it requires an existing LocalAccess row.

This appears intentional since upsert_account_in_space uses SECURITY DEFINER to bypass RLS when creating accounts. Please confirm this is the expected behavior—direct inserts are only allowed for accounts already tracked in the system.


164-180: View correctly exposes accounts in shared spaces.

The my_accounts view properly joins LocalAccess and SpaceAccess to show platform accounts that exist in spaces the current user has access to via their account_uid.


67-122: Security utility functions are well-designed.

All functions correctly use STABLE SECURITY DEFINER with SET search_path = '' to prevent search path injection attacks. The logic properly enforces the new access model:

  • is_my_account: Validates ownership via dg_account
  • my_space_ids/in_space: Check SpaceAccess by account_uid
  • account_in_shared_space/unowned_account_in_shared_space: Use the LocalAccessSpaceAccess join pattern

124-162: Upsert function correctly handles claimed vs. unclaimed accounts.

The logic appropriately differentiates:

  • Claimed accounts (dg_account IS NOT NULL): Creates both SpaceAccess (auth user access) and LocalAccess (platform account tracking)
  • Unclaimed accounts: Creates only LocalAccess

This aligns with the access model where SpaceAccess gates user-level permissions and LocalAccess tracks platform account presence.

packages/database/supabase/schemas/account.sql (3)

314-330: View definition is consistent with the new access model.

The my_accounts view correctly uses the LocalAccessSpaceAccess join to expose platform accounts visible to the authenticated user.


366-380: LocalAccess RLS policies are properly defined.

Policies correctly enforce:

  • SELECT: User must have SpaceAccess to the space
  • DELETE/INSERT/UPDATE: User must own the account or it must be an unowned account in a shared space

Note: Direct inserts for brand-new accounts are blocked (by design) since upsert_account_in_space uses SECURITY DEFINER to bypass RLS.


389-399: AgentIdentifier policies correctly differentiate read vs. write access.

The SELECT policy uses account_in_shared_space (allows viewing identifiers for any account in a shared space), while mutation policies require unowned_account_in_shared_space OR is_my_account. This correctly prevents modifying another user's claimed account identifiers while allowing visibility for collaboration.

@maparent
Copy link
Collaborator Author

maparent commented Jan 1, 2026

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
packages/database/features/getContext.feature (1)

13-13: "Scenario Outline" without Examples table.

Both scenarios are labeled Scenario Outline but lack the required Examples: table. In Gherkin, Scenario Outline is used for parameterized tests with an Examples table. If no parameterization is intended, these should be plain Scenario instead.

🔎 Proposed fix
-  Scenario Outline: Calling the getContext steps
+  Scenario: Calling the getContext steps
-  Scenario Outline: Calling getContext again
+  Scenario: Calling getContext again

Also applies to: 26-26

🧹 Nitpick comments (4)
packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql (2)

144-149: Type mismatch: user_uuid is VARCHAR but account_uid is UUID.

The variable user_uuid is declared as VARCHAR (line 135/144) but is used to insert into account_uid which is of type UUID. While PostgreSQL will implicitly cast, it's cleaner to declare user_uuid as UUID for type consistency. However, since this is a migration file and per learnings should not be modified after application, this can be addressed in the schema file instead.


67-74: Consider using EXISTS instead of COUNT for efficiency.

COUNT(id) > 0 scans all matching rows to count them, while EXISTS short-circuits after finding the first match. Based on learnings, performance optimizations like LIMIT 1 on auth.uid() lookups are valued in this project.

🔎 Proposed optimization
 CREATE OR REPLACE FUNCTION public.is_my_account(account_id BIGINT) RETURNS boolean
 STABLE SECURITY DEFINER
 SET search_path = ''
 LANGUAGE sql
 AS $$
-    SELECT COUNT(id) > 0 FROM public."PlatformAccount"
-    WHERE id = account_id AND dg_account = auth.uid();
+    SELECT EXISTS (
+        SELECT 1 FROM public."PlatformAccount"
+        WHERE id = account_id AND dg_account = auth.uid()
+        LIMIT 1
+    );
 $$;

However, since this is a migration file and per learnings should not be modified after application, this optimization should be applied in the schema file instead.

packages/database/supabase/schemas/account.sql (2)

150-151: Type mismatch: user_uuid declared as VARCHAR but used as UUID.

The variable user_uuid is declared as VARCHAR (line 151) but dg_account is UUID and it's inserted into account_uid which is also UUID. While PostgreSQL will implicitly cast, declaring as UUID is cleaner and provides type safety.

🔎 Proposed fix
 DECLARE
     platform_ public."Platform";
     account_id_ BIGINT;
-    user_uuid VARCHAR;
+    user_uuid UUID;
 BEGIN

Also applies to: 160-166


220-227: Consider EXISTS over COUNT for better performance.

Based on learnings from this project, LIMIT 1 optimizations on auth.uid() lookups provide positive performance impact. Similarly, EXISTS short-circuits after finding the first match, while COUNT must scan all matching rows.

🔎 Proposed optimization
 CREATE OR REPLACE FUNCTION public.is_my_account(account_id BIGINT) RETURNS boolean
 STABLE SECURITY DEFINER
 SET search_path = ''
 LANGUAGE sql
 AS $$
-    SELECT COUNT(id) > 0 FROM public."PlatformAccount"
-    WHERE id = account_id AND dg_account = auth.uid();
+    SELECT EXISTS (
+        SELECT 1 FROM public."PlatformAccount"
+        WHERE id = account_id AND dg_account = auth.uid()
+        LIMIT 1
+    );
 $$;
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9658205 and 95e9375.

📒 Files selected for processing (3)
  • packages/database/features/getContext.feature
  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
  • packages/database/supabase/schemas/account.sql
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 165
File: packages/database/supabase/migrations/20250504202930_content_tables.sql:37-45
Timestamp: 2025-05-20T03:11:07.917Z
Learning: When reviewing SQL migrations in this codebase, understand that historical migration files should not be modified once they're applied. Instead, issues should be fixed in subsequent migrations or schema definition files. This is why maparent indicated "migration, not changing. corrected in schema."
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 165
File: packages/database/supabase/migrations/20250504202930_content_tables.sql:37-45
Timestamp: 2025-05-20T03:11:07.917Z
Learning: When reviewing SQL migrations in the discourse-graph codebase, understand that historical migration files should not be modified once they're applied. Instead, issues should be fixed in subsequent migrations or schema definition files. This is why maparent indicated "migration, not changing. corrected in schema."
📚 Learning: 2025-06-09T16:57:14.681Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 198
File: packages/database/supabase/migrations/20250605083319_alpha_upload.sql:157-337
Timestamp: 2025-06-09T16:57:14.681Z
Learning: Migration files in packages/database/supabase/migrations/ are historical snapshots that preserve database schema and functions as they existed at the time of creation. These files should not be updated to reflect current schema changes, even if they reference tables or columns that have since been modified or removed. Schema incompatibilities in migration files are expected and acceptable as they represent the valid state at the time of migration.

Applied to files:

  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-05-20T03:04:21.602Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 165
File: packages/database/supabase/migrations/20250512142307_sync_table.sql:20-21
Timestamp: 2025-05-20T03:04:21.602Z
Learning: Database migration files (like the SQL files in packages/database/supabase/migrations/) should not be modified after they're created, even to fix minor issues like unused variables. Issues should be addressed in newer schema files instead to maintain migration history integrity.

Applied to files:

  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
📚 Learning: 2025-10-15T00:12:54.623Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 482
File: packages/database/supabase/schemas/access_token.sql:43-43
Timestamp: 2025-10-15T00:12:54.623Z
Learning: In PostgreSQL RLS policies, you cannot combine multiple operations like `FOR SELECT, UPDATE, DELETE` in a single CREATE POLICY statement. Use `FOR ALL` to cover all operations, or create separate policies for each operation type (FOR SELECT, FOR INSERT, FOR UPDATE, FOR DELETE).

Applied to files:

  • packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql
  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-10-08T18:55:18.029Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-10-08T18:55:18.029Z
Learning: In PostgreSQL queries within the discourse-graph project, adding `LIMIT 1` to `auth.uid()` lookups provides positive performance impact and should be retained as an optimization technique.

Applied to files:

  • packages/database/supabase/schemas/account.sql
📚 Learning: 2025-07-14T05:51:46.322Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-07-14T05:51:46.322Z
Learning: The concept_in_space function in the discourse-graph project is slower than using a more direct approach with in_space(space_id) directly in RLS policies, which is why a more direct approach is sometimes preferred for performance reasons.

Applied to files:

  • packages/database/supabase/schemas/account.sql
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Supabase Preview
  • GitHub Check: Supabase Preview
🔇 Additional comments (6)
packages/database/features/getContext.feature (1)

17-24: Test expectations correctly updated for the new access model.

The updated assertions properly reflect the migration: one SpaceAccess entry for the authenticated user (via account_uid) and one LocalAccess entry tracking the platform account's presence in the space. This aligns with the removal of anonymous user entries from SpaceAccess in the migration.

packages/database/supabase/migrations/20251231203152_migrate_space_access_to_user.sql (2)

55-59: Data migration correctly populates SpaceAccess from existing records.

The migration properly joins LocalAccess with PlatformAccount to transfer editor status to the new SpaceAccess table, filtering only accounts that have a linked dg_account (authenticated user). This ensures only claimed accounts get access entries.


1-6: Clean migration structure for schema transition.

The migration properly handles the schema transition by:

  1. Revoking permissions and dropping policies before restructuring
  2. Renaming the old table and constraints
  3. Creating the new table with proper foreign keys
  4. Migrating data appropriately
  5. Dropping the legacy my_account() function at the end

This is a well-organized approach for this type of schema migration.

Also applies to: 203-203

packages/database/supabase/schemas/account.sql (3)

67-95: Well-structured LocalAccess table definition.

The LocalAccess table correctly establishes the relationship between platform accounts and spaces with:

  • Proper composite primary key (account_id, space_id)
  • Cascading foreign keys to both PlatformAccount and Space
  • Appropriate grants for authenticated and service_role

356-362: SpaceAccess policies correctly enforce user-owned access.

The RLS policies appropriately restrict modifications to only the user's own records via account_uid = auth.uid(), while allowing SELECT to anyone in the same space via public.in_space(space_id).


364-378: LocalAccess RLS policies properly integrate with new access model.

The policies correctly use the helper functions:

  • in_space(space_id) for SELECT visibility
  • unowned_account_in_shared_space(account_id) OR is_my_account(account_id) for modifications

This allows users to modify their own records or unowned accounts in shared spaces, which aligns with the described access control requirements.

@maparent maparent marked this pull request as ready for review January 1, 2026 18:28
@maparent maparent requested a review from mdroidian January 1, 2026 18:28
Sign up for free to 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