fix: all 5 high-severity bugs from codex review
- use sqlx migrate!() instead of broken split(';') — triggers now work
- seq via AUTOINCREMENT — no race conditions, monotonic ordering
- replace ?since= with ?after_seq= — cursor-based, no timestamp format issues
- replace all unwrap() with typed errors (404, 409, 400, 500)
- reply_to same-channel enforced in route handler
- add biome for frontend linting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
crates/colony/migrations/20260329000001_init.sql
Normal file
55
crates/colony/migrations/20260329000001_init.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
display_name TEXT NOT NULL,
|
||||
role TEXT NOT NULL CHECK (role IN ('ape', 'agent')),
|
||||
password_hash TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS api_tokens (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
user_id TEXT NOT NULL REFERENCES users(id),
|
||||
token_hash TEXT UNIQUE NOT NULL,
|
||||
token_prefix TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channels (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
created_by TEXT NOT NULL REFERENCES users(id),
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
|
||||
);
|
||||
|
||||
-- seq is INTEGER PRIMARY KEY AUTOINCREMENT = global monotonic, no race conditions
|
||||
-- id is a separate UUID with a unique index
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
id TEXT UNIQUE NOT NULL,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id),
|
||||
user_id TEXT NOT NULL REFERENCES users(id),
|
||||
type TEXT NOT NULL CHECK (type IN ('text', 'code', 'result', 'error', 'plan')),
|
||||
content TEXT NOT NULL,
|
||||
metadata TEXT,
|
||||
reply_to TEXT REFERENCES messages(id),
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
||||
updated_at TEXT,
|
||||
deleted_at TEXT
|
||||
-- reply_to same-channel constraint enforced in application layer (routes.rs)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_channel_seq ON messages(channel_id, seq);
|
||||
|
||||
-- Seed users
|
||||
INSERT OR IGNORE INTO users (id, username, display_name, role)
|
||||
VALUES ('00000000-0000-0000-0000-000000000001', 'benji', 'Benji', 'ape');
|
||||
|
||||
INSERT OR IGNORE INTO users (id, username, display_name, role)
|
||||
VALUES ('00000000-0000-0000-0000-000000000002', 'neeraj', 'Neeraj', 'ape');
|
||||
|
||||
-- Seed general channel
|
||||
INSERT OR IGNORE INTO channels (id, name, description, created_by)
|
||||
VALUES ('00000000-0000-0000-0000-000000000010', 'general', 'General discussion', '00000000-0000-0000-0000-000000000001');
|
||||
Reference in New Issue
Block a user