···11+CREATE TABLE IF NOT EXISTS repos (
22+ id TEXT PRIMARY KEY,
33+ name TEXT NOT NULL,
44+ org TEXT NOT NULL,
55+ created_at TEXT DEFAULT (datetime('now')),
66+ UNIQUE(org, name)
77+);
88+99+CREATE TABLE IF NOT EXISTS users (
1010+ id TEXT PRIMARY KEY,
1111+ email TEXT UNIQUE NOT NULL,
1212+ name TEXT,
1313+ password_hash TEXT NOT NULL,
1414+ created_at TEXT DEFAULT (datetime('now'))
1515+);
1616+1717+CREATE TABLE IF NOT EXISTS repo_access (
1818+ repo_id TEXT REFERENCES repos(id) ON DELETE CASCADE,
1919+ user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
2020+ role TEXT CHECK(role IN ('read', 'write', 'admin')) NOT NULL,
2121+ PRIMARY KEY (repo_id, user_id)
2222+);
2323+2424+CREATE TABLE IF NOT EXISTS auth_tokens (
2525+ token TEXT PRIMARY KEY,
2626+ user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
2727+ expires_at TEXT NOT NULL
2828+);
2929+3030+CREATE INDEX IF NOT EXISTS idx_repo_access_user ON repo_access(user_id);
3131+CREATE INDEX IF NOT EXISTS idx_auth_tokens_user ON auth_tokens(user_id);