CREATE TABLE IF NOT EXISTS devices ( id TEXT PRIMARY KEY, device_code TEXT NOT NULL UNIQUE, name TEXT NOT NULL, type TEXT NOT NULL, user_agent TEXT, network_group_key TEXT, public_ip_hash TEXT, is_online INTEGER NOT NULL DEFAULT 0, last_seen_at TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS rooms ( code TEXT PRIMARY KEY, creator_device_id TEXT NOT NULL REFERENCES devices(id), joiner_device_id TEXT REFERENCES devices(id), status TEXT NOT NULL, created_at TEXT NOT NULL, expires_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS sessions ( id TEXT PRIMARY KEY, initiator_device_id TEXT NOT NULL REFERENCES devices(id), target_device_id TEXT NOT NULL REFERENCES devices(id), room_code TEXT REFERENCES rooms(code), connect_mode TEXT NOT NULL DEFAULT 'p2p', status TEXT NOT NULL DEFAULT 'connecting', fail_reason TEXT, connected_at TEXT, closed_at TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS transfers ( id TEXT PRIMARY KEY, session_id TEXT REFERENCES sessions(id), kind TEXT NOT NULL, name TEXT NOT NULL, content TEXT, size_bytes INTEGER NOT NULL DEFAULT 0, sender_device_id TEXT NOT NULL REFERENCES devices(id), receiver_device_id TEXT NOT NULL REFERENCES devices(id), transfer_strategy TEXT NOT NULL, current_channel TEXT NOT NULL DEFAULT 'p2p', fallback_allowed INTEGER NOT NULL DEFAULT 0, final_status TEXT NOT NULL DEFAULT 'pending', fallback_reason TEXT, object_key TEXT, expires_at TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS fallback_objects ( transfer_id TEXT PRIMARY KEY REFERENCES transfers(id) ON DELETE CASCADE, bucket TEXT NOT NULL, object_key TEXT NOT NULL UNIQUE, size_bytes INTEGER NOT NULL DEFAULT 0, cleanup_state TEXT NOT NULL DEFAULT 'pending', created_at TEXT NOT NULL, expires_at TEXT NOT NULL, cleaned_at TEXT ); CREATE TABLE IF NOT EXISTS admin_users ( username TEXT PRIMARY KEY, password_hash TEXT NOT NULL, is_active INTEGER NOT NULL DEFAULT 1, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS system_configs ( config_key TEXT PRIMARY KEY, config_value TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS audit_logs ( id TEXT PRIMARY KEY, operator_type TEXT NOT NULL, operator_id TEXT, action TEXT NOT NULL, payload TEXT, created_at TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_devices_online ON devices (is_online, last_seen_at DESC); CREATE INDEX IF NOT EXISTS idx_devices_network_group ON devices (network_group_key); CREATE INDEX IF NOT EXISTS idx_rooms_status_expires ON rooms (status, expires_at DESC); CREATE INDEX IF NOT EXISTS idx_sessions_status_created ON sessions (status, created_at DESC); CREATE INDEX IF NOT EXISTS idx_transfers_status_created ON transfers (final_status, created_at DESC); CREATE INDEX IF NOT EXISTS idx_transfers_sender_receiver ON transfers (sender_device_id, receiver_device_id); CREATE INDEX IF NOT EXISTS idx_fallback_objects_expires ON fallback_objects (cleanup_state, expires_at ASC); CREATE INDEX IF NOT EXISTS idx_audit_logs_created ON audit_logs (created_at DESC); INSERT INTO system_configs (config_key, config_value, updated_at) VALUES ( 'transfer_policy', '{"max_minio_fallback_size_bytes":10737418240,"minio_capacity_bytes":128849018880,"minio_retention_hours":2,"p2p_connect_timeout_sec":15,"turn_connect_timeout_sec":20,"minio_usage_alert_percent":85,"minio_fallback_enabled":true,"turn_urls":[],"turn_username":"","turn_password":""}', STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'now') ) ON CONFLICT(config_key) DO NOTHING;