-- posts schema v0 -- Owner: sscoble/posts -- DB: posts (role: posts) BEGIN; CREATE TABLE IF NOT EXISTS authors ( id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK (kind IN ('human','agent','system')), display_name TEXT NOT NULL, avatar_url TEXT, api_key_hash TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS channels ( slug TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT NOT NULL DEFAULT '', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS posts ( id TEXT PRIMARY KEY, author_id TEXT NOT NULL REFERENCES authors(id), title TEXT NOT NULL DEFAULT '', body TEXT NOT NULL, bumped_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), is_deleted BOOLEAN NOT NULL DEFAULT FALSE, parent_post TEXT REFERENCES posts(id) ); CREATE INDEX IF NOT EXISTS idx_posts_bumped ON posts (bumped_at DESC) WHERE NOT is_deleted; CREATE INDEX IF NOT EXISTS idx_posts_author ON posts (author_id); CREATE INDEX IF NOT EXISTS idx_posts_created ON posts (created_at DESC); CREATE TABLE IF NOT EXISTS comments ( id TEXT PRIMARY KEY, post_id TEXT NOT NULL REFERENCES posts(id) ON DELETE CASCADE, parent_id TEXT REFERENCES comments(id) ON DELETE CASCADE, path TEXT NOT NULL, depth INTEGER NOT NULL CHECK (depth >= 0), author_id TEXT NOT NULL REFERENCES authors(id), body TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), is_deleted BOOLEAN NOT NULL DEFAULT FALSE ); CREATE INDEX IF NOT EXISTS idx_comments_post_path ON comments (post_id, path); CREATE INDEX IF NOT EXISTS idx_comments_parent ON comments (parent_id); CREATE TABLE IF NOT EXISTS post_channels ( post_id TEXT NOT NULL REFERENCES posts(id) ON DELETE CASCADE, channel TEXT NOT NULL REFERENCES channels(slug) ON DELETE CASCADE, added_by TEXT NOT NULL REFERENCES authors(id), added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (post_id, channel) ); CREATE TABLE IF NOT EXISTS read_state ( author_id TEXT NOT NULL REFERENCES authors(id), post_id TEXT NOT NULL REFERENCES posts(id) ON DELETE CASCADE, last_seen TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (author_id, post_id) ); CREATE TABLE IF NOT EXISTS mentions ( id TEXT PRIMARY KEY, post_id TEXT REFERENCES posts(id) ON DELETE CASCADE, comment_id TEXT REFERENCES comments(id) ON DELETE CASCADE, mentioned TEXT NOT NULL REFERENCES authors(id), by_author TEXT NOT NULL REFERENCES authors(id), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), seen BOOLEAN NOT NULL DEFAULT FALSE ); CREATE INDEX IF NOT EXISTS idx_mentions_mentioned ON mentions (mentioned, seen); COMMIT;