// SQLite data layer + schema. // Uses Node's built-in node:sqlite (no native compilation needed). const { DatabaseSync } = require('node:sqlite'); const path = require('path'); const db = new DatabaseSync(process.env.DB_PATH || path.join(__dirname, 'data.db')); // WAL is preferred but unsupported on some mounted/network filesystems; fall back quietly. try { db.exec('PRAGMA journal_mode = WAL'); } catch { /* default rollback journal is fine */ } db.exec('PRAGMA foreign_keys = ON'); db.exec(` CREATE TABLE IF NOT EXISTS teams ( id TEXT PRIMARY KEY, name TEXT NOT NULL, created_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, team_id TEXT NOT NULL REFERENCES teams(id), email TEXT NOT NULL UNIQUE, pw_hash TEXT NOT NULL, pw_salt TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'technician', mfa_secret TEXT, mfa_enabled INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS sessions_auth ( token TEXT PRIMARY KEY, user_id TEXT NOT NULL REFERENCES users(id), mfa_passed INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL, expires_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS machines ( id TEXT PRIMARY KEY, team_id TEXT NOT NULL REFERENCES teams(id), name TEXT NOT NULL, enroll_token TEXT NOT NULL UNIQUE, unattended INTEGER NOT NULL DEFAULT 0, last_seen INTEGER, created_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS audit_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, team_id TEXT NOT NULL, user_id TEXT, user_email TEXT, machine_id TEXT, machine_name TEXT, action TEXT NOT NULL, detail TEXT, at INTEGER NOT NULL ); `); // Migration: optional display name for agents (shown to customers on consent) try { db.exec('ALTER TABLE users ADD COLUMN name TEXT'); } catch (e) { /* already exists */ } // Migration: agent active flag (deactivate without deleting) try { db.exec('ALTER TABLE users ADD COLUMN active INTEGER NOT NULL DEFAULT 1'); } catch (e) { /* exists */ } // Session report: one row per support session with duration db.exec(` CREATE TABLE IF NOT EXISTS sessions_log ( id TEXT PRIMARY KEY, team_id TEXT NOT NULL, agent_email TEXT, agent_name TEXT, ticket TEXT, started_at INTEGER NOT NULL, ended_at INTEGER ); `); // Migration: stored recording filename for a session (null if not recorded) try { db.exec('ALTER TABLE sessions_log ADD COLUMN recording TEXT'); } catch (e) { /* exists */ } try { db.exec('ALTER TABLE sessions_log ADD COLUMN transcript TEXT'); } catch (e) { /* exists */ } module.exports = db;