eduard/cobra-boards
Cobra Boards, team task boards you can run from Claude or ChatGPT. FastAPI + DataK3 + appid + Dodil Models + MCP.
A remix template · 1 remixes · Remix eduard/cobra-boards
schema.sql
-- Created once by the remix, in the bucket it makes. Natural keys only: DataK3 has no sequences,
-- and every id here is chosen by the app (a card is "<board_id>-<number>").
CREATE TABLE IF NOT EXISTS boards (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
owner_email TEXT NOT NULL,
created_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS memberships (
id TEXT PRIMARY KEY, -- board_id + ':' + email
board_id TEXT NOT NULL,
email TEXT NOT NULL,
role TEXT NOT NULL -- member | viewer (the owner lives on boards)
);
CREATE TABLE IF NOT EXISTS board_lists (
id TEXT PRIMARY KEY,
board_id TEXT NOT NULL,
name TEXT NOT NULL,
position DOUBLE,
is_done BOOLEAN -- cards here are finished: never overdue, never blocking
);
CREATE TABLE IF NOT EXISTS cards (
id TEXT PRIMARY KEY, -- board_id + '-' + number, claimed by a plain INSERT
board_id TEXT NOT NULL,
number BIGINT NOT NULL,
list_id TEXT NOT NULL,
title TEXT NOT NULL,
description TEXT,
assignee TEXT,
due_date DATE,
labels TEXT, -- JSON array of strings
position DOUBLE,
version BIGINT NOT NULL, -- bumped by every write; a stale write matches no row
created_by TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS card_events (
id TEXT PRIMARY KEY,
board_id TEXT NOT NULL,
card_id TEXT,
actor TEXT NOT NULL,
action TEXT NOT NULL,
summary TEXT,
changes TEXT, -- JSON: field -> [before, after]
event_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS card_dependencies (
id TEXT PRIMARY KEY, -- card_id + '<' + blocker_id
board_id TEXT NOT NULL,
card_id TEXT NOT NULL, -- this card ...
blocker_id TEXT NOT NULL -- ... waits for this one
);
CREATE TABLE IF NOT EXISTS checklist_items (
id TEXT PRIMARY KEY,
card_id TEXT NOT NULL,
text TEXT NOT NULL,
done BOOLEAN,
position DOUBLE
);
CREATE TABLE IF NOT EXISTS card_vectors (
card_id TEXT PRIMARY KEY,
board_id TEXT NOT NULL,
text_hash TEXT NOT NULL, -- the card text it was made from; a changed card is re-embedded
embedding VECTOR(768) -- arctic-embed-m-v2 (Dodil Models), cosine distance
);
CREATE TABLE IF NOT EXISTS card_comments (
id TEXT PRIMARY KEY,
board_id TEXT NOT NULL,
card_id TEXT NOT NULL,
author TEXT NOT NULL,
body TEXT NOT NULL,
mentions TEXT, -- JSON array of the emails it @mentions
created_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS notifications (
id TEXT PRIMARY KEY,
email TEXT NOT NULL, -- who it is for
board_id TEXT NOT NULL,
card_id TEXT,
kind TEXT NOT NULL, -- mention | assigned | comment
actor TEXT NOT NULL,
summary TEXT,
created_at TIMESTAMP,
read_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS card_attachments (
id TEXT PRIMARY KEY,
board_id TEXT NOT NULL,
card_id TEXT NOT NULL,
name TEXT NOT NULL,
content_type TEXT,
size BIGINT,
object_key TEXT NOT NULL, -- where the bytes live in this bucket's object storage
uploaded_by TEXT,
created_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS archived_cards (
card_id TEXT PRIMARY KEY, -- an archived card leaves the board, keeps its number and history
board_id TEXT NOT NULL,
archived_by TEXT,
archived_at TIMESTAMP
);