-- ActivePush schema v1 CREATE TABLE IF NOT EXISTS settings ( id INTEGER PRIMARY KEY CHECK (id = 1), json TEXT NOT NULL, revision INTEGER NOT NULL DEFAULT 1, updated_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS admins ( id INTEGER PRIMARY KEY, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, created_at INTEGER NOT NULL, last_login INTEGER, password_changed_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS admin_sessions ( token_hash TEXT PRIMARY KEY, admin_id INTEGER NOT NULL REFERENCES admins(id) ON DELETE CASCADE, csrf TEXT NOT NULL, created_at INTEGER NOT NULL, expires_at INTEGER NOT NULL, last_seen INTEGER NOT NULL, ip TEXT, user_agent TEXT ); CREATE TABLE IF NOT EXISTS setup_token ( id INTEGER PRIMARY KEY CHECK (id = 1), token_hash TEXT NOT NULL, expires_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS devices ( id INTEGER PRIMARY KEY, device_id TEXT NOT NULL, username TEXT NOT NULL, device_type TEXT NOT NULL DEFAULT '', user_agent TEXT NOT NULL DEFAULT '', model TEXT NOT NULL DEFAULT '', imei TEXT NOT NULL DEFAULT '', friendly_name TEXT NOT NULL DEFAULT '', os TEXT NOT NULL DEFAULT '', os_language TEXT NOT NULL DEFAULT '', phone_number TEXT NOT NULL DEFAULT '', mobile_operator TEXT NOT NULL DEFAULT '', as_version TEXT NOT NULL DEFAULT '', policy_key INTEGER NOT NULL DEFAULT 0, policy_temp_key INTEGER NOT NULL DEFAULT 0, policy_name TEXT NOT NULL DEFAULT '', policy_hash TEXT NOT NULL DEFAULT '', wipe_status INTEGER NOT NULL DEFAULT 0, wipe_requested_at INTEGER, wipe_requested_by TEXT, wipe_completed_at INTEGER, blocked INTEGER NOT NULL DEFAULT 0, approved INTEGER NOT NULL DEFAULT 1, first_seen INTEGER NOT NULL, last_seen INTEGER NOT NULL, last_ip TEXT NOT NULL DEFAULT '', last_command TEXT NOT NULL DEFAULT '', requests INTEGER NOT NULL DEFAULT 0, recovery_password TEXT NOT NULL DEFAULT '', ping_folders TEXT NOT NULL DEFAULT '', ping_lifetime INTEGER NOT NULL DEFAULT 0, last_sync_request TEXT NOT NULL DEFAULT '', notes TEXT NOT NULL DEFAULT '', UNIQUE (device_id, username) ); CREATE INDEX IF NOT EXISTS devices_user ON devices(username); CREATE INDEX IF NOT EXISTS devices_seen ON devices(last_seen); CREATE TABLE IF NOT EXISTS sync_states ( device_rowid INTEGER NOT NULL REFERENCES devices(id) ON DELETE CASCADE, collection TEXT NOT NULL, uuid TEXT NOT NULL, counter INTEGER NOT NULL, data BLOB NOT NULL, created_at INTEGER NOT NULL, PRIMARY KEY (device_rowid, collection, uuid, counter) ); CREATE TABLE IF NOT EXISTS folder_map ( username TEXT NOT NULL, backend_id TEXT NOT NULL, short_id INTEGER NOT NULL, PRIMARY KEY (username, backend_id), UNIQUE (username, short_id) ); CREATE TABLE IF NOT EXISTS item_map ( username TEXT NOT NULL, folder TEXT NOT NULL, long_id TEXT NOT NULL, short_id INTEGER NOT NULL, PRIMARY KEY (username, folder, long_id), UNIQUE (username, folder, short_id) ); CREATE TABLE IF NOT EXISTS folder_stats ( device_rowid INTEGER NOT NULL REFERENCES devices(id) ON DELETE CASCADE, collection TEXT NOT NULL, folder_name TEXT NOT NULL DEFAULT '', folder_class TEXT NOT NULL DEFAULT '', last_sync INTEGER NOT NULL DEFAULT 0, items_out INTEGER NOT NULL DEFAULT 0, items_in INTEGER NOT NULL DEFAULT 0, item_count INTEGER NOT NULL DEFAULT 0, last_status INTEGER NOT NULL DEFAULT 0, window_size INTEGER NOT NULL DEFAULT 0, loop_hits INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (device_rowid, collection) ); CREATE TABLE IF NOT EXISTS stats_hourly ( hour INTEGER PRIMARY KEY, requests INTEGER NOT NULL DEFAULT 0, errors INTEGER NOT NULL DEFAULT 0, auth_failures INTEGER NOT NULL DEFAULT 0, bytes_in INTEGER NOT NULL DEFAULT 0, bytes_out INTEGER NOT NULL DEFAULT 0, items_out INTEGER NOT NULL DEFAULT 0, items_in INTEGER NOT NULL DEFAULT 0, mails_sent INTEGER NOT NULL DEFAULT 0, total_ms INTEGER NOT NULL DEFAULT 0, commands TEXT NOT NULL DEFAULT '{}' ); CREATE TABLE IF NOT EXISTS audit_log ( id INTEGER PRIMARY KEY, ts INTEGER NOT NULL, actor TEXT NOT NULL, action TEXT NOT NULL, target TEXT NOT NULL DEFAULT '', ip TEXT NOT NULL DEFAULT '', details TEXT NOT NULL DEFAULT '' ); CREATE INDEX IF NOT EXISTS audit_ts ON audit_log(ts);