← back to Wallco Ai
audit: umbrella hard-rule gate (mural-kinds + designs.json local_path leak)
d249fc86158f00e9e98755b9ad9f81622f5081a2 · 2026-06-04 09:16:00 -0700 · Steve Abrams
One read-only command (node scripts/audit-hard-rules.js) that verifies the
data-integrity hard rules from CLAUDE.md in one green/red pass: delegates rule 1
to audit-mural-kinds.js, checks rule 2 (no local_path / /Users home-path leak in
the public snapshot) inline. Exit 1 on any violation -> usable as a pre-deploy
gate or cron canary. Current state: ALL CLEAR (26,060 rows).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
A scripts/audit-hard-rules.js
Diff
commit d249fc86158f00e9e98755b9ad9f81622f5081a2
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jun 4 09:16:00 2026 -0700
audit: umbrella hard-rule gate (mural-kinds + designs.json local_path leak)
One read-only command (node scripts/audit-hard-rules.js) that verifies the
data-integrity hard rules from CLAUDE.md in one green/red pass: delegates rule 1
to audit-mural-kinds.js, checks rule 2 (no local_path / /Users home-path leak in
the public snapshot) inline. Exit 1 on any violation -> usable as a pre-deploy
gate or cron canary. Current state: ALL CLEAR (26,060 rows).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
scripts/audit-hard-rules.js | 66 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/scripts/audit-hard-rules.js b/scripts/audit-hard-rules.js
new file mode 100644
index 0000000..e7f1237
--- /dev/null
+++ b/scripts/audit-hard-rules.js
@@ -0,0 +1,66 @@
+#!/usr/bin/env node
+/**
+ * audit-hard-rules.js — one command that verifies the data-integrity hard rules
+ * from CLAUDE.md still hold against the live catalog + shipped snapshot.
+ *
+ * These are the rules where a silent regression is customer-facing or a privacy
+ * leak, and where nothing else catches the drift after the fact:
+ *
+ * 1. Mural categories are NEVER tileable (delegates to audit-mural-kinds.js)
+ * — a tile kind in a mural category renders as a broken tiny repeating tile.
+ * 2. data/designs.json MUST NOT leak local_path (or any /Users/<home> path)
+ * — that column leaks absolute home paths through the PUBLIC /api/designs.
+ *
+ * Read-only. Never writes the DB or any file. Exit 0 = all clear, 1 = a rule is
+ * violated (so it is usable as a pre-deploy gate / cron canary).
+ *
+ * Usage: node scripts/audit-hard-rules.js
+ */
+'use strict';
+const path = require('path');
+const fs = require('fs');
+const { spawnSync } = require('child_process');
+
+let failed = false;
+const section = (n) => console.log(`\n### ${n}`);
+
+// --- Rule 1: mural categories never tileable (reuse the canonical checker) ---
+section('1. mural categories are never tileable');
+{
+ const r = spawnSync('node', [path.join(__dirname, 'audit-mural-kinds.js')], { encoding: 'utf8' });
+ process.stdout.write(r.stdout || '');
+ if (r.stderr) process.stderr.write(r.stderr);
+ if (r.status !== 0) { failed = true; console.log(' -> FAIL'); }
+ else console.log(' -> PASS');
+}
+
+// --- Rule 2: no local_path / home-path leak in the public snapshot ---
+section('2. data/designs.json carries no local_path / home-path leak');
+{
+ const jsonPath = path.join(__dirname, '..', 'data', 'designs.json');
+ if (!fs.existsSync(jsonPath)) {
+ console.log(' data/designs.json absent — skipped (nothing to leak)');
+ } else {
+ const parsed = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ const rows = Array.isArray(parsed) ? parsed : (parsed.designs || parsed.items || []);
+ const withKey = [];
+ const withHome = [];
+ for (const row of rows) {
+ if (!row || typeof row !== 'object') continue;
+ if ('local_path' in row) withKey.push(row.id);
+ for (const [k, v] of Object.entries(row)) {
+ if (typeof v === 'string' && v.includes('/Users/stevestudio2')) { withHome.push([row.id, k]); break; }
+ }
+ }
+ console.log(` rows=${rows.length} local_path-key=${withKey.length} home-path-leak=${withHome.length}`);
+ if (withKey.length || withHome.length) {
+ failed = true;
+ console.log(` -> FAIL local_path ids: ${withKey.slice(0, 10).join(', ')} home-leak: ${JSON.stringify(withHome.slice(0, 10))}`);
+ } else {
+ console.log(' -> PASS');
+ }
+ }
+}
+
+console.log(`\n=== HARD-RULE AUDIT: ${failed ? 'FAIL — a rule is violated (see above)' : 'ALL CLEAR'} ===`);
+process.exit(failed ? 1 : 0);
← 24c17c0 audit: standing read-only check that mural categories never
·
back to Wallco Ai
·
audit: extend hard-rule gate to vendor-names + FLIEPAPER (4 222ab35 →