文档核心
This commit is contained in:
262
Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md
Normal file
262
Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md
Normal file
@@ -0,0 +1,262 @@
|
||||
`DATA_MODEL.md` 的核心目标是:**让 AI 在触碰任何数据相关代码时,都能理解业务语义,而不只是看到一堆字段名。**
|
||||
|
||||
---
|
||||
|
||||
### 必须包含的内容
|
||||
|
||||
#### 1. 领域概览(Domain Overview)
|
||||
|
||||
用业务语言(不是技术语言)描述核心概念和它们的关系。这是 AI 理解"为什么"的基础。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Domain Overview
|
||||
|
||||
This is a **multi-tenant** project management tool.
|
||||
|
||||
Core concepts:
|
||||
- **Workspace**: The top-level container, maps to a paying customer (company)
|
||||
- **Project**: Lives inside a Workspace, has a lifecycle (draft → active → archived)
|
||||
- **Task**: The atomic unit of work, always belongs to a Project
|
||||
- **Member**: A User's role within a specific Workspace (not global)
|
||||
|
||||
Key business rules:
|
||||
- A User can belong to multiple Workspaces with different roles
|
||||
- Deleting a Project soft-deletes all its Tasks (never hard delete)
|
||||
- Only Workspace `owner` or `admin` can invite new Members
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. 实体关系图(Entity Relationship)
|
||||
|
||||
用文字或 ASCII 图表达清楚关系,不要依赖读者去脑补。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Entity Relationships
|
||||
|
||||
Workspace (1) ──── (N) Project
|
||||
Workspace (1) ──── (N) Member
|
||||
Member (N) ──── (1) User ← same User, different roles per Workspace
|
||||
Project (1) ──── (N) Task
|
||||
Task (N) ──── (1) Member ← assignee
|
||||
Task (1) ──── (N) Comment
|
||||
Task (N) ──── (N) Tag ← via task_tags join table
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 3. 完整 Schema 定义(Schema Definition)
|
||||
|
||||
每个表都需要:字段 + 类型 + 约束 + **业务注释**。注释是给 AI 的关键上下文。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Schema
|
||||
|
||||
### workspaces
|
||||
| Column | Type | Constraints | Notes |
|
||||
|--------------|-------------|-------------------|--------------------------------|
|
||||
| id | uuid | PK, default gen | |
|
||||
| slug | text | UNIQUE, NOT NULL | URL identifier, immutable after creation |
|
||||
| name | text | NOT NULL | |
|
||||
| plan | text | NOT NULL | enum: 'free' | 'pro' | 'enterprise' |
|
||||
| created_at | timestamptz | NOT NULL, default now() | |
|
||||
| deleted_at | timestamptz | nullable | soft delete, filter WHERE deleted_at IS NULL |
|
||||
|
||||
### members
|
||||
| Column | Type | Constraints | Notes |
|
||||
|--------------|-------------|-------------------|--------------------------------|
|
||||
| id | uuid | PK | |
|
||||
| workspace_id | uuid | FK → workspaces.id, CASCADE DELETE | |
|
||||
| user_id | uuid | FK → users.id | |
|
||||
| role | text | NOT NULL | enum: 'owner' \| 'admin' \| 'member' \| 'viewer' |
|
||||
| invited_by | uuid | FK → members.id, nullable | null = founding owner |
|
||||
| joined_at | timestamptz | nullable | null = invitation pending |
|
||||
|
||||
-- UNIQUE(workspace_id, user_id) — one membership per workspace per user
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 4. 枚举与常量(Enums & Constants)
|
||||
|
||||
把所有枚举值集中在一处,AI 就不会自己发明状态值。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Enums & Constants
|
||||
|
||||
### Task Status (ordered, represents workflow progression)
|
||||
pending → in_progress → in_review → done → cancelled
|
||||
|
||||
Rules:
|
||||
- Only forward transitions are allowed (no reopening cancelled tasks)
|
||||
- `done` and `cancelled` are terminal states
|
||||
- Changing status logs an entry in task_activity
|
||||
|
||||
### Member Role Permissions
|
||||
| Action | owner | admin | member | viewer |
|
||||
|---------------------|-------|-------|--------|--------|
|
||||
| Invite members | ✅ | ✅ | ❌ | ❌ |
|
||||
| Delete project | ✅ | ❌ | ❌ | ❌ |
|
||||
| Create tasks | ✅ | ✅ | ✅ | ❌ |
|
||||
| Comment on tasks | ✅ | ✅ | ✅ | ✅ |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 5. 索引策略(Indexes)
|
||||
|
||||
告诉 AI 哪些查询是热路径,避免它写出全表扫描的代码。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Indexes
|
||||
|
||||
-- tasks is the most queried table, optimize for these patterns:
|
||||
CREATE INDEX idx_tasks_project_status ON tasks(project_id, status) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_tasks_assignee ON tasks(assignee_id) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_members_user ON members(user_id); -- "get all workspaces for a user"
|
||||
|
||||
-- Avoid: never query tasks without a project_id filter
|
||||
-- Avoid: never do SELECT * on tasks, always select specific columns
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 6. 软删除约定(Soft Delete Convention)
|
||||
|
||||
如果使用软删除,必须明确说明规则,否则 AI 会写出漏掉过滤条件的查询。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Soft Delete Convention
|
||||
|
||||
Tables with soft delete: workspaces, projects, tasks
|
||||
|
||||
Rules:
|
||||
- ALL queries MUST include `WHERE deleted_at IS NULL` unless explicitly retrieving deleted records
|
||||
- Use `deletedAt: new Date()` to soft delete, never use DELETE SQL
|
||||
- Cascading: deleting a Project sets deleted_at on all its Tasks in the same transaction
|
||||
- Deleted records are purged by a cron job after 30 days (hard delete)
|
||||
|
||||
⚠️ AI Note: Never generate a query on these tables without the soft delete filter.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 7. 多租户隔离规则(Multi-tenancy Rules)
|
||||
|
||||
这是安全的核心,必须让 AI 理解每次查询都要带租户过滤。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Multi-tenancy & Data Isolation
|
||||
|
||||
This is a **workspace-scoped** multi-tenant system.
|
||||
|
||||
Rules:
|
||||
- EVERY query involving projects, tasks, members MUST be scoped by workspace_id
|
||||
- Never query tasks directly by id alone — always join through project → workspace
|
||||
- The workspace_id must come from the authenticated session, never from user input
|
||||
- Row Level Security (RLS) is enabled on Supabase for all tenant tables
|
||||
|
||||
Correct pattern:
|
||||
SELECT * FROM tasks
|
||||
JOIN projects ON tasks.project_id = projects.id
|
||||
WHERE projects.workspace_id = :workspaceId ← always present
|
||||
AND tasks.id = :taskId
|
||||
|
||||
Wrong pattern (security hole):
|
||||
SELECT * FROM tasks WHERE id = :taskId ← missing tenant scope
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 8. 核心查询模式(Common Query Patterns)
|
||||
|
||||
把最常用的查询写出来,AI 会直接复用,而不是重新发明。
|
||||
|
||||
md
|
||||
|
||||
````md
|
||||
## Common Query Patterns
|
||||
|
||||
### Get tasks for a project (with assignee info)
|
||||
```sql
|
||||
SELECT t.*, m.user_id, u.name as assignee_name
|
||||
FROM tasks t
|
||||
LEFT JOIN members m ON t.assignee_id = m.id
|
||||
LEFT JOIN users u ON m.user_id = u.id
|
||||
WHERE t.project_id = :projectId
|
||||
AND t.deleted_at IS NULL
|
||||
ORDER BY t.created_at DESC;
|
||||
```
|
||||
|
||||
### Check if user has permission in workspace
|
||||
```sql
|
||||
SELECT role FROM members
|
||||
WHERE workspace_id = :workspaceId
|
||||
AND user_id = :userId
|
||||
AND joined_at IS NOT NULL; -- pending invitations don't count
|
||||
```
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
#### 9. 明确禁止的操作(Forbidden Operations)
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Forbidden Operations
|
||||
|
||||
- ❌ Never hard DELETE on workspaces, projects, or tasks — use soft delete
|
||||
- ❌ Never UPDATE a task's status by skipping intermediate states
|
||||
- ❌ Never expose internal UUIDs in URLs — use slugs for workspaces/projects
|
||||
- ❌ Never store user PII (email, name) in tasks or comments — always join from users table
|
||||
- ❌ Never write a migration that drops a column without a deprecation period
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 10. 数据迁移约定(Migration Convention)
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Migration Convention
|
||||
|
||||
- Migration tool: Drizzle Kit
|
||||
- File naming: `0001_create_workspaces.ts`, sequential, never rename
|
||||
- Every migration must be reversible (include `down` function)
|
||||
- Never edit a migration that has been merged to main
|
||||
- Backfill scripts go in /scripts, not in migrations
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 内容优先级总结
|
||||
|
||||
|优先级|内容|为什么关键|
|
||||
|---|---|---|
|
||||
|🔴 必须|领域概览 + 业务规则|AI 需要理解"为什么"才能做正确取舍|
|
||||
|🔴 必须|完整 Schema + 字段注释|防止字段命名歧义和类型错误|
|
||||
|🔴 必须|软删除 + 多租户规则|安全漏洞和数据污染的高发区|
|
||||
|🟡 重要|枚举常量 + 状态机|防止 AI 自己发明状态值|
|
||||
|🟡 重要|常用查询模式|复用 > 重新发明|
|
||||
|🟢 加分|索引策略|引导 AI 写出性能友好的查询|
|
||||
|🟢 加分|迁移约定|保持 schema 演进的可控性|
|
||||
|
||||
---
|
||||
|
||||
**核心原则**:`DATA_MODEL.md` 写的不是给数据库看的 DDL,而是给 AI 看的**业务契约**。每一个"显而易见"的业务规则,在 AI 眼里都是需要被明确告知的约束。没写的,它都会自己猜。
|
||||
Reference in New Issue
Block a user