---
paths:
  - "src/models/**"
  - "alembic/**"
  - "migrations/**"
---

# 数据库规则（Clover · MySQL + Alembic）

> 承接架构方案v0.3 第三章（16表）。一期建14张，matrix_accounts/preference_profile 二期预留。

## 迁移
- 每次 schema 变更创建迁移文件，不手动改数据库
- 迁移文件不可修改已提交的，只能新增
- 迁移必须包含 up 和 down
- 按序：001(banana搬3张) → 002(多租户基础) → 003(业务7张) → 004(飞轮)

## 查询
- 禁止 SELECT *，明确列出字段
- 大表查询必须有索引支撑，新增查询模式时同步加索引
- N+1 问题：关联查询用 JOIN 或批量加载
- 飞轮聚合走 MySQL JOIN（MongoDB 只存 AI debug trace，业务不依赖）

## 命名
- 表名：snake_case 复数（users, generation_tasks, preference_events）
- 字段名：snake_case（created_at, workspace_id）
- 索引名：idx_表名_字段名

## 关键约束（架构方案）
- 任务主键：自增 BIGINT + mongo_trace_id VARCHAR(24)
- user_api_keys：UNIQUE(user_id, workspace_id, provider)
- 所有业务表必须有 workspace_id（多租户逻辑隔离）
- preference_events 必须有 workspace_id + product_id（跨公司隔离+按产品分开学）

## 状态机（generation_tasks.status）
pending → generating → pending_selection → pending_review → approved/rejected → archived
- 打回后回到 pending_selection
- 非法流转返错误码 40901

## 字段红线
- API Key 字段：encrypted_key（Fernet），**不存 url 字段**（token站固定自家站）
- users 表：删除 banana 的 credits 字段
- eval_score：留 NULL（不接 banana 假评分）
- data_ownership：client_data / platform_asset（洞7分层归属）
- banned_words.level：auto_fix / soft_warn / hard_block（三级）

## 枚举约束
- DB 枚举约束要有对应代码侧常量文件（消除三套命名打架）
- 品类（products.category）是纯数据字段，禁止任何品类枚举常量
