feat(db): posts schema v0

This commit is contained in:
Hermes 2026-06-22 22:34:39 -07:00
parent 2cfdd05d5d
commit 46b52e7304

83
docs/schema.sql Normal file
View file

@ -0,0 +1,83 @@
-- 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;