// Migration: Add ivanti_finding_archives and ivanti_archive_transitions tables const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const dbPath = path.join(__dirname, '..', 'cve_database.db'); const db = new sqlite3.Database(dbPath); console.log('Starting finding archive tables migration...'); db.serialize(() => { // Archive records — one row per finding that has entered the archive lifecycle db.run(` CREATE TABLE IF NOT EXISTS ivanti_finding_archives ( id INTEGER PRIMARY KEY AUTOINCREMENT, finding_id TEXT NOT NULL UNIQUE, finding_title TEXT NOT NULL DEFAULT '', host_name TEXT NOT NULL DEFAULT '', ip_address TEXT NOT NULL DEFAULT '', current_state TEXT NOT NULL CHECK(current_state IN ('ARCHIVED', 'RETURNED', 'CLOSED')), last_severity REAL NOT NULL DEFAULT 0, first_archived_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, last_transition_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `, (err) => { if (err) console.error('Error creating ivanti_finding_archives table:', err); else console.log('✓ ivanti_finding_archives table created'); }); // Transition history — one row per state change on an archive record db.run(` CREATE TABLE IF NOT EXISTS ivanti_archive_transitions ( id INTEGER PRIMARY KEY AUTOINCREMENT, archive_id INTEGER NOT NULL, from_state TEXT NOT NULL, to_state TEXT NOT NULL, severity_at_transition REAL NOT NULL DEFAULT 0, reason TEXT NOT NULL DEFAULT '', transitioned_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (archive_id) REFERENCES ivanti_finding_archives(id) ) `, (err) => { if (err) console.error('Error creating ivanti_archive_transitions table:', err); else console.log('✓ ivanti_archive_transitions table created'); }); // Indexes for query performance db.run(` CREATE INDEX IF NOT EXISTS idx_archive_finding_id ON ivanti_finding_archives(finding_id) `, (err) => { if (err) console.error('Error creating idx_archive_finding_id:', err); else console.log('✓ idx_archive_finding_id index created'); }); db.run(` CREATE INDEX IF NOT EXISTS idx_archive_current_state ON ivanti_finding_archives(current_state) `, (err) => { if (err) console.error('Error creating idx_archive_current_state:', err); else console.log('✓ idx_archive_current_state index created'); }); db.run(` CREATE INDEX IF NOT EXISTS idx_transition_archive_id ON ivanti_archive_transitions(archive_id) `, (err) => { if (err) console.error('Error creating idx_transition_archive_id:', err); else console.log('✓ idx_transition_archive_id index created'); }); }); db.close(() => { console.log('Migration complete!'); });