[object Object]

← 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

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 →