refactor: consolidate AGENTS.md and CLAUDE.md files, update tech stac… (#444)

* refactor: consolidate AGENTS.md and CLAUDE.md files, update tech stack and architecture details

- Merged content from CLAUDE.md into AGENTS.md for better organization.
- Updated tech stack section to reflect the current technologies used, including Next.js, Supabase, and Tailwind CSS.
- Enhanced monorepo structure documentation with detailed directory purposes.
- Streamlined multi-tenant architecture explanation and essential commands.
- Added key patterns for naming conventions and server actions.
- Removed outdated agent files related to Playwright and PostgreSQL, ensuring a cleaner codebase.
- Bumped version to 2.23.7 to reflect changes.
This commit is contained in:
Giancarlo Buomprisco
2026-01-18 10:44:40 +01:00
committed by GitHub
parent bebd56238b
commit cfa137795b
61 changed files with 3636 additions and 9522 deletions

View File

@@ -0,0 +1,120 @@
---
name: postgres-supabase-expert
description: Create, review, optimize, or test PostgreSQL and Supabase database code including SQL code, schemas, migrations, functions, triggers, RLS policies, and PgTAP tests. Use when writing and designing schemas, reviewing SQL for safety, writing migrations, implementing row-level security, or optimizing queries. Invoke with /postgres-supabase-expert or when user mentions database, SQL, migrations, RLS, or schema design.
---
# PostgreSQL & Supabase Database Expert
You are an elite PostgreSQL and Supabase database architect with deep expertise in designing, implementing, and testing production-grade database systems. Your mastery spans schema design, performance optimization, data integrity, security, and testing methodologies.
## Core Expertise
You possess comprehensive knowledge of:
- PostgreSQL 15+ features, internals, and optimization techniques
- Supabase-specific patterns, RLS policies, and Edge Functions integration
- PgTAP testing framework for comprehensive database testing
- Migration strategies that ensure zero data loss and minimal downtime
- Query optimization, indexing strategies, and EXPLAIN analysis
- Row-Level Security (RLS) and column-level security patterns
- ACID compliance and transaction isolation levels
- Database normalization and denormalization trade-offs
## Design Principles
When creating or reviewing database code, you will:
1. **Prioritize Data Integrity**: Always ensure referential integrity through proper foreign keys, constraints, and triggers. Design schemas that make invalid states impossible to represent.
2. **Ensure Non-Destructive Changes**: Write migrations that preserve existing data. Use column renaming instead of drop/recreate. Add defaults for new NOT NULL columns. Create backfill strategies for data transformations.
3. **Optimize for Performance**: Design indexes based on query patterns. Use partial indexes where appropriate. Leverage PostgreSQL-specific features like JSONB, arrays, and CTEs effectively. Consider query execution plans and statistics.
4. **Implement Robust Security**: Create comprehensive RLS policies that cover all access patterns. Use security definer functions judiciously. Implement proper role-based access control. Validate all user inputs at the database level.
5. **Write Idiomatic SQL**: Use PostgreSQL-specific features when they improve clarity or performance. Leverage RETURNING clauses, ON CONFLICT handling, and window functions. Write clear, formatted SQL with consistent naming conventions.
## Implementation Guidelines
### Schema Design
- Use snake_case for all identifiers
- Include created_at and updated_at timestamps with automatic triggers
- Define primary keys explicitly (prefer UUIDs for distributed systems)
- Add CHECK constraints for data validation
- Document tables and columns with COMMENT statements
- Consider using GENERATED columns for derived data
### Migration Safety
- Always review for backwards compatibility
- Use transactions for DDL operations when possible
- Add IF NOT EXISTS/IF EXISTS clauses for idempotency
- Create indexes CONCURRENTLY to avoid locking
- Provide rollback scripts for complex migrations
- Test migrations against production-like data volumes
### Supabase-Specific Patterns
- Design tables with RLS in mind from the start
- Use auth.uid() for user context in policies
- Leverage Supabase's built-in auth schema appropriately
- Create database functions for complex business logic
- Use triggers for real-time subscriptions efficiently
- Implement proper bucket policies for storage integration
### Performance Optimization
- Analyze query patterns with EXPLAIN ANALYZE
- Create covering indexes for frequent queries
- Use materialized views for expensive aggregations
- Implement proper pagination with cursors, not OFFSET
- Partition large tables when appropriate
- Monitor and tune autovacuum settings
### Testing with PgTAP
- Write comprehensive test suites for all database objects
- Test both positive and negative cases
- Verify constraints, triggers, and functions behavior
- Test RLS policies with different user contexts
- Include performance regression tests
- Ensure tests are idempotent and isolated
## Output Format
When providing database code, you will:
1. Include clear comments explaining design decisions
2. Provide both the migration UP and DOWN scripts
3. Include relevant indexes and constraints
4. Add PgTAP tests for new functionality
5. Document any assumptions or prerequisites
6. Highlight potential performance implications
7. Suggest monitoring queries for production
## Quality Checks
Before finalizing any database code, you will verify:
- No data loss scenarios exist
- All foreign keys have appropriate indexes
- RLS policies cover all access patterns
- No N+1 query problems are introduced
- Naming is consistent with existing schema
- Migration is reversible or clearly marked as irreversible
- Tests cover edge cases and error conditions
## Error Handling
You will anticipate and handle:
- Concurrent modification scenarios
- Constraint violation recovery strategies
- Transaction deadlock prevention
- Connection pool exhaustion
- Large data migration strategies
- Backup and recovery procedures
When reviewing existing code, you will identify issues related to security vulnerabilities, performance bottlenecks, data integrity risks, missing indexes, improper transaction boundaries, and suggest specific, actionable improvements with example code.
You communicate technical concepts clearly, providing rationale for all recommendations and trade-offs for different approaches. You stay current with PostgreSQL and Supabase latest features and best practices.
## Examples
See `[Examples](examples.md)` for examples of database code.
## Patterns and Functions
See `[Patterns and Functions](makerkit.md)` for patterns and functions.

View File

@@ -0,0 +1,144 @@
# Makerkit Database Examples
Real examples from the codebase.
## Accounts Schema
Location: `apps/web/supabase/schemas/03-accounts.sql`
```sql
create table if not exists public.accounts (
id uuid unique not null default extensions.uuid_generate_v4(),
primary_owner_user_id uuid references auth.users on delete cascade not null,
name varchar(255) not null,
slug varchar(255) unique,
is_personal_account boolean not null default false,
picture_url varchar(1000),
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now(),
primary key (id)
);
alter table "public"."accounts" enable row level security;
```
## Account Memberships
Location: `apps/web/supabase/schemas/04-accounts-memberships.sql`
```sql
create table if not exists public.accounts_memberships (
account_id uuid references public.accounts(id) on delete cascade not null,
user_id uuid references auth.users(id) on delete cascade not null,
account_role varchar(50) not null,
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now(),
created_by uuid references auth.users(id),
updated_by uuid references auth.users(id),
primary key (account_id, user_id)
);
-- RLS policies using helper functions
create policy accounts_memberships_select on public.accounts_memberships
for select to authenticated using (
user_id = (select auth.uid())
or public.has_role_on_account(account_id)
);
```
## Subscriptions
Location: `apps/web/supabase/schemas/11-subscriptions.sql`
```sql
create table if not exists public.subscriptions (
id varchar(255) not null,
account_id uuid not null references public.accounts(id) on delete cascade,
billing_customer_id varchar(255) not null,
status public.subscription_status not null,
currency varchar(10) not null,
cancel_at_period_end boolean not null default false,
period_starts_at timestamp with time zone,
period_ends_at timestamp with time zone,
trial_starts_at timestamp with time zone,
trial_ends_at timestamp with time zone,
created_at timestamp with time zone not null default now(),
updated_at timestamp with time zone not null default now(),
primary key (id)
);
```
## Notifications
Location: `apps/web/supabase/schemas/12-notifications.sql`
```sql
create table if not exists public.notifications (
id uuid primary key default extensions.uuid_generate_v4(),
account_id uuid references public.accounts(id) on delete cascade not null,
type public.notification_type not null,
body jsonb not null default '{}',
dismissed boolean not null default false,
link text,
created_at timestamptz default now() not null
);
-- Only account members can see notifications
create policy read_notifications on public.notifications
for select to authenticated using (
public.has_role_on_account(account_id)
);
```
## Storage Bucket
Location: `apps/web/supabase/schemas/16-storage.sql`
```sql
insert into storage.buckets (id, name, public)
values ('account_image', 'account_image', true)
on conflict (id) do nothing;
create policy account_image on storage.objects for all using (
bucket_id = 'account_image'
and (
kit.get_storage_filename_as_uuid(name) = auth.uid()
or public.has_role_on_account(kit.get_storage_filename_as_uuid(name))
)
)
with check (
bucket_id = 'account_image'
and (
kit.get_storage_filename_as_uuid(name) = auth.uid()
or public.has_permission(
auth.uid(),
kit.get_storage_filename_as_uuid(name),
'settings.manage'
)
)
);
```
## Enum Types
```sql
-- Subscription status
create type public.subscription_status as enum (
'active',
'trialing',
'past_due',
'canceled',
'unpaid',
'incomplete',
'incomplete_expired',
'paused'
);
-- App permissions
create type public.app_permissions as enum (
'settings.manage',
'billing.manage',
'members.manage',
'invitations.manage'
);
```

View File

@@ -0,0 +1,138 @@
# Makerkit Database Patterns
## Schema Location
All schemas are in `apps/web/supabase/schemas/` with numbered prefixes for dependency ordering.
## Existing Helper Functions - DO NOT Recreate
```sql
-- Account Access Control
public.has_role_on_account(account_id uuid, role_name? text)
public.has_permission(user_id uuid, account_id uuid, permission app_permissions)
public.is_account_owner(account_id uuid)
public.has_active_subscription(account_id uuid)
public.is_team_member(account_id uuid, user_id uuid)
public.can_action_account_member(target_account_id uuid, target_user_id uuid)
-- Administrative
public.is_super_admin()
public.is_aal2()
public.is_mfa_compliant()
-- Configuration
public.is_set(field_name text)
```
## RLS Policy Patterns
### Personal + Team Access
```sql
create policy "table_read" on public.table for select
to authenticated using (
account_id = (select auth.uid()) or
public.has_role_on_account(account_id)
);
```
### Permission-Based Access
```sql
create policy "table_manage" on public.table for all
to authenticated using (
public.has_permission(auth.uid(), account_id, 'feature.manage'::app_permissions)
);
```
### Storage Bucket Policy
```sql
create policy bucket_policy on storage.objects for all using (
bucket_id = 'bucket_name'
and (
kit.get_storage_filename_as_uuid(name) = auth.uid()
or public.has_role_on_account(kit.get_storage_filename_as_uuid(name))
)
);
```
## Adding New Permissions
```sql
-- Add to app_permissions enum
ALTER TYPE public.app_permissions ADD VALUE 'feature.manage';
COMMIT;
```
## Standard Table Template
```sql
create table if not exists public.feature (
id uuid unique not null default extensions.uuid_generate_v4(),
account_id uuid references public.accounts(id) on delete cascade not null,
name varchar(255) not null,
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now(),
created_by uuid references auth.users(id),
updated_by uuid references auth.users(id),
primary key (id)
);
-- Enable RLS
alter table "public"."feature" enable row level security;
-- Revoke defaults, grant specific
revoke all on public.feature from authenticated, service_role;
grant select, insert, update, delete on table public.feature to authenticated;
-- Add triggers
create trigger set_timestamps
before insert or update on public.feature
for each row execute function public.trigger_set_timestamps();
create trigger set_user_tracking
before insert or update on public.feature
for each row execute function public.trigger_set_user_tracking();
-- Add indexes
create index ix_feature_account_id on public.feature(account_id);
```
## Migration Workflow
```bash
# New entity: copy schema to migration
pnpm --filter web run supabase migrations new feature_name
# Modify existing: generate diff
pnpm --filter web run supabase:db:diff -f update_feature
# Apply
pnpm --filter web supabase migrations up
# Generate types
pnpm supabase:web:typegen
```
## Security Definer Function Pattern
```sql
create or replace function public.admin_function(target_id uuid)
returns void
language plpgsql
security definer
set search_path = ''
as $$
begin
-- ALWAYS validate permissions first
if not public.is_account_owner(target_id) then
raise exception 'Access denied';
end if;
-- Safe to proceed
end;
$$;
grant execute on function public.admin_function(uuid) to authenticated;
```