关于 db-enforcer
面向使用 PostgreSQL 和 Prisma 的 TypeScript 应用,帮助保持应用类型与数据库结构一致。该技能涵盖迁移安全、约束和 Row-Level Security,并将其纳入架构修改流程。
主要功能
- 01对齐 TypeScript 类型与数据库约束
- 02优先生成 SQL 迁移
- 03Prisma 命名与模型映射
- 04Row-Level Security 检查
- 05考虑锁影响的迁移模式
适用场景
- 01规划 PostgreSQL 架构变更
- 02审计 Prisma 映射和约束
- 03准备更安全的生产迁移
- 04为新表添加 RLS 策略
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oakoss/ agent-skills --skill db-enforcer安装后在 Claude Code 中输入/db-enforcer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/migration-safety.mdpostgres-integrity.mdprisma-architecture.mdrls-security.md详细介绍
DB Enforcer
概述
在 TypeScript 应用层与 PostgreSQL 持久化层之间强制执行数据完整性和架构一致性。通过确保 CHECK 约束与 TypeScript 类型一致、在应用变更前生成迁移,以及使用行级安全保护每张表,防止类型漂移。
适用场景: 架构设计、迁移规划、编写 RLS 策略、Prisma 模型映射、约束审计、零停机部署。
不适用场景: 应用层业务逻辑、前端状态管理、非 PostgreSQL 数据库。如需全面审计 RLS、进行性能调优和合规性验证,请改用 database-security 技能。
快速参考
| 模式 | API/工具 | 要点 |
|---|---|---|
| 类型与数据库同步 | prisma migrate dev --create-only | 应用变更前先生成 SQL |
| 命名对齐 | @map / @@map | SQL 中使用 snake_case,TS 中使用 camelCase |
| 主键 | DEFAULT uuidv7() | 按顺序生成、全局唯一、索引速度快(PG 18+) |
| 虚拟列 | GENERATED ALWAYS AS (...) VIRTUAL | 不占用磁盘空间,读取时计算(PG 18+) |
| 时间范围唯一性 | EXCLUDE USING gist | 原生防止范围重叠 |
| NOT VALID 约束 | ADD CONSTRAINT ... NOT VALID | 添加约束时不锁定表 |
| TypedSQL | prisma.$queryRawTyped() | 通过 .sql 文件执行类型安全的原始 SQL |
| 关系模拟 | relationMode = "prisma" | 在没有外键的环境中保证完整性(自 4.8.0 起正式可用) |
| 软删除 | Prisma $extends | 通过客户端扩展处理横切关注点 |
| RLS 标准 | (select auth.uid()) = user_id | 默认的自有数据访问策略,支持 initPlan 缓存 |
| 团队 RLS | EXISTS 子查询 | 通过连接表进行权限检查 |
| 列级安全 | PostgreSQL 视图 | 对公共 API 隐藏敏感列 |
同步协议
每次修改架构都必须遵循以下步骤:
- 类型与数据库验证:在 TS 中添加枚举或联合类型时,验证 SQL 中是否存在对应的 CHECK 约束
- 迁移优先生成:在应用迁移前,使用
prisma migrate dev --create-only生成 SQL 迁移 - 命名对齐:通过显式的
@map/@@map指令,确保 SQL 使用 snake_case,TS 使用 camelCase - 完整性审计:运行
prisma validate,并检查关系标量是否缺少索引 - RLS 验证:确认每张新表都已启用 RLS,并配置了适当的策略
- 锁评估:评估迁移是否需要使用
CREATE INDEX CONCURRENTLY或NOT VALID模式
PostgreSQL 版本要求
此技能中的若干模式需要特定版本的 PostgreSQL:
| 功能 | 最低版本 | 后备方案 |
|---|---|---|
uuidv7() | PostgreSQL 18 | 通过 pgcrypto 使用 gen_random_uuid()(UUIDv4) |
| 虚拟列 | PostgreSQL 18 | STORED 生成列(PG 12+) |
EXCLUDE USING | PostgreSQL 9.0 | 在应用层检查范围是否重叠 |
NOT VALID | PostgreSQL 9.1 | 安排在停机期间添加约束 |
security_invoker | PostgreSQL 15 | 使用权限受限的 security_definer |
常见错误
| 错误 | 正确做法 |
|---|---|
| 不通过迁移,手动运行 SQL 变更 | 应用前,使用 prisma migrate dev --create-only 生成带编号的迁移 |
| 在 URL 中公开自增 ID 或原始 ID | 使用 UUIDv7 作为全局唯一且不可枚举的标识符 |
| 未对枚举或联合类型添加 CHECK 约束 | 添加与 TypeScript 类型对应的数据库级 CHECK 约束 |
| 混用 snake_case 和 camelCase,却未显式映射 | 使用 @map 和 @@map,确保 SQL 中使用 snake_case,TypeScript 中使用 camelCase |
| 表未配置行级安全策略 | 为每张表应用 RLS 策略,默认使用 (select auth.uid()) = user_id |
| 在单次部署中 DROP 或 RENAME 列 | 使用扩展与收缩模式:添加新列、双写、回填、切换读取、删除旧列 |
| 对大型表添加 NOT NULL,导致整表锁定 | 先将列添加为 NULL,完成回填后,再使用 NOT VALID 添加 NOT NULL |
| 创建索引时未使用 CONCURRENTLY | 在原始 SQL 迁移中使用 CREATE INDEX CONCURRENTLY,避免锁表 |
在 RLS 中直接使用 auth.uid(),未使用子查询 | 将其包装为 (select auth.uid()),以触发 initPlan 缓存 |
假定所有 PG 版本都支持 uuidv7() | 确认使用 PostgreSQL 18+;较旧版本使用 gen_random_uuid() 作为回退 |
命名约定
Prisma 模型在 TypeScript 中使用 camelCase,并且必须映射到 PostgreSQL 中的 snake_case:
| 层 | 约定 | 强制方式 |
|---|---|---|
| TypeScript | camelCase | Prisma 模型字段名 |
| PostgreSQL | snake_case | @map / @@map |
| 枚举 | UPPER_SNAKE | CHECK 约束 |
| 索引 | snake_case | idx_table_column |
部署流程
迁移必须严格遵循以下流程顺序:
prisma migrate dev --create-only-- 在本地生成并审查 SQLprisma validate-- 验证架构一致性- 应用到 staging/preview 数据库并运行集成测试
prisma migrate deploy-- 在 CI/CD 流程中应用到生产环境- 监控锁竞争和查询计划回归
与其他技能的关系
database-security:涵盖完整的 RLS 审计、PGAudit 配置、Supabase 专属模式、Convex 身份验证防护和合规性验证。深入审查策略和模拟访问时使用database-security。对于将 RLS 纳入完整性工作流的架构设计和迁移模式,使用db-enforcer。
委派
- 审计现有架构中缺失的约束或索引:使用
ExploreAgent - 规划生产数据库的零停机迁移策略:使用
PlanAgent - 执行包含类型对齐和 RLS 配置的完整架构重构:使用
TaskAgent - 审查 RLS 策略中的绕过风险和性能问题:使用
database-security技能
参考资料
评论
支持 Markdown