feat(db): roll DEFAULT_TABLE_CONFIG to 2026 — teams_2026_summer_sat + streams_2026_summer_sat #23

Merged
deco merged 1 commit from feat/2026-summer-sat-tables into main 2026-05-20 23:06:01 +03:00
Owner

Summary

Rolls the runtime table year forward for the 2026-06-13 event. Fresh DBs now come up as teams_2026_summer_sat / streams_2026_summer_sat; the home page and all runtime API routes follow.

Per direction in the conversation that asked for this (2026-05-20):

  • Bump the default; 2026 becomes the runtime year.
  • Start 2026 fresh — no row migration from the 2025 tables.
  • Just teams + streams; no additional table types in scope.

Changes

  • lib/constants.ts: DEFAULT_TABLE_CONFIG.year 2025 → 2026. TABLE_NAMES now resolves to the 2026 tables.
  • 5 runtime sites refactored away from inline getTableName(..., { year: 2025, ... }) to TABLE_NAMES.{TEAMS,STREAMS} — these would otherwise silently keep targeting the 2025 tables (split-brain vs. the home page):
    • app/api/createGroup/route.ts (UPDATE teams)
    • app/api/syncGroups/route.ts (SELECT + UPDATE teams)
    • app/api/addStream/route.ts × 3 (fetchTeamInfo, UUID UPDATE, INSERT into streams)
  • app/api/__tests__/yearHardcodeGuard.test.ts: new CI guard that scans app/api/**/*.ts for literal year: NNNN. Fails CI if any future runtime route hand-rolls a year config — so the next year roll is a one-line edit again, not a five-site safari.
  • lib/__tests__/database.test.ts: new DEFAULT_TABLE_CONFIG block pinning year=2026 and TABLE_NAMES.* to the 2026 names — anchors the bump so it can't silently regress.

Non-changes (intentional)

  • scripts/{addGroupNameToTeams,addGroupUuidColumn,createSatSummer2025Tables}.ts keep their hard-coded year: 2025. They are historical migration scripts named for the 2025 season; rewriting them rewrites history nobody asked for.
  • No 2026 migration script needed — initializeDatabase() creates the 2026 teams table with group_name + group_uuid already baked in (per #21), so a fresh-DB cold-start needs no follow-up ALTERs.
  • 2025 row data is untouched in any DB that already holds it. CREATE TABLE IF NOT EXISTS is a no-op for those tables; they sit alongside the new 2026 tables, read-only by definition since no runtime route targets them after this commit.

Test plan

  • Unit: 3 new tests across 2 suites (yearHardcodeGuard + DEFAULT_TABLE_CONFIG pins); full suite 149/22 green.
  • Type-check + lint clean
  • npm run audit:sqlite-opens clean
  • Manual acceptance (fresh DB):
    rm files/sources.db && npm run dev
    curl http://127.0.0.1:3000/api/streams
      → 200 {"success":true,"data":[],"timestamp":"..."}
    sqlite3 files/sources.db ".tables"
      → streams_2026_summer_sat  teams_2026_summer_sat
    sqlite3 files/sources.db "PRAGMA table_info(teams_2026_summer_sat);"
      → team_id, team_name, group_name, group_uuid (all four present)
    

Depends on

  • #21 (Phase 0.8 — schema bootstrap). The 2026 teams CREATE TABLE only includes group_name/group_uuid because of #21; without it, fresh 2026 DBs would still trip /api/streams. Branch is rebased onto #21 — please merge #21 first.
## Summary Rolls the runtime table year forward for the 2026-06-13 event. Fresh DBs now come up as `teams_2026_summer_sat` / `streams_2026_summer_sat`; the home page and all runtime API routes follow. Per direction in the conversation that asked for this (2026-05-20): - Bump the default; 2026 becomes the runtime year. - Start 2026 fresh — no row migration from the 2025 tables. - Just teams + streams; no additional table types in scope. ## Changes - **`lib/constants.ts`**: `DEFAULT_TABLE_CONFIG.year` 2025 → 2026. `TABLE_NAMES` now resolves to the 2026 tables. - **5 runtime sites refactored** away from inline `getTableName(..., { year: 2025, ... })` to `TABLE_NAMES.{TEAMS,STREAMS}` — these would otherwise silently keep targeting the 2025 tables (split-brain vs. the home page): - `app/api/createGroup/route.ts` (UPDATE teams) - `app/api/syncGroups/route.ts` (SELECT + UPDATE teams) - `app/api/addStream/route.ts` × 3 (fetchTeamInfo, UUID UPDATE, INSERT into streams) - **`app/api/__tests__/yearHardcodeGuard.test.ts`**: new CI guard that scans `app/api/**/*.ts` for literal `year: NNNN`. Fails CI if any future runtime route hand-rolls a year config — so the next year roll is a one-line edit again, not a five-site safari. - **`lib/__tests__/database.test.ts`**: new `DEFAULT_TABLE_CONFIG` block pinning `year=2026` and `TABLE_NAMES.*` to the 2026 names — anchors the bump so it can't silently regress. ## Non-changes (intentional) - `scripts/{addGroupNameToTeams,addGroupUuidColumn,createSatSummer2025Tables}.ts` keep their hard-coded `year: 2025`. They are historical migration scripts named for the 2025 season; rewriting them rewrites history nobody asked for. - No 2026 migration script needed — `initializeDatabase()` creates the 2026 teams table with `group_name` + `group_uuid` already baked in (per #21), so a fresh-DB cold-start needs no follow-up `ALTER`s. - 2025 row data is untouched in any DB that already holds it. `CREATE TABLE IF NOT EXISTS` is a no-op for those tables; they sit alongside the new 2026 tables, read-only by definition since no runtime route targets them after this commit. ## Test plan - [x] Unit: 3 new tests across 2 suites (`yearHardcodeGuard` + `DEFAULT_TABLE_CONFIG` pins); full suite 149/22 green. - [x] Type-check + lint clean - [x] `npm run audit:sqlite-opens` clean - [x] **Manual acceptance** (fresh DB): ```sh rm files/sources.db && npm run dev curl http://127.0.0.1:3000/api/streams → 200 {"success":true,"data":[],"timestamp":"..."} sqlite3 files/sources.db ".tables" → streams_2026_summer_sat teams_2026_summer_sat sqlite3 files/sources.db "PRAGMA table_info(teams_2026_summer_sat);" → team_id, team_name, group_name, group_uuid (all four present) ``` ## Depends on - **#21** (Phase 0.8 — schema bootstrap). The 2026 teams `CREATE TABLE` only includes `group_name`/`group_uuid` because of #21; without it, fresh 2026 DBs would still trip `/api/streams`. Branch is rebased onto #21 — please merge #21 first.
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.
feat(db): roll DEFAULT_TABLE_CONFIG to 2026 — teams_2026_summer_sat + streams_2026_summer_sat
All checks were successful
Lint and Build / build (pull_request) Successful in 2m52s
6bc052fa38
The event is 2026-06-13. The app was still defaulting to the 2025 SaT
tables — fresh DBs would come up named teams_2025_summer_sat /
streams_2025_summer_sat and operators would need to manually run the
2025-named CREATE script before the venue went live. This rolls the
default forward.

Per user direction (2026-05-20):
  - Bump the default; 2026 becomes the runtime year.
  - Start 2026 fresh — no row migration from the 2025 tables.
  - Just teams + streams; no additional table types in scope.

Changes
  - lib/constants.ts: DEFAULT_TABLE_CONFIG year 2025 → 2026. TABLE_NAMES
    now resolves to teams_2026_summer_sat / streams_2026_summer_sat.
  - 5 runtime API sites were hand-rolling getTableName(BASE_TABLE_NAMES.X,
    { year: 2025, season: 'summer', suffix: 'sat' }) instead of using
    TABLE_NAMES.X. After a year bump those would silently keep
    targeting 2025 (split-brain against the home page). Refactored to
    TABLE_NAMES.{TEAMS,STREAMS}:
      - app/api/createGroup/route.ts (UPDATE teams)
      - app/api/syncGroups/route.ts (SELECT + UPDATE teams)
      - app/api/addStream/route.ts × 3 (fetchTeamInfo, UUID UPDATE,
        INSERT into streams)
  - app/api/__tests__/yearHardcodeGuard.test.ts: scans app/api/**/*.ts
    for literal `year: NNNN`. Fails CI if any new runtime route hand-
    rolls a year config — the next year roll will be a one-line edit
    again, not a five-site safari.
  - lib/__tests__/database.test.ts: new DEFAULT_TABLE_CONFIG block
    pinning year=2026 and TABLE_NAMES.* to the 2026 names — anchors
    the bump so it can't silently regress.

Non-changes (intentional)
  - scripts/{addGroupNameToTeams,addGroupUuidColumn,createSatSummer2025
    Tables}.ts keep their hard-coded year:2025 — they are historical
    migration scripts named for the 2025 season; touching them rewrites
    history nobody asked for. No 2026 migration script is needed:
    initializeDatabase already creates the 2026 teams table with
    group_name + group_uuid baked in (Phase 0.8.1), so a fresh-DB
    cold-start needs no follow-up ALTERs.
  - 2025 row data is untouched in any DB that already holds it. CREATE
    TABLE IF NOT EXISTS is a no-op for those tables; they sit alongside
    the new 2026 tables, read-only by definition since no runtime route
    targets them after this commit.

Acceptance (manual)
  rm files/sources.db && npm run dev
  curl http://127.0.0.1:3000/api/streams
    → 200 {"success":true,"data":[],"timestamp":"..."}
  sqlite3 files/sources.db ".tables"
    → streams_2026_summer_sat  teams_2026_summer_sat
  PRAGMA table_info(teams_2026_summer_sat)
    → team_id, team_name, group_name, group_uuid (all four present)

Suite: 149/22 passing (was 146/21 on phase-0.8; +3 in
yearHardcodeGuard + DEFAULT_TABLE_CONFIG pins). Type-check + lint
clean; sqlite-opens audit unchanged.

Depends on #21 (Phase 0.8 — schema bootstrap). The 2026 teams CREATE
TABLE only includes group_name/group_uuid because of #21; without it,
fresh 2026 DBs would still trip /api/streams.
deco merged commit 117ad6c8e6 into main 2026-05-20 23:06:01 +03:00
deco deleted branch feat/2026-summer-sat-tables 2026-05-20 23:06:01 +03:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
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!23
No description provided.