-- Post engagement surface: unique views, 1-5 ratings, and post messages. -- Applied by rustelo_server::migrations::MigrationRunner on PostgreSQL connect. -- Identity is an opaque visitor_id (first-party `vid` cookie); no raw IP/UA is stored. CREATE TABLE IF NOT EXISTS post_view ( post_id TEXT NOT NULL, lang TEXT NOT NULL, visitor_id TEXT NOT NULL, first_seen TIMESTAMPTZ NOT NULL, PRIMARY KEY (post_id, lang, visitor_id) ); CREATE TABLE IF NOT EXISTS post_rating ( post_id TEXT NOT NULL, visitor_id TEXT NOT NULL, value INTEGER NOT NULL CHECK (value BETWEEN 1 AND 5), updated_at TIMESTAMPTZ NOT NULL, PRIMARY KEY (post_id, visitor_id) ); CREATE TABLE IF NOT EXISTS post_message ( id TEXT PRIMARY KEY, post_id TEXT NOT NULL, post_title TEXT NOT NULL, lang TEXT NOT NULL, name TEXT NOT NULL, email TEXT, body TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'new', -- new | approved | spam (approved => public later) visitor_id TEXT, created_at TIMESTAMPTZ NOT NULL ); CREATE INDEX IF NOT EXISTS idx_post_view_post ON post_view(post_id, lang); CREATE INDEX IF NOT EXISTS idx_post_message_post ON post_message(post_id, status);