Database Schema Designer — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Database Schema Designer (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.
A schema is the one part of a system you cannot refactor with a find-and-replace: every shortcut taken at design time becomes a locked-table migration on a hot production database later. This skill produces schemas that stay correct and fast as data grows - invalid states unrepresentable, indexes matched to real queries, and every change shippable without downtime.
Follow the steps in order. Constraints come before indexes because constraints define correctness and indexes only define speed; migrations come last because they depend on both.
Collect these before writing any DDL. If a number is a guess, label it a guess and proceed.
tenant_id on every row?Normalize to third normal form (3NF) by default: every non-key column depends on the key, the whole key, and nothing but the key. Denormalize a specific read path only when ALL of these hold:
For M:N relationships, use a join table with a composite primary key on both foreign keys.
BIGINT GENERATED ALWAYS AS IDENTITY, or UUIDv7 when IDs are generated client-side or must not be guessable. Never UUIDv4 as a clustered/primary key - random inserts fragment the index and wreck insert throughput on large tables.TIMESTAMPTZ, never naive local time.NUMERIC(19,4) or integer minor units (total_cents BIGINT), never float.CHECK (col IN (...)) constraint, a Postgres enum, or a lookup table. Lookup table when values change at runtime; CHECK/enum when they change with a deploy.Add NOT NULL by default, foreign keys with an explicit ON DELETE behavior (RESTRICT unless cascade is a designed feature), and CHECK constraints for domain rules (total_cents >= 0). Every constraint you skip becomes application code that at least one code path forgets.
(user_id, created_at DESC) serves "this user's recent orders"; the reverse order does not.INCLUDE selected columns) when a top query can be served from the index alone.WHERE status = 'pending' when pending is under ~5% of rows but queried constantly.pg_stat_user_indexes for zero-scan indexes.tenant_id leads every index prefix and appears in every unique key.NOT VALID then VALIDATE CONSTRAINT on Postgres to avoid a full-table lock).CREATE INDEX CONCURRENTLY - a plain CREATE INDEX blocks writes for the whole build.deleted_at TIMESTAMPTZ, and every unique constraint becomes a partial unique index WHERE deleted_at IS NULL - otherwise a deleted row blocks re-creation forever.Bad - three common shortcuts:
CREATE TABLE orders (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY, -- UUIDv4: fragments the index
user_email TEXT, -- denormalized copy, no sync owner
status TEXT, -- free text: 'Paid', 'paid', 'PAID '
total FLOAT -- float money: rounding drift
);Migration bill this schema generates within a year: a data-cleaning pass to canonicalize every status typo before a CHECK constraint can be validated; a backfill joining users to repair stale user_email copies; a FLOAT -> NUMERIC type change that rewrites the whole table under lock; and insert throughput decay from UUIDv4 fragmentation that no migration fixes without a new PK.
Good - the same table designed forward:
CREATE TABLE orders (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
status TEXT NOT NULL CHECK (status IN ('pending','paid','shipped')),
total_cents BIGINT NOT NULL CHECK (total_cents >= 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_orders_user_created ON orders (user_id, created_at DESC);Future migrations against this table are additive: new columns arrive nullable-then-backfilled, new statuses extend the CHECK, and nothing requires a cleanup pass first.
Produce a schema design containing: the DDL for every table with constraints inline; the index list annotated with the specific query each index serves; the denormalization decisions (if any) each naming its sync mechanism; and the migration plan for getting from the current state to the target, ordered and reversible.
CREATE INDEX or an immediate SET NOT NULL on a large production table; both take locks that stall writes.deleted_at in unique constraints when soft-deleting - the second "delete and recreate" fails in production.A finished design passes only if:
For query plans that stay slow on a sound schema, hand off to explain-plan-reader or sql-query-optimizer. When a table's growth projection crosses ~100M rows or needs time-based pruning, bring in partition-planner before it gets there. Gate risky production migrations through migration-safety-checker.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.