CREATE TABLE feed_sources ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, url TEXT NOT NULL UNIQUE, is_enabled INTEGER NOT NULL DEFAULT 1 CHECK (is_enabled IN (0, 1)), refresh_interval_minutes INTEGER NOT NULL DEFAULT 60 CHECK (refresh_interval_minutes BETWEEN 15 AND 10080), default_category_id TEXT REFERENCES section_categories(id) ON DELETE SET NULL, etag TEXT NOT NULL DEFAULT '', last_modified TEXT NOT NULL DEFAULT '', last_fetched_at_utc TEXT, next_fetch_at_utc TEXT, last_error TEXT NOT NULL DEFAULT '', created_at_utc TEXT NOT NULL, updated_at_utc TEXT NOT NULL ); CREATE TABLE feed_entries ( id TEXT PRIMARY KEY, feed_id TEXT NOT NULL REFERENCES feed_sources(id) ON DELETE CASCADE, external_id TEXT NOT NULL, title TEXT NOT NULL, url TEXT NOT NULL, summary TEXT NOT NULL DEFAULT '', published_at_utc TEXT, status TEXT NOT NULL DEFAULT 'new' CHECK (status IN ('new', 'imported', 'discarded')), piece_id TEXT REFERENCES pieces(id) ON DELETE SET NULL, first_seen_at_utc TEXT NOT NULL, updated_at_utc TEXT NOT NULL, UNIQUE (feed_id, external_id) ); CREATE INDEX feed_entries_status_idx ON feed_entries(status, first_seen_at_utc DESC); CREATE INDEX feed_sources_due_idx ON feed_sources(is_enabled, next_fetch_at_utc); CREATE TABLE technical_accesses ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, token_hash TEXT NOT NULL UNIQUE, permissions TEXT NOT NULL CHECK (permissions IN ('read', 'read_write')), created_by_user_id TEXT NOT NULL REFERENCES users(id), created_at_utc TEXT NOT NULL, last_used_at_utc TEXT, revoked_at_utc TEXT ); CREATE TABLE api_idempotency ( access_id TEXT NOT NULL REFERENCES technical_accesses(id) ON DELETE CASCADE, request_key TEXT NOT NULL, request_hash TEXT NOT NULL, status_code INTEGER NOT NULL, response_json TEXT NOT NULL CHECK (json_valid(response_json)), created_at_utc TEXT NOT NULL, PRIMARY KEY (access_id, request_key) ); CREATE TABLE audit_events ( id TEXT PRIMARY KEY, actor_type TEXT NOT NULL CHECK (actor_type IN ('user', 'technical')), actor_id TEXT NOT NULL, action TEXT NOT NULL, target_type TEXT NOT NULL, target_id TEXT NOT NULL, created_at_utc TEXT NOT NULL ); CREATE INDEX audit_events_created_idx ON audit_events(created_at_utc DESC);