include AGENTS guidance updates, plan doc replacements, and utility script changes left in working tree
26 KiB
Plan: social-app 数据库数据模型重设计(支持社交/事项/自动化)
Date: 2026-02-26 Author: AI Assistant Status: Draft
枚举存储约定
统一使用枚举名称(字符串)存储,不使用整数值。
- 数据库层:
VARCHAR(20)+CHECK约束 - 代码层:Python
Enum类继承str - 优势:调试可读、易扩展(新增枚举值无需迁移旧数据)、ORM 友好
class AgentType(str, Enum):
INTENT_RECOGNITION = "INTENT_RECOGNITION"
TASK_EXECUTION = "TASK_EXECUTION"
RESULT_REPORTING = "RESULT_REPORTING"
-- Migration
ALTER TABLE user_agents ADD CONSTRAINT chk_agent_type
CHECK (agent_type IN ('INTENT_RECOGNITION', 'TASK_EXECUTION', 'RESULT_REPORTING'));
Overview
本方案面向 social-app 的下一阶段功能升级,重设计 PostgreSQL 数据模型,统一支持用户专属 agent、好友/群组协作、待处理消息、设置、可订阅且可授权编辑的日程事项、待办联动与自动化定时任务。目标是在 FastAPI + Flutter 协作场景下提供长期稳定的数据基础,降低后续 API 演进和跨端同步复杂度。
Requirements
Functional
- 每个用户有专属 agent,且模型可扩展到未来多 agent 能力
- 用户支持好友关系、群组创建与成员管理
- 用户支持 inbox/pending 待处理消息
- 用户支持个性化设置(偏好/隐私/通知)
- 用户支持“绑定日程的事项”,可多人订阅,且仅特定人可修改
- 用户支持待办事项(可由日程事项提取,也可手动创建)
- 用户支持自动化定时任务(循环触发)
Non-Functional
- 性能:核心读路径(inbox 列表、待办列表、事项列表)P95 < 150ms(单用户典型数据量)
- 安全:权限以后端业务授权为准;数据库层保留 RLS 防御边界
- 一致性:关键写路径(好友状态、权限变更、任务触发)使用事务保障
- 可演进:当前阶段采用重建库快速迭代;后续稳定后切换为增量迁移与灰度
Technical Approach
采用“认证域(auth.users)+ 业务域(public.*)”分层建模。保持 auth.users 作为身份主键来源,业务表统一引用 user_id UUID -> auth.users.id。领域边界拆分为:Identity/Profile、Social Graph、Collaboration(事项/订阅/权限)、Inbox、Todo、Automation。通过“规范化主模型 + 局部物化/冗余快照”平衡一致性与查询性能。
Key Decisions
| Decision | Rationale |
|---|---|
| 用户与 agent 采用 1:1 主约束 + 可扩展结构 | 当前满足"每用户专属 agent",未来允许多 agent 形态演进 |
| 记忆系统采用单表 + memory_type 区分 | user 类型可选 agent_id,work 类型必须绑定 agent_id |
| 好友关系用单表双向规范化表示 | 避免 A-B / B-A 重复,降低去重成本 |
| 事项权限采用 ACL 表而非仅 owner | 满足“仅特定人可修改”的协作场景 |
| 待办采用主表 + 关联表 | todos + todo_sources 保证来源关系可校验 |
| 自动化采用 Jobs 单表 + Sessions 关联 | sessions 通过 session_type + job_id 区分普通对话与自动化运行 |
| inbox 采用单表接收者视角 | 发送者 + 消息类型 + 关联业务,一表搞定待处理消息 |
A. 设计原则与边界
1) 核心实体与聚合边界
- 用户聚合:
profiles(含 settings JSONB),user_agents,memories - 社交聚合:
friendships,groups,group_members - 协作事项聚合:
schedule_items,schedule_subscriptions(当前仅用户主体) - 消息聚合:
inbox_messages - 待办聚合:
todos - 自动化聚合:
automation_jobs
2) 一致性分级
- 强一致(同事务):好友关系状态迁移、群组成员角色变更、事项权限写入、定时任务抢占执行
- 最终一致:inbox 衍生、待办同步、提醒派发(允许异步补偿)
3) 多租户假设
- 默认假设:单租户产品(同一业务库服务所有用户),以
user_id做数据隔离 - 扩展预留:各核心表可预留
tenant_id UUID NULL(需业务确认是否近期引入组织空间)
B. 领域模型与关系图(文字化)
实体与关系
auth.users (1) - (1) profiles(settings 作为 JSONB 内嵌)auth.users (1) - (1) user_agentsauth.users (1) - (N) memoriesuser_agents (1) - (N) memories(work 类型)auth.users (N) - (N) auth.users通过friendshipsauth.users (1) - (N) groups(创建者)groups (1) - (N) group_members,auth.users (1) - (N) group_membersauth.users (1) - (N) schedule_items(创建者)schedule_items (1) - (N) schedule_subscriptions,auth.users (1) - (N) schedule_subscriptionsauth.users (1) - (N) inbox_messagesauth.users (1) - (N) todosauth.users (1) - (N) automation_jobsautomation_jobs (1) - (N) sessions(通过sessions.job_id关联)
关键约束
- 唯一性:
user_agents.user_id唯一friendships(user_low_id, user_high_id)唯一group_members(group_id, user_id)唯一schedule_subscriptions(item_id, subscriber_id)唯一
- CHECK:
friendships:user_low_id < user_high_id且user_low_id <> user_high_idschedule_subscriptions:permission BETWEEN 0 AND 7memories:work类型必须有agent_id,user类型必须无agent_idsessions:session_type/job_id组合一致
- 外键:统一显式
ON DELETE策略(见下) - 可空性:权限关键字段、状态字段默认
NOT NULL - 删除策略:
- 用户删除:大部分
CASCADE(用户私有数据);跨用户协作数据优先软删 - 事项删除:对子表
CASCADE;待办保留历史,改status = 'archived'
- 用户删除:大部分
外键删除策略明细(必做)
sessions.job_id -> automation_jobs.id:ON DELETE RESTRICTtodo_sources.todo_id -> todos.id:ON DELETE CASCADEtodo_sources.schedule_item_id -> schedule_items.id:ON DELETE CASCADEinbox_messages.friendship_id -> friendships.id:ON DELETE CASCADEinbox_messages.schedule_item_id -> schedule_items.id:ON DELETE CASCADEinbox_messages.group_id -> groups.id:ON DELETE CASCADE
C. 数据库表设计(PostgreSQL)
以下为推荐主表(方案 1,规范化优先)。字段示例采用 UUID + timestamptz + enum/text-check。
1) 用户与 agent
profiles(已有,建议补齐)
- PK:
id UUID(auth.users.id) - 关键字段:
username,avatar_url,bio - 新增 JSONB 字段:
settings JSONB(用户自定义设置,含version,preferences,privacy,notification四大块)
- 时间字段:
created_at,updated_at,deleted_at - 索引:
INDEX(username)(允许重名,仅用于列表查询)GIN(settings)(支持 JSONB 表达式查询)- 表达式索引:
(settings->'notification'->>'enabled')(按需,对高频查询字段单独建)
- 审计:
created_by,updated_by(可等于 id) - 删除策略: 用户删除时
CASCADE
user_agents
- PK:
id UUID - 关键字段:
user_id UNIQUE(每用户专属 agent)llm_id UUID NOT NULL(关联绑定的 LLM 模型)agent_type VARCHAR(20) NOT NULL(枚举限制:INTENT_RECOGNITION|TASK_EXECUTION|RESULT_REPORTING)config JSONB(agent 配置参数)
- 时间字段:
created_at,updated_at,deleted_at - 状态字段:
status(active|paused|migrating) - 索引:
UNIQUE(user_id) WHERE deleted_at IS NULLINDEX(status)INDEX(agent_type)GIN(config)(按需)
- 审计:
created_by,updated_by
memories
- PK:
id UUID - 关键字段:
owner_id(用户,NOT NULL)agent_id(work 类型时必需)memory_type(枚举:user | work)titlecontent(JSONB,存储具体记忆结构)source(manual | agent | imported)
- 时间字段:
created_at,updated_at - 状态字段:
status(active | disabled) - 索引:
INDEX(owner_id, memory_type, status)INDEX(agent_id, memory_type, status)GIN(content)(支持 JSONB 内容查询)
- 约束:
CHECK ((memory_type = 'work' AND agent_id IS NOT NULL) OR (memory_type = 'user' AND agent_id IS NULL))
memory_type 说明:
| 类型 | agent_id | 说明 |
|---|---|---|
user |
可空 | 用户记忆:偏好、背景信息、实体等 |
work |
必需 | 工作记忆:长期运行后对工作流程的经验整理,避免重复错误 |
content JSONB 示例:
// 用户记忆
{"type": "preference", "data": {"style": "concise", "language": "zh-CN"}}
// 工作记忆
{"type": "workflow_summary", "data": {"task": "代码审查", "learnings": ["优先检查安全漏洞", "关注性能热点"], "improvements": []}}
2) 社交关系
friendships
- PK:
id UUID - 关键字段:
user_low_id(两者中较小的 UUID)user_high_id(两者中较大的 UUID)initiator_id(发起请求方的 user_id,用于追溯谁主动)status,requested_at,accepted_at,blocked_by
- 时间字段:
created_at,updated_at - 状态字段:
status(pending|accepted|blocked|declined|canceled) - 约束:
CHECK(user_low_id < user_high_id)(强制小值放 low,大值放 high,确保 A→B 和 B→A 是同一行)CHECK(initiator_id IN (user_low_id, user_high_id))UNIQUE(user_low_id, user_high_id)
- 索引:
INDEX(user_low_id, status)INDEX(user_high_id, status)- 部分索引
INDEX(status) WHERE status='pending'
- 审计:
created_by,updated_by
查询示例:
- 查询用户 A 的所有好友:
SELECT * FROM friendships WHERE user_low_id = A OR user_high_id = A
groups
- PK:
id UUID - 关键字段:
name,description,owner_id - 时间字段:
created_at,updated_at,deleted_at - 状态字段:
status(active|archived) - 索引:
INDEX(owner_id, status) - 审计:
created_by,updated_by
group_members
- PK:
id UUID - 关键字段:
group_id,user_idrole(枚举:owner|admin|member)join_source(invited|joined)invited_by,joined_at
- 时间字段:
created_at,updated_at,removed_at - 状态字段:
status(active|muted|removed) - 约束:
UNIQUE(group_id, user_id) - 索引:
INDEX(group_id, role, status)INDEX(user_id, status)
- 审计:
created_by,updated_by
role 说明:
| role | 含义 |
|---|---|
owner |
群主/创建者 |
admin |
管理员 |
member |
普通成员 |
- 角色可升降:服务层变更 role 字段即可
3) 用户设置(已合并至 profiles 表)
用户设置采用 JSONB 内嵌方式,渐进式扩展无需改表结构:
{
"version": 1,
"preferences": {
"interface_language": "zh-CN",
"ai_language": "zh-CN",
"timezone": "Asia/Shanghai"
},
"privacy": {},
"notification": {}
}
- 索引策略:对高频查询字段使用表达式索引
- 更新方式:服务层使用 JSONB merge 或字段级 UPDATE,避免读-改-写并发问题(建议用
jsonb_set原子操作)
4) 事项与订阅/权限
schedule_items
- PK:
id UUID - 关键字段:
owner_idtitledescriptionstart_atend_attimezone(用于将日程时间转换为用户本地时间显示)metadata(JSONB,扩展字段)recurrence_rule(可选,支持循环日程)source_type(manual | imported | agent_generated)
- 时间字段:
created_at,updated_at - 状态字段:
status(active | completed | canceled | archived) - 索引:
INDEX(owner_id, start_at)INDEX(status, start_at)
- 审计:
created_by
metadata JSONB 示例:
{
"color": "#FF6B6B",
"location": "会议室A",
"notes": "记得提前准备投影仪",
"attachments": [
{
"name": "会议纪要.pdf",
"url": "https://...",
"visible_to": [],
"type": "document"
},
{
"name": "投影仪提醒",
"visible_to": ["uuid1"],
"type": "reminder",
"content": "记得带投影仪"
},
{
"name": "技术方案.docx",
"url": "https://...",
"visible_to": ["uuid2"],
"type": "document",
"note": "需要他确认预算"
}
],
"version": 1
}
| type | 说明 | 特殊字段 |
|---|---|---|
| document | 文档/文件 | url, note |
| reminder | 提醒 | content |
schedule_subscriptions
- PK:
id UUID - 关键字段:
item_idsubscriber_idpermission(INTEGER,用位运算存储权限组合,NOT NULL DEFAULT 1)notify_level(all | mentions | none,NOT NULL DEFAULT 'all')
- 时间字段:
created_at - 状态字段:
status(active | paused | unsubscribed,NOT NULL DEFAULT 'active') - 约束:
UNIQUE(item_id, subscriber_id) - 约束补充:
CHECK(permission BETWEEN 0 AND 7)(view=1, invite=2, edit=4,0表示无权限) - 索引:
INDEX(subscriber_id, status),INDEX(item_id, status) - 审计:
created_by
权柄说明(位运算):
| 权柄 | 值 | 二进制 | 说明 |
|---|---|---|---|
| view | 1 | 001 | 查看事项详情 |
| invite | 2 | 010 | 邀请其他人订阅此事项 |
| edit | 4 | 100 | 修改事项内容、管理订阅 |
- 权限检查:
permission & 2 = 2检查是否有 invite 权限 - 权限添加:
permission | 2添加 invite 权限 - 事项 owner 默认拥有全部权柄:
7(111) - owner 权柄由服务层恒等判定为
7,不依赖 owner 是否在schedule_subscriptions中存在记录
当前版本边界:
schedule_subscriptions仅支持用户订阅(subscriber_id -> auth.users.id)- 事项协作暂不引入群主体授权
5) 待处理消息(Inbox)
inbox_messages
- PK:
id UUID - 关键字段:
recipient_id(接收者)sender_id(发送者,系统消息可为 NULL)message_type(枚举:friend_request | calendar | system | group)friendship_id(可空,friend_request时必填)schedule_item_id(可空,calendar时必填)group_id(可空,group时必填)content(TEXT,消息内容,系统消息用)
- 时间字段:
created_at - 状态字段:
is_read(BOOLEAN,是否已读)status(pending | accepted | rejected | dismissed)
- 索引:
INDEX(recipient_id, status, created_at DESC)- 部分索引
INDEX(recipient_id, created_at DESC) WHERE status='pending'
- 审计:
created_by
message_type 与业务字段对应关系:
| message_type | 对应业务字段 |
|---|---|
| friend_request | friendship_id -> friendships.id |
| calendar | schedule_item_id -> schedule_items.id |
| system | 三个业务字段均为 NULL(内容直接在 content) |
| group | group_id -> groups.id |
说明:一张表搞定,接收者视角,通过 message_type + 对应业务字段 直接定位要处理的业务,避免单列多态外键带来的引用不一致问题。
一致性约束(必做):
- 使用
CHECK保证不同message_type下仅允许对应业务字段非空(system时业务字段全空) - 使用
CHECK保证message_type='system'时sender_id IS NULL,否则sender_id IS NOT NULL friendship_id、schedule_item_id、group_id分别建立 FK,并显式声明ON DELETE策略
6) 待办
todos
- PK:
id UUID - 关键字段:
owner_idtitledescriptiondue_atpriority(INTEGER,用于四象限:1=重要且紧急, 2=重要不紧急, 3=紧急不重要, 4=不重要不紧急)
- 时间字段:
created_at,completed_at - 状态字段:
status(pending | done | canceled) - 索引:
INDEX(owner_id, status, due_at)INDEX(owner_id, created_at DESC)- 部分索引
INDEX(owner_id, due_at) WHERE status='pending'
- 审计:
created_by
todo_sources
- PK:
id UUID - 关键字段:
todo_id(FK -> todos.id)schedule_item_id(FK -> schedule_items.id)
- 时间字段:
created_at - 约束:
UNIQUE(todo_id, schedule_item_id) - 索引:
INDEX(todo_id),INDEX(schedule_item_id)
说明:
- 手动创建待办:不写
todo_sources - 从事项提取待办:写入
todo_sources,替代 JSONB 数组,保证来源关系可校验
7) 自动化定时任务
automation_jobs
- PK:
id UUID - 关键字段:
owner_idtitle(任务标题)prompt(AI 执行的 prompt)schedule_type(枚举:daily | weekly)run_at(首次运行时间)next_run_at(下次运行时间,调度器扫描主字段)timezone(时区,如Asia/Shanghai)last_run_at(最近运行时间,可空)
- 时间字段:
created_at,updated_at - 状态字段:
status(active | disabled) - 索引:
INDEX(owner_id, status),INDEX(status, next_run_at) - 约束补充:
UNIQUE(id, owner_id)(用于sessions(job_id, user_id)归属一致性外键) - 审计:
created_by
说明:定时任务执行时,在 sessions 表创建记录存储 AI 对话内容。
8) 会话表扩展(已有 sessions)
sessions(更新)
- 新增字段:
session_type(chat | automation)job_id(可空,FK -> automation_jobs.id)
- 一致性约束:
CHECK((session_type = 'chat' AND job_id IS NULL) OR (session_type = 'automation' AND job_id IS NOT NULL))- 通过复合 FK 约束归属一致性:
FOREIGN KEY(job_id, user_id) -> automation_jobs(id, owner_id)
- 索引:
INDEX(user_id, session_type, last_activity_at DESC)INDEX(job_id)
D. 权限与协作模型
1) 事项权限落表
- 权限直接存储在
schedule_subscriptions.permission整数中(位运算) - owner 不写入
schedule_subscriptions,owner 权限仅由schedule_items.owner_id推导 - 权限决策顺序:
schedule_items.owner_id→ 服务层恒等全部权柄["view", "invite", "edit"](7)schedule_subscriptions中该用户的permission位图- 非 owner 且非 subscriber 默认无权限(0)
2) 当前版本边界
- 事项权限仅处理用户主体(owner + subscriber)
- 群组与事项权限继承关系不在本期范围
E. 消息与待办联动
1) inbox 关联业务对象
inbox_messages.message_type枚举:friend_request(好友请求)→friendship_id指向 friendshipscalendar(日程邀请)→schedule_item_id指向 schedule_itemssystem(系统消息)→ 业务字段均为 NULLgroup(群组邀请)→group_id指向 groups
- 通过
message_type + 对应业务字段直接定位业务对象,并用CHECK约束保证字段一致性
2) 待办来源提取
- 从事项提取待办时,写入
todo_sources(todo_id, schedule_item_id) - 手动创建的待办不写
todo_sources - 支持多来源:同一待办可关联多个日程事项(多行
todo_sources) - 待办完成时无需反向更新来源事项状态(简化设计)
F. 定时任务模型
1) 调度规则
schedule_type枚举:daily(每日) |weekly(每周)run_at用于首次执行时间,next_run_at用于后续调度- 调度器扫描
status='active' AND next_run_at <= now()的任务,执行后回写下一次next_run_at timezone参与下一次执行时间计算,避免时区偏差
2) 执行记录
- 每次执行在 sessions 表创建记录,通过
sessions.job_id关联 job sessions通过session_type区分chat与automation- 执行失败时记录在
automation_jobs(如last_error,可后续细化)
G. 数据库迁移思路
策略:重建数据库 + Alembic ORM 迁移
由于是全新设计的数据模型,且当前处于开发初期(可清除旧数据),采用重建数据库策略:
执行门禁(强制):
- 仅允许在本地开发环境执行
- 禁止在生产/共享环境执行
rm backend/alembic/versions/*.py - 执行前必须备份数据库或创建 git tag
- 删除所有旧 migration 脚本(保留
env.py) - 创建 ORM 模型文件
- 生成 Alembic migration
- 重建数据库并执行迁移
执行步骤
-
删除旧 migration 文件
rm backend/alembic/versions/*.py -
重建空数据库(确保以空库基线生成 initial migration)
docker compose --env-file .env -f infra/docker/docker-compose.yml down -v docker compose --env-file .env -f infra/docker/docker-compose.yml up -d db -
创建 ORM 模型文件(参考
models/目录结构)- 新增:
user_agents.py,memories.py,friendships.py,groups.py,group_members.py,schedule_items.py,schedule_subscriptions.py,inbox_messages.py,todos.py,todo_sources.py,automation_jobs.py - 更新:
profile.py- 添加settings字段 - 更新:
agent_chat_session.py- 添加session_type、job_id字段 - 重写:
create_profile_for_new_user触发器,确保profiles.settings有默认值
- 新增:
-
更新
models/__init__.py导出所有模型 -
更新
alembic/env.py添加模型导入 -
生成 initial migration(以空库为对比基线)
cd backend && uv run alembic revision --autogenerate -m "initial schema" -
为所有新建
public业务表补齐 RLS(SELECT/INSERT/UPDATE/DELETEpolicy)- 每张表都执行
ENABLE ROW LEVEL SECURITY - 每张表都显式创建
SELECT/INSERT/UPDATE/DELETEpolicy - downgrade 必须可逆,不得弱化既定安全边界
anon/authenticated默认全部 deny
RLS 最小策略矩阵(本期统一模板):
anon:SELECT/INSERT/UPDATE/DELETE全部 denyauthenticated:SELECT/INSERT/UPDATE/DELETE全部 denyservice_role:由后端服务连接使用,不依赖 RLS 放行
- 每张表都执行
-
执行迁移
cd backend && uv run alembic upgrade head -
验证表结构
H. 交付物
ORM 模型文件清单
| 文件 | 说明 |
|---|---|
models/user_agents.py |
用户专属 agent |
models/memories.py |
用户/工作记忆 |
models/friendships.py |
好友关系 |
models/groups.py |
群组 |
models/group_members.py |
群组成员 |
models/schedule_items.py |
日程事项 |
models/schedule_subscriptions.py |
日程订阅与权限 |
models/inbox_messages.py |
待处理消息 |
models/todos.py |
待办 |
models/todo_sources.py |
待办与事项来源关联 |
models/automation_jobs.py |
定时任务 |
models/profile.py |
更新:添加 settings 字段 |
models/agent_chat_session.py |
更新:添加 session_type、job_id 字段 |
执行步骤
-
删除旧 migration 文件
rm backend/alembic/versions/*.py -
重建空数据库(确保以空库基线生成 initial migration)
docker compose --env-file .env -f infra/docker/docker-compose.yml down -v docker compose --env-file .env -f infra/docker/docker-compose.yml up -d db -
创建/更新 ORM 模型文件
-
更新
models/__init__.py导出所有模型 -
更新
alembic/env.py添加模型导入 -
生成 initial migration(以空库为对比基线)
cd backend && uv run alembic revision --autogenerate -m "initial schema" -
为所有新建
public业务表补齐 RLS(SELECT/INSERT/UPDATE/DELETEpolicy)- 每张表都执行
ENABLE ROW LEVEL SECURITY - 每张表都显式创建
SELECT/INSERT/UPDATE/DELETEpolicy - downgrade 必须可逆,不得弱化既定安全边界
- 每张表都执行
-
执行迁移
cd backend && uv run alembic upgrade head -
更新测试文件适配新表结构
I. 数据库表名规范与审计
1) 命名规范(统一执行)
- 使用
snake_case - 业务表统一使用复数名词(如
profiles,friendships,automation_jobs) - 关联表使用
<主实体复数>_<从实体复数>或约定俗成复数短语(如group_members,todo_sources) - 禁止过于泛化的表名(如
messages,sessions),必须带业务前缀 - 存量历史表允许短期例外,但必须在审计表中登记并给出迁移计划
- 缩写保持一致:LLM 统一使用
llm前缀,不混用model/llm两套命名
2) 表名审计结果
| 当前表名 | 审计结论 | 建议表名 | 说明 |
|---|---|---|---|
profiles |
通过 | - | 符合复数名词规范 |
user_agents |
通过 | - | 语义清晰 |
memories |
通过 | - | 语义清晰 |
friendships |
通过 | - | 关系表命名清晰 |
groups |
通过 | - | 符合规范 |
group_members |
通过 | - | 关联表命名清晰 |
schedule_items |
通过 | - | 语义清晰 |
schedule_subscriptions |
通过 | - | 语义清晰 |
inbox_messages |
通过 | - | 带业务前缀,避免歧义 |
todos |
通过 | - | 简洁且清晰 |
todo_sources |
通过 | - | 关联关系明确 |
automation_jobs |
通过 | - | 语义清晰 |
llms |
通过 | - | 与 LLM 语义一致 |
llm_factory |
建议调整 | llm_factories |
当前为单数,建议改复数以统一规范 |
sessions |
建议调整 | agent_chat_sessions |
过于泛化,建议加业务前缀 |
messages |
建议调整 | agent_chat_messages |
过于泛化,建议加业务前缀 |
3) 落地建议
- 本期命名边界:不重命名
llm_factory/sessions/messages,仅在新表严格执行命名规范 - 本期最小可行:先保持现有表名可运行,新增表全部遵循规范
- 下期统一治理:通过一次性迁移将
llm_factory/sessions/messages重命名到规范名 - 若本期直接重命名,需同步 ORM 模型、外键、索引、RLS policy 名称与运行文档