Database Schema Reviewer — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Database Schema Reviewer (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill directs the agent to review a database schema — provided as SQL DDL, an ORM model file (Drizzle, Prisma, SQLAlchemy, ActiveRecord, etc.), or a plain description — and produce a prioritized list of issues. It checks normalization, indexes, constraints, naming conventions, nullable columns, and overall scalability. Every issue includes a concrete SQL or ORM fix.
Use this before deploying a new schema to production, during code review of a migration file, or when a database is growing and you're starting to feel query pain.
Copy this file to .agents/skills/database-schema-reviewer/SKILL.md in your project root.
Then share your schema and ask:
Provide the full schema file, a SQL DDL dump, or paste the relevant CREATE TABLE statements.
Add the "Prompt / Instructions" section to your .cursorrules file. Open your schema or migration file and ask Cursor to review it.
Paste the schema DDL or ORM model definitions into the chat along with the instructions below. Include any known query patterns if you want index recommendations tailored to your workload.
When asked to review a database schema, follow these steps:
CREATE TABLE statements)model blocks)zip_code and city in the same table as user_id)WHERE, ORDER BY, or JOIN conditions should be indexed — infer from column names (e.g., email, status, created_at, user_id)email in a users table)REFERENCES constraintNOT NULL but are nullable: primary-purpose columns like email, name, created_atDEFAULT value but don't (e.g., created_at, boolean flags)ON DELETE / ON UPDATE behavior on foreign keysid (or table_id) — flag non-standard PK namesreferenced_table_id — flag deviationsis_, has_, or can_ prefix — flag ambiguous names like active or enabledTEXT or VARCHAR(MAX) for columns that are used in WHERE clauses or indexesENUM types in PostgreSQL/MySQL where the values change frequently (painful to alter)SELECT * traps: wide tables with many columns that are rarely all needed together (suggest splitting)role column on users with no roles table, suggesting future extensibility issues).## Schema Review Results
### Summary
[X] High · [Y] Medium · [Z] Low findings across [N] tables
---
### High Priority
#### [Issue title] — [Table.column]
**Problem:** [Plain English explanation]
**Risk:** [What goes wrong if this isn't fixed]
**Fix:**[concrete SQL or ORM fix]
---
[repeat by priority level]
### Passed Checks
- [List areas that look good]Input to Agent:
"Use the Database Schema Reviewer skill on this schema:
>
```sql CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255), email VARCHAR(255), role VARCHAR(50), address TEXT, city VARCHAR(100), zip VARCHAR(20), created TIMESTAMP );
>
CREATE TABLE orders ( order_id SERIAL PRIMARY KEY, userId INTEGER, items TEXT, status VARCHAR(50), total DECIMAL(10,2) ); ```"
Output from Agent:
## Schema Review Results
>
### Summary 4 High · 3 Medium · 2 Low findings across 2 tables
>
---
>
### High Priority
>
#### Missing UNIQUE constraint on users.email Problem: Email is the primary identifier for login but has no unique constraint. Duplicate accounts can be created. Risk: Authentication bugs, data corruption, duplicate account merging nightmare. Fix: ``sql ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email); CREATE INDEX idx_users_email ON users (email); ``>
#### orders.userId has no foreign key constraint Problem:userIdreferences theuserstable logically but has noREFERENCESconstraint. Orphaned orders with deleted users will exist silently. Risk: Referential integrity violations, broken order history views. Fix: ``sql ALTER TABLE orders ADD CONSTRAINT fk_orders_user FOREIGN KEY (userId) REFERENCES users(id) ON DELETE RESTRICT; CREATE INDEX idx_orders_user_id ON orders (userId);``
>
#### orders.items stores multiple values in a TEXT column (1NF violation) Problem: Storing order items as a text blob violates first normal form and makes querying individual items impossible without string parsing. Risk: Impossible to query "which orders contain product X", no referential integrity on items. Fix: Create anorder_itemstable: ``sql CREATE TABLE order_items ( id SERIAL PRIMARY KEY, order_id INTEGER NOT NULL REFERENCES orders(order_id) ON DELETE CASCADE, product_id INTEGER NOT NULL, quantity INTEGER NOT NULL DEFAULT 1, unit_price DECIMAL(10,2) NOT NULL );``
>
---
>
### Medium Priority
>
#### users.city and users.zip are a transitive dependency (3NF violation) Problem: City and zip code describe each other, not the user. Moving address data to an addresses table is cleaner for reuse and consistency.>
#### users.created should be NOT NULL with a DEFAULT Fix: created TIMESTAMP NOT NULL DEFAULT NOW()>
#### Naming inconsistency: orders uses order_id and userId (mixed conventions) Fix: Rename toidanduser_idto match PostgreSQL snake_case convention.
>
---
>
### Passed Checks - Primary keys are present on both tables - DECIMAL used correctly for monetary values (not FLOAT)
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.