project-bifrost-platform/migrations/0004_phase_two.sql
Jonathan Hvid 865347f682 feat(db): migration 0004 — phase 2 schema + 4 new tokens
users: adds pull_quote, member_number (unique partial index, NULLs allowed),
focus_tags. title already exists from 0003 — not re-added. Backfills
member_number for existing cab users in COALESCE(cab_joined_date,
created_at) asc, tiebreak id asc. Lars gets #1.

events: rebuild required to widen the kind CHECK constraint (SQLite can't
ALTER it in place). Adds working_session as a new kind. Same rebuild adds
four new columns: audience, duration_label, action_label, notes_url. Data
preserved.

dispatches: new entity, status enum draft/published/archived, kind enum
decision/update/behind_the_scenes/note. published_at nullable until
publishPulse-equivalent stamps it. Indexes on (status, published_at) and
author_id.

Tokens (src/styles/tokens.css): adds --surface-card, --surface-card-border,
--ink, --ink-text, --ink-muted. Spec called these out as the only
additions; existing --radius-lg covers the spec's --border-radius-lg
reference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:46:53 +02:00

74 lines
3.3 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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);