fix(phase 0.8): schema bootstrap — group_name + group_uuid in CREATE TABLE #21

Merged
deco merged 2 commits from fix/phase-0.8-schema-bootstrap into main 2026-05-20 22:53:30 +03:00
Owner

Summary

Closes Phase 0.8 from .omc/plans/stream-a-thon-2026-06-13.md.

A fresh checkout (no sources.db inherited from a prior run — e.g. a hot-spare laptop provisioned at the venue) tripped /api/streams with SQLITE_ERROR: no such column: t.group_name. The columns were added late in the project via standalone migration scripts (addGroupNameToTeams.ts, addGroupUuidColumn.ts) that aren't auto-run on cold start, so a freshly initialized DB had only (team_id, team_name).

Changes

  • 0.8.1 lib/database.ts: fold group_name TEXT + group_uuid TEXT into the teams CREATE TABLE IF NOT EXISTS. Migration scripts stay in place — they remain idempotent via PRAGMA table_info checks, so existing DBs are unaffected. initializeDatabase() is now exported so the test can target it.
  • 0.8.2 app/page.tsx unwrap path: Array.isArray guard around the streams payload + typeof-object guard around activeSources, so a future schema-drift bug (or any /api/streams 500) degrades to "empty list" rather than crashing streams.forEach / streams.find during render.
  • 0.8.3 lib/__tests__/database.test.ts: in-memory SQLite test asserting (a) the streams + teams tables hold every column referenced by runtime route SELECTs, and (b) the actual SELECT statements from /api/streams, /api/setActive, /api/syncGroups, and /api/addStream resolve without "no such column" errors. CI now catches CREATE-TABLE / runtime-SELECT drift.

Test plan

  • Unit: lib/__tests__/database.test.ts (9 new tests; full suite 146/21 green)
  • Type-check + lint clean
  • Manual acceptance: rm files/sources.db && npm run dev && curl http://127.0.0.1:3000/api/streams200 {"success":true,"data":[],"timestamp":"..."} (was 500 before fix)
  • PRAGMA table_info(teams_2025_summer_sat) on a fresh DB yields team_id, team_name, group_name, group_uuid
## Summary Closes Phase 0.8 from `.omc/plans/stream-a-thon-2026-06-13.md`. A fresh checkout (no `sources.db` inherited from a prior run — e.g. a hot-spare laptop provisioned at the venue) tripped `/api/streams` with `SQLITE_ERROR: no such column: t.group_name`. The columns were added late in the project via standalone migration scripts (`addGroupNameToTeams.ts`, `addGroupUuidColumn.ts`) that aren't auto-run on cold start, so a freshly initialized DB had only `(team_id, team_name)`. ### Changes - **0.8.1** `lib/database.ts`: fold `group_name TEXT` + `group_uuid TEXT` into the teams `CREATE TABLE IF NOT EXISTS`. Migration scripts stay in place — they remain idempotent via `PRAGMA table_info` checks, so existing DBs are unaffected. `initializeDatabase()` is now exported so the test can target it. - **0.8.2** `app/page.tsx` unwrap path: `Array.isArray` guard around the streams payload + typeof-object guard around `activeSources`, so a future schema-drift bug (or any `/api/streams` 500) degrades to "empty list" rather than crashing `streams.forEach` / `streams.find` during render. - **0.8.3** `lib/__tests__/database.test.ts`: in-memory SQLite test asserting (a) the streams + teams tables hold every column referenced by runtime route SELECTs, and (b) the actual SELECT statements from `/api/streams`, `/api/setActive`, `/api/syncGroups`, and `/api/addStream` resolve without "no such column" errors. CI now catches CREATE-TABLE / runtime-SELECT drift. ### Test plan - [x] Unit: `lib/__tests__/database.test.ts` (9 new tests; full suite 146/21 green) - [x] Type-check + lint clean - [x] Manual acceptance: `rm files/sources.db && npm run dev && curl http://127.0.0.1:3000/api/streams` → `200 {"success":true,"data":[],"timestamp":"..."}` (was 500 before fix) - [x] `PRAGMA table_info(teams_2025_summer_sat)` on a fresh DB yields `team_id, team_name, group_name, group_uuid`
fix(phase 0.8): schema bootstrap — group_name + group_uuid in CREATE TABLE
Some checks failed
Lint and Build / build (pull_request) Failing after 2m8s
b57dd8f511
A fresh checkout (no sources.db inherited from a prior run, e.g. a hot-
spare laptop provisioned at the venue) tripped /api/streams with
SQLITE_ERROR: no such column: t.group_name. The columns were added late
in the project via standalone migration scripts
(addGroupNameToTeams.ts, addGroupUuidColumn.ts) that aren't auto-run on
cold start, so a freshly-initialized DB had only (team_id, team_name).

Phase 0.8 closes the foot-gun:

  0.8.1  lib/database.ts: fold group_name TEXT + group_uuid TEXT into
         the teams CREATE TABLE IF NOT EXISTS. Migration scripts stay
         in place — they remain idempotent via PRAGMA table_info
         checks, so existing DBs are unaffected.

  0.8.2  app/page.tsx unwrap path: Array.isArray guard around the
         streams payload and a typeof-object guard around activeSources,
         so a future schema-drift bug (or any /api/streams 500)
         degrades to "empty list" rather than crashing streams.forEach
         / streams.find during render.

  0.8.3  lib/__tests__/database.test.ts: in-memory SQLite test that
         asserts (a) the streams + teams tables hold every column
         referenced by runtime route SELECTs, and (b) the actual
         SELECT statements from /api/streams, /api/setActive,
         /api/syncGroups, and /api/addStream resolve without "no such
         column" errors. initializeDatabase() is now exported for this
         purpose. Future CREATE-TABLE / runtime-SELECT drift is a CI
         failure rather than an event-day surprise.

Acceptance (manual, on a fresh DB):
  rm files/sources.db && npm run dev
  curl -sS http://127.0.0.1:3000/api/streams
  → 200 {"success":true,"data":[],"timestamp":"..."}
  → sqlite3 files/sources.db "PRAGMA table_info(teams_2025_summer_sat);"
    yields team_id, team_name, group_name, group_uuid.

Suite: 146/21 passing (was 137/20; +9 in lib/__tests__/database.test.ts).
Type-check + lint clean.
fix(phase 0.8): allowlist in-memory test DB for sqlite-opens audit
All checks were successful
Lint and Build / build (pull_request) Successful in 2m52s
316d041602
The Phase 0.8.3 drift guard opens an :memory: SQLite via the same
`open({...})` shape that the audit pattern catches. It's a pure test
surface — never touches disk, never runs in production — so allowlist
it like the other test/script sites.

Without this, CI on #21 trips the audit immediately after the test
file lands.
deco merged commit c0e0e0b8c3 into main 2026-05-20 22:53:30 +03:00
deco deleted branch fix/phase-0.8-schema-bootstrap 2026-05-20 22:53:30 +03:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
deco/cuesheet!21
No description provided.