diff --git a/db/database.js b/db/database.js index a29416f..cba0200 100755 --- a/db/database.js +++ b/db/database.js @@ -13,12 +13,12 @@ db.pragma('foreign_keys = ON'); const schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf8'); db.exec(schema); -// ── Migrations for existing DBs ───────────────────────────────────────────── +// ── Migrations for existing DBs ────────────────────────────────────────────── const cols = db.prepare('PRAGMA table_info(violations)').all().map(c => c.name); -if (!cols.includes('negated')) db.exec("ALTER TABLE violations ADD COLUMN negated INTEGER NOT NULL DEFAULT 0"); -if (!cols.includes('negated_at')) db.exec("ALTER TABLE violations ADD COLUMN negated_at DATETIME"); -if (!cols.includes('prior_active_points')) db.exec("ALTER TABLE violations ADD COLUMN prior_active_points INTEGER"); -if (!cols.includes('prior_tier_label')) db.exec("ALTER TABLE violations ADD COLUMN prior_tier_label TEXT"); +if (!cols.includes('negated')) db.exec("ALTER TABLE violations ADD COLUMN negated INTEGER NOT NULL DEFAULT 0"); +if (!cols.includes('negated_at')) db.exec("ALTER TABLE violations ADD COLUMN negated_at DATETIME"); +if (!cols.includes('prior_active_points')) db.exec("ALTER TABLE violations ADD COLUMN prior_active_points INTEGER"); +if (!cols.includes('prior_tier_label')) db.exec("ALTER TABLE violations ADD COLUMN prior_tier_label TEXT"); // Ensure resolutions table exists db.exec(`CREATE TABLE IF NOT EXISTS violation_resolutions ( @@ -30,6 +30,30 @@ db.exec(`CREATE TABLE IF NOT EXISTS violation_resolutions ( created_at DATETIME DEFAULT CURRENT_TIMESTAMP )`); +// ── Feature: Violation Amendments ──────────────────────────────────────────── +// Stores a field-level diff every time a violation's editable fields are changed. +db.exec(`CREATE TABLE IF NOT EXISTS violation_amendments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + violation_id INTEGER NOT NULL REFERENCES violations(id) ON DELETE CASCADE, + changed_by TEXT, + field_name TEXT NOT NULL, + old_value TEXT, + new_value TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +)`); + +// ── Feature: Audit Log ─────────────────────────────────────────────────────── +// Append-only record of every write action across the system. +db.exec(`CREATE TABLE IF NOT EXISTS audit_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + action TEXT NOT NULL, + entity_type TEXT NOT NULL, + entity_id INTEGER, + performed_by TEXT, + details TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +)`); + // Recreate view so it always filters negated rows db.exec(`DROP VIEW IF EXISTS active_cpas_scores; CREATE VIEW active_cpas_scores AS