ai-coding-rules / rules
Luxvil/ai-coding-rules/.cursor/rules/92-database.mdc
Rules for database schema and migrations
Cursor rule3 starsChanged 8 months ago
- Reads credentials
What's in it
- 🗃️ Database Rules
- Schema Design
- 1. Naming Conventions
- 2. Required Fields (STRICT)
- 3. Indexes
- Migration Rules (STRICT)
- 1. Never Edit Existing Migrations
- 2. Reversible Migrations
- 3. Data Migrations Separate
- Query Patterns
- 1. Parameterized Queries (STRICT)
- 2. Select Only Needed Fields
- 3. Tenant Isolation (STRICT)
- Forbidden Patterns
- Seeding
---
description: Rules for database schema and migrations
globs: ["**/prisma/**", "**/drizzle/**", "**/migrations/**", "**/*.sql", "**/schema.prisma"]
alwaysApply: false
---
# 🗃️ Database Rules
> Auto-activated for Prisma, Drizzle, and SQL files.
## Schema Design
### 1. Naming Conventions
```prisma
// ✅ GOOD
model User {
id String @id @default(cuid())
email String @unique
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("users") // snake_case table name
}
// ✅ Relations: explicit names
model Post {
author User @relation("PostAuthor", fields: [authorId], references: [id])
authorId String @map("author_id")
}
```
### 2. Required Fields (STRICT)
Every table MUST have:
- `id` — Primary key (cuid or uuid preferred)
- `created_at` — Creation timestamp
- `updated_at` — Last update timestamp
For multi-tenant apps:
- `tenant_id` — Tenant isolation (CRITICAL)
### 3. Indexes
```prisma
// ✅ Index frequently queried fields
model Order {
id String @id
userId String
status String
createdAt DateTime
@@index([userId]) // FK queries
@@index([status, createdAt]) // Filtered queries
}
```
## Migration Rules (STRICT)
### 1. Never Edit Existing Migrations
```bash
# ❌ NEVER modify deployed migrations
# ✅ Create new migration for changes
npx prisma migrate dev --name fix_user_email
```
### 2. Reversible Migrations
```sql
-- ✅ Always provide rollback
-- Migration: add_status_column
ALTER TABLE orders ADD COLUMN status VARCHAR(20) DEFAULT 'pending';
-- Rollback:
-- ALTER TABLE orders DROP COLUMN status;
```
### 3. Data Migrations Separate
```
migrations/
├── 001_add_status_column.sql # Schema only
└── 001_backfill_status.ts # Data migration (separate)
```
## Query Patterns
### 1. Parameterized Queries (STRICT)
```typescript
// ✅ ALWAYS use parameterized queries
const user = await prisma.user.findUnique({
where: { email: sanitizedEmail }
});
// ❌ NEVER concatenate SQL
const query = `SELECT * FROM users WHERE email = '${email}'`; // SQL INJECTION!
```
### 2. Select Only Needed Fields
```typescript
// ✅ GOOD: Select specific fields
const users = await prisma.user.findMany({
select: { id: true, email: true, name: true }
});
// ❌ BAD: Select all (may include sensitive data)
const users = await prisma.user.findMany();
```
### 3. Tenant Isolation (STRICT)
```typescript
// ✅ ALWAYS filter by tenant
const orders = await prisma.order.findMany({
where: {
tenantId: session.tenantId, // CRITICAL
status: 'pending'
}
});
```
## Forbidden Patterns
```typescript
// ❌ NEVER: Raw queries with interpolation
await prisma.$queryRaw`SELECT * FROM users WHERE id = ${userId}`;
// ✅ USE: Prisma.sql for safe interpolation
await prisma.$queryRaw(Prisma.sql`SELECT * FROM users WHERE id = ${userId}`);
// ❌ NEVER: Cascade delete without confirmation
await prisma.user.delete({ where: { id } }); // May delete related data!
// ❌ NEVER: Skip tenant check
await prisma.order.findMany({ where: { status: 'pending' } }); // Cross-tenant leak!
```
## Seeding
```typescript
// seed.ts - for development only
async function seed() {
// Clear existing data (dev only!)
if (process.env.NODE_ENV === 'development') {
await prisma.user.deleteMany();
}
// Create test data
await prisma.user.create({
data: {
email: 'test@example.com',
name: 'Test User',
}
});
}
```
More agent context in Luxvil/ai-coding-rules
24 other files this repository gives its agents.
CLAUDE.md
Copilot instructions
Cursor rule
- .cursor/rules/00-global.mdc
- .cursor/rules/10-output-contract.mdc
- .cursor/rules/20-security-privacy.mdc
- .cursor/rules/30-testing.mdc
- .cursor/rules/40-context-memory.mdc
- .cursor/rules/50-mcp-tools.mdc
- .cursor/rules/60-stack-frontend.mdc
- .cursor/rules/61-stack-backend.mdc
- .cursor/rules/62-stack-python.mdc
- .cursor/rules/63-stack-db.mdc
- .cursor/rules/64-stack-rust.mdc
- .cursor/rules/65-stack-supabase.mdc
- .cursor/rules/66-stack-shadcn.mdc
- .cursor/rules/67-stack-nextjs15.mdc
- .cursor/rules/71-git-workflow.mdc
- .cursor/rules/72-refactoring.mdc
- .cursor/rules/73-error-handling.mdc
- .cursor/rules/74-api-design.mdc
- .cursor/rules/80-vibe-coding.mdc
- .cursor/rules/90-ui-components.mdc
- .cursor/rules/91-api-routes.mdc
- .cursor/rules/93-state-management.mdc
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
Reports can't be read right now.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

