-- Phase 2 — council portal revisions -- Adds pull_quote/member_number/focus_tags to users (title already exists -- from 0003), rebuilds events to widen the kind CHECK + add four columns, -- creates dispatches, backfills member_numbers for existing cab users. -- ── users: new columns ───────────────────────────────────────────── ALTER TABLE users ADD COLUMN pull_quote TEXT; ALTER TABLE users ADD COLUMN member_number INTEGER; ALTER TABLE users ADD COLUMN focus_tags TEXT; -- JSON array, capped 3 × 24 chars at app layer CREATE UNIQUE INDEX idx_users_member_number ON users(member_number) WHERE member_number IS NOT NULL; -- Backfill member_numbers for existing CAB users in member-since order, -- tiebreaking on user.id ascending. Deterministic across machines. WITH ranked AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY COALESCE(cab_joined_date, created_at) ASC, id ASC) AS rn FROM users WHERE role = 'cab' ) UPDATE users SET member_number = (SELECT rn FROM ranked WHERE ranked.id = users.id) WHERE role = 'cab' AND member_number IS NULL; -- ── events: rebuild for widened kind enum + 4 new columns ───────── -- SQLite can't ALTER a CHECK constraint; full rebuild required. CREATE TABLE events_new ( id INTEGER PRIMARY KEY AUTOINCREMENT, slug TEXT UNIQUE NOT NULL, title TEXT NOT NULL, kind TEXT NOT NULL DEFAULT 'dinner' CHECK(kind IN ('dinner','office_hours','summit','virtual','working_session')), description TEXT NOT NULL DEFAULT '', location TEXT NOT NULL DEFAULT '', starts_at TEXT NOT NULL, ends_at TEXT, capacity INTEGER, photo_url TEXT, audience TEXT, duration_label TEXT, action_label TEXT, notes_url TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), created_by INTEGER REFERENCES users(id) ); INSERT INTO events_new (id, slug, title, kind, description, location, starts_at, ends_at, capacity, photo_url, created_at, created_by) SELECT id, slug, title, kind, description, location, starts_at, ends_at, capacity, photo_url, created_at, created_by FROM events; DROP TABLE events; ALTER TABLE events_new RENAME TO events; CREATE INDEX idx_events_starts_at ON events(starts_at); -- ── dispatches ──────────────────────────────────────────────────── CREATE TABLE dispatches ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, body TEXT NOT NULL, excerpt TEXT, kind TEXT NOT NULL DEFAULT 'note' CHECK (kind IN ('decision','update','behind_the_scenes','note')), author_id INTEGER NOT NULL REFERENCES users(id), status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','published','archived')), published_at TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX idx_dispatches_published ON dispatches(status, published_at); CREATE INDEX idx_dispatches_author ON dispatches(author_id);