-- Router-lists local storage (SQLite). EvoBGP holds reference lists; this DB holds config + caches. CREATE TABLE IF NOT EXISTS app_meta ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS schema_migrations ( id INTEGER PRIMARY KEY AUTOINCREMENT, version INTEGER NOT NULL UNIQUE, applied_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS blobs ( object_key TEXT PRIMARY KEY, namespace TEXT NOT NULL CHECK (namespace IN ( 'config', 'derived', 'per_server', 'cache' )), content_type TEXT NOT NULL DEFAULT 'application/octet-stream', body BLOB NOT NULL, byte_size INTEGER NOT NULL, etag TEXT NOT NULL, updated_at INTEGER NOT NULL, created_at INTEGER NOT NULL ); CREATE INDEX IF NOT EXISTS idx_blobs_namespace_updated ON blobs (namespace, updated_at DESC); CREATE INDEX IF NOT EXISTS idx_blobs_prefix ON blobs (object_key); CREATE TABLE IF NOT EXISTS blob_versions ( id INTEGER PRIMARY KEY AUTOINCREMENT, object_key TEXT NOT NULL, body BLOB NOT NULL, byte_size INTEGER NOT NULL, etag TEXT, created_at INTEGER NOT NULL, FOREIGN KEY (object_key) REFERENCES blobs(object_key) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_blob_versions_key_time ON blob_versions (object_key, created_at DESC); CREATE TABLE IF NOT EXISTS versioned_keys ( object_key TEXT PRIMARY KEY ); INSERT OR IGNORE INTO versioned_keys (object_key) VALUES ('filters.json'), ('servers.json'); CREATE TABLE IF NOT EXISTS cache_entries ( cache_key TEXT PRIMARY KEY, namespace TEXT NOT NULL DEFAULT 'cache', body BLOB NOT NULL, byte_size INTEGER NOT NULL, etag TEXT, updated_at INTEGER NOT NULL, expires_at INTEGER ); CREATE INDEX IF NOT EXISTS idx_cache_expires ON cache_entries (expires_at);