Update documentation rules for various contexts and functionalities (#235)
Update cusor rules for various contexts and functionalities
This commit is contained in:
committed by
GitHub
parent
53b09fcb8e
commit
1030c84eee
@@ -3,7 +3,6 @@ description: Detailed Database Schema and Architecture
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Database Rules
|
||||
|
||||
## Database Architecture
|
||||
@@ -12,10 +11,15 @@ alwaysApply: true
|
||||
- Accounts are the general concept of a user account, defined by the having the same ID as Supabase Auth's users (personal). They can be a team account or a personal account.
|
||||
- Generally speaking, other tables will be used to store data related to the account. For example, a table `notes` would have a foreign key `account_id` to link it to an account.
|
||||
|
||||
## Schemas
|
||||
- The DB schemas are available at `apps/web/supabase/schemas`
|
||||
- To edit the DB schema, we can either change the schema files, or created new ones
|
||||
- To create a new schema, create a file at `apps/web/supabase/schemas/<number>-<name>.sql`
|
||||
|
||||
## Migrations
|
||||
- Migration files are placed at `apps/<app>/supabase/migrations`
|
||||
- The main migration schema can be found at [20221215192558_schema.sql](mdc:apps/web/supabase/migrations/20221215192558_schema.sql)
|
||||
- Use the command `pnpm --filter web supabase migrations new <name>` for creating well timestamped migrations
|
||||
- After creating a schema, we can create a migration
|
||||
- Use the command `pnpm --filter web supabase:db:diff` for creating migrations from schemas
|
||||
- After generating a migration, reset the database for applying the changes using the command `pnpm --filter web supabase:db:reset`
|
||||
|
||||
## Security & RLS
|
||||
- Using RLS, we must ensure that only the account owner can access the data. Always write safe RLS policies and ensure that the policies are enforced.
|
||||
@@ -25,94 +29,67 @@ alwaysApply: true
|
||||
- Always consider the security of the data and explain the security implications of the data.
|
||||
- Always use Postgres schemas explicitly (e.g., `public.accounts`)
|
||||
- Consider the required compromises between simplicity, functionality and developer experience. However, never compromise on security, which is paramount and fundamental.
|
||||
- Use existing helper functions for access control instead of making your own queries, unless unavailable
|
||||
|
||||
## Schema Overview
|
||||
|
||||
Makerkit uses a Supabase Postgres database with a well-defined schema focused on multi-tenancy through the concepts of accounts (both personal and team) and robust permission systems.
|
||||
|
||||
### Core Entity Relationships
|
||||
### Database Schema
|
||||
|
||||
1. **User ↔ Account**:
|
||||
- Each user has a personal account (1:1)
|
||||
- Users can belong to multiple team accounts (M:N through `accounts_memberships`)
|
||||
- Accounts can have multiple users (M:N through `accounts_memberships`)
|
||||
|
||||
2. **Account ↔ Role**:
|
||||
- Each user has a role in each account they belong to
|
||||
- Roles define permissions through `role_permissions`
|
||||
|
||||
3. **Subscription System**:
|
||||
- Accounts can have subscriptions
|
||||
- Subscriptions have multiple subscription items
|
||||
- Billing providers include Stripe, Lemon Squeezy, and Paddle
|
||||
|
||||
4. **Invitation System**:
|
||||
- Team accounts can invite users via email
|
||||
- Invitations specify roles for the invited user
|
||||
|
||||
5. **One-Time Tokens**:
|
||||
- Used for secure verification processes
|
||||
- Generic system that can be used for various purposes
|
||||
|
||||
## Table Relationships
|
||||
|
||||
```
|
||||
auth.users
|
||||
├── public.accounts (personal_account=true, id=user_id)
|
||||
└── public.accounts_memberships
|
||||
└── public.accounts (personal_account=false)
|
||||
└── public.roles (hierarchy_level)
|
||||
└── public.role_permissions
|
||||
└── app_permissions (enum)
|
||||
```
|
||||
|
||||
```
|
||||
public.accounts
|
||||
├── public.billing_customers
|
||||
│ └── public.subscriptions
|
||||
│ └── public.subscription_items
|
||||
└── public.invitations
|
||||
```
|
||||
|
||||
```
|
||||
public.nonces
|
||||
└── auth.users (optional relationship)
|
||||
```
|
||||
|
||||
## Schema Overview
|
||||
|
||||
Makerkit implements a multi-tenant SaaS architecture through a robust account and permission system:
|
||||
|
||||
1. **Core Entities**:
|
||||
- `auth.users`: Supabase Auth users
|
||||
- `public.accounts`: Both personal and team accounts
|
||||
- `public.accounts_memberships`: Links users to accounts with roles
|
||||
- `public.roles` and `public.role_permissions`: Define permission hierarchy
|
||||
- `public.invitations`: For inviting users to team accounts
|
||||
|
||||
2. **Billing System**:
|
||||
- `public.billing_customers`: Account's connection to billing providers
|
||||
- `public.subscriptions` and `public.subscription_items`: For subscription tracking
|
||||
- `public.orders` and `public.order_items`: For one-time purchases
|
||||
|
||||
3. **Security**:
|
||||
- `public.nonces`: One-time tokens for secure operations
|
||||
1. Enums [01-enums.sql](mdc:apps/web/supabase/schemas/01-enums.sql)
|
||||
2. Config [02-config.sql](mdc:apps/web/supabase/schemas/02-config.sql)
|
||||
3. Accounts [03-accounts.sql](mdc:apps/web/supabase/schemas/03-accounts.sql)
|
||||
4. Roles [04-roles.sql](mdc:apps/web/supabase/schemas/04-roles.sql)
|
||||
5. Memberships [05-memberships.sql](mdc:apps/web/supabase/schemas/05-memberships.sql)
|
||||
6. Roles Permissions [06-roles-permissions.sql](mdc:apps/web/supabase/schemas/06-roles-permissions.sql)
|
||||
7. Invitations [07-invitations.sql](mdc:apps/web/supabase/schemas/07-invitations.sql)
|
||||
8. Billing Customers [08-billing-customers.sql](mdc:apps/web/supabase/schemas/08-billing-customers.sql)
|
||||
9. Subscriptions [09-subscriptions.sql](mdc:apps/web/supabase/schemas/09-subscriptions.sql)
|
||||
10. Orders [10-orders.sql](mdc:apps/web/supabase/schemas/10-orders.sql)
|
||||
11. Notifications [11-notifications.sql](mdc:apps/web/supabase/schemas/11-notifications.sql)
|
||||
12. One Time Tokens [12-one-time-tokens.sql](mdc:apps/web/supabase/schemas/12-one-time-tokens.sql)
|
||||
13. Multi Factor Auth [13-mfa.sql](mdc:apps/web/supabase/schemas/13-mfa.sql)
|
||||
14. Super Admin [14-super-admin.sql](mdc:apps/web/supabase/schemas/14-super-admin.sql)
|
||||
15. Account Views [15-account-views.sql](mdc:apps/web/supabase/schemas/15-account-views.sql)
|
||||
16. Storage [16-storage.sql](mdc:apps/web/supabase/schemas/16-storage.sql)
|
||||
|
||||
## Database Best Practices
|
||||
|
||||
### Inferring Database types
|
||||
|
||||
Fetch auto-generated data types using the `@kit/supabase/database` import. Do not write types manually if the shape is the same as the one from the database row.
|
||||
|
||||
```tsx
|
||||
import { Tables } from '@kit/supabase/database';
|
||||
|
||||
// public.accounts
|
||||
type Account = Tables<'accounts'>;
|
||||
|
||||
// public.subscriptions
|
||||
type Subscription = Tables<'subscriptions'>;
|
||||
|
||||
// public.notifications
|
||||
type Notification = Tables<'notifications'>;
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
- **Always enable RLS** on new tables unless explicitly instructed otherwise
|
||||
- **Create proper RLS policies** for all CRUD operations following existing patterns
|
||||
- **Always associate data with accounts** using a foreign key to ensure proper access control
|
||||
- **Use explicit schema references** (`public.table_name` not just `table_name`)
|
||||
- **Place internal functions in the `kit` schema**
|
||||
- **Private schema**: Place internal functions in the `kit` schema
|
||||
- **Search Path**: Always set search path to '' when defining functions
|
||||
- **Security Definer**: Do not use `security definer` functions unless stricly required
|
||||
|
||||
### Data Access Patterns
|
||||
|
||||
- Use `has_role_on_account(account_id, role?)` to check membership
|
||||
- Use `has_permission(user_id, account_id, permission)` for permission checks
|
||||
- Use `is_account_owner(account_id)` to identify account ownership
|
||||
- Use `public.has_role_on_account(account_id, role?)` to check membership
|
||||
- Use `public.has_permission(user_id, account_id, permission)` for permission checks
|
||||
- Use `public.is_account_owner(account_id)` to identify account ownership
|
||||
|
||||
### SQL Coding Style
|
||||
|
||||
@@ -136,12 +113,15 @@ Makerkit implements a multi-tenant SaaS architecture through a robust account an
|
||||
|
||||
### 1. RLS Policy Management
|
||||
|
||||
- **Always Enable RLS**: Always enable RLS for your tables unless you have a specific reason not to.
|
||||
#### Always Enable RLS
|
||||
|
||||
Always enable RLS for your tables unless you have a specific reason not to.
|
||||
```sql
|
||||
ALTER TABLE public.my_table ENABLE ROW LEVEL SECURITY;
|
||||
```
|
||||
|
||||
- **Follow the Standard Policies Pattern**: Use the existing structure for policies:
|
||||
#### Use Helper Functions to validate permissions and access control
|
||||
Use the existing structure for policies:
|
||||
```sql
|
||||
-- SELECT policy
|
||||
CREATE POLICY "my_table_read" ON public.my_table FOR SELECT
|
||||
@@ -153,11 +133,19 @@ Makerkit implements a multi-tenant SaaS architecture through a robust account an
|
||||
-- INSERT/UPDATE/DELETE policies follow similar patterns
|
||||
```
|
||||
|
||||
When using RLS at team-account level, use `public.has_role_on_account(account_id)` for a generic check to understand if a user is part of a team.
|
||||
|
||||
When using RLS at user-account level, use `account_id = (select auth.uid())`.
|
||||
|
||||
When an entity can belong to both, use both.
|
||||
|
||||
When requiring a specific role, use the role parameter `public.has_role_on_account(account_id, 'owner')`
|
||||
|
||||
### 2. Account Association
|
||||
|
||||
- **Associate Data with Accounts**: Always link data to accounts using a foreign key:
|
||||
```sql
|
||||
CREATE TABLE public.my_data (
|
||||
CREATE TABLE if not exists public.my_data (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
account_id UUID REFERENCES public.accounts(id) ON DELETE CASCADE NOT NULL,
|
||||
/* other fields */
|
||||
@@ -201,14 +189,14 @@ Makerkit implements a multi-tenant SaaS architecture through a robust account an
|
||||
```sql
|
||||
CREATE TYPE public.my_status AS ENUM('active', 'inactive', 'pending');
|
||||
|
||||
CREATE TABLE public.my_table (
|
||||
CREATE TABLE if not exists public.my_table (
|
||||
status public.my_status NOT NULL DEFAULT 'pending'
|
||||
);
|
||||
```
|
||||
|
||||
- **Apply Appropriate Constraints**: Use constraints to ensure data integrity:
|
||||
```sql
|
||||
CREATE TABLE public.my_table (
|
||||
CREATE TABLE if not exists public.my_table (
|
||||
email VARCHAR(255) NOT NULL CHECK (email ~* '^.+@.+\..+$'),
|
||||
count INTEGER NOT NULL CHECK (count >= 0),
|
||||
/* other fields */
|
||||
@@ -265,6 +253,8 @@ Makerkit implements a multi-tenant SaaS architecture through a robust account an
|
||||
SELECT ...
|
||||
```
|
||||
|
||||
You always must use `(security_invoker = true)` for views.
|
||||
|
||||
## Key Functions to Know
|
||||
|
||||
1. **Account Access**
|
||||
|
||||
Reference in New Issue
Block a user