The re-measure and standing report of the canonical data model's live DB conformance. Use when asked 'where are we at' on DB drift or conformance, to update the drift numbers, when a drift-audit brief is re-issued, or on /drift-audit. NOT the per-table fix recipe (use matrx-frontend's db-canonicalize-table).
Scanned 10/3/2026
npx -y skills add armanisadeghi/ai-matrx --skill drift-audit --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Drift Audit?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/armanisadeghi-drift-audit)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: drift-audit
type: Skill
title: "drift-audit — refresh the canonical-DB conformance numbers, then act"
description: "The re-measure and standing report of the canonical data model's live DB conformance. Use when asked 'where are we at' on DB drift or conformance, to update the drift numbers, when a drift-audit brief is re-issued, or on /drift-audit. NOT the per-table fix recipe (use matrx-frontend's db-canonicalize-table)."
tags: [db, canonical-model, audit, conformance, chips]
timestamp: 2026-08-21T00:00:00Z
---
<!-- SYNCED COPY — do not edit here.
Canonical: common-docs/skills/drift-audit/SKILL.md
This file is distributed to every consuming repo by
common-docs/meta/scripts/sync_skills.py. Edit the canonical, run the
sync, and commit each repo. Edits made here are overwritten and lost. -->
# drift-audit — refresh the numbers, then act
**Invocation: `/drift-audit`.** The deliverable is never just numbers: it is *numbers → diff
→ chips fired → decision list*. Ending at a report with no chips is an incomplete run —
that gap is exactly why this skill exists (Arman, 2026-08-21).
## 0. Ground rules
- **Live project ONLY: `brsgrqvjdzwihsvnfqkf`** (`db.matrxserver.com`). Never access the
retired project `txzxabzwovsujtloxrus`, including for reads or historical comparison;
use archived evidence for historical comparisons instead.
- **Verify against live state, never against a brief.** Audit briefs go stale and get
re-issued: the 8-finding "Canonical Architecture Drift Audit" brief is from 2026-08-15 and
was fully adjudicated the same day.
If a finding doesn't reproduce live, say so — that is a result, not a failure.
- Canon = [db-rules FEATURE.md](/systems/architecture/database/FEATURE.md); operating doctrine =
[database-changeover-doctrine](/policies/database-changeover-doctrine.md) (measurement
traps §4: certified-vs-all universes, `is_component` vs `rls_variant`, cached certify,
counts are not work lists).
- The sentinels below measure the whole database on purpose. When one of them surfaces a specific
table, say which kind of table it is before reporting it —
[canonical-first triage](/policies/canonical-first-triage.md): deprecated is never mentioned, and a
problem on a certified or foundation table outranks the same problem on an uncertified one.
## 1. Measure (read-only, via Supabase MCP)
Run these against live; record each number with its query framing so the next run diffs
apples to apples:
| # | Sentinel | Query sketch |
|---|---|---|
| 1 | Certification | `count(*) filter (where certified)` / total from `audit.summary` (run `select audit.refresh()` first if stale) |
| 2 | Component `created_by` policies | policies on `rls_variant='component'` active tokens whose qual/with_check mention `created_by` — **must be 0** |
| 3 | Nullable org (registered) | active `entity_types` rows whose table's `organization_id` is nullable (~34 known; diff the SET, not the count) |
| 4 | Event triggers | `count(*) from pg_event_trigger` (expect 5 platform + Supabase built-ins; **any restore silently drops them**) |
| 5 | pg_cron | `count(*) from cron.job` (restore also drops these) |
| 6 | ddl_guard_log | total, unacknowledged, and unacknowledged `hand_rolled_entity` rows + new `object_ref`s since last run |
| 7 | Versioned-without-capture | active `is_versioned` + `version_store='history'` tokens with no trigger whose **`tgfoid`** resolves to `platform._version_capture` (never match by trigger name) |
| 8 | Grant holes | tables with `authenticated` policies but no SELECT grant — check `role_table_grants` **∪ `role_column_grants`** (column-grant designs are deliberate: files/secrets/docproc) |
| 9 | RLS-off / zero-policy | `pg_class.relrowsecurity` false, or RLS on with 0 policies but live SIUD grants (the D184 class) |
| 10 | Reachability | `count(distinct refreshed_at)` (1 = recent full rebuild; several = incremental upkeep visible); run `platform.reachability_drift()` if it exists |
## 2. Diff against the last recorded state
Sources, in order: the standing report artifact (update it in place — ask Arman for the link
or use the artifact list; 2026-08-21 baseline:
`https://claude.ai/code/artifact/15a5737b-075a-4307-81a0-2e26c2e3cbc0`), the archived
08-15 adjudication, `matrx-frontend/FOUND_DEFECTS.md` (D146/D182/D184/D232 family), and the
session-memory note `project_drift_audit_adjudication`. For every worsened number, find the
cause (new tables? a lost trigger? a restore?) before reporting it. **Republish the same
artifact** — never a new URL (if it was deleted, publish fresh and repoint this line + the
memory note in the same session).
## 3. Act — this is the point
Split every open item three ways:
1. **Chip it** (default): anything a focused session can finish end-to-end — a guard, a
gate, a bounded sweep, a ≤3-table fix. Fire `spawn_task` chips immediately. Every chip
prompt must be self-contained: live project id + never-touch-retired rule, the canon and
doctrine pointers, the exact end state, the non-breaking constraints, the full-change
contract (doctrine §8a: DB + ORM + types + consumers + commit/push), and the
retreat-cycle rule (§3a: finish forward).
2. **Split it**: too big for one session → chip the first bounded piece with a self-contained brief; never chip "do the whole backlog".
3. **Arman's list**: openness calls, machinery ratifications, schedule approvals, anything
db-rules marks Arman-only. Direct question + your recommendation each
(his standing format — never a doc pointer). Do NOT chip these.
## 4. Report
One message: headline numbers with deltas, what improved, what worsened and why, chips
fired (titles), decisions awaiting Arman. Update the artifact, update the
`project_drift_audit_adjudication` memory, log the run in common-docs if any doc changed.
## Known standing items (groom this list each run — remove what's done)
As of 2026-08-21 evening: the first enforcement wave is DONE and verified live (birth-gate
ERROR + provisioner marker, ddl_guard_log ack contract + readers + full triage → D232,
blocking ratchets + strict org-backstop gate, column-grant guard, component-created_by
blocking check, canon residue trio fixed, 10/11 pg_cron jobs restored,
`reachability_drift()` built, four rules in both CLAUDE.mds). All six Arman rulings are
DECIDED — NO NULL ORG ever (platform-wide, enforced at every layer) · no machinery
exemptions, fix classification instead (per-variant column contract) · batch.* is
user-visible (canonical model) · reachability check daily + self-heal. Second-wave chips in
flight: seo backstop pair + ack, last 9 versioned-without-capture, D232 residue,
component created_by neutralization, NULL-org annihilation + screamers, batch access, drift
schedule. **DONE 2026-08-21: variant-contract reclassification** — `iam.verify_canonical` v4
(db-rules §6d-3) makes the base contract per-variant, so "machinery exemption" is retired as a
concept for base columns; FAILs 799→445, certified 242→281, 42 tables fixed / 0 regressed, and
the `seo`+`runtime` families are FAIL-free. **Read §6d-3 before reading any base-column finding.** Next run: verify those landed, then groom
this list down.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!