Skip to content

Add track_position column to flowsheet (E6-4, #835)#932

Merged
jakebromberg merged 1 commit into
mainfrom
e6-4-flowsheet-track-position
May 18, 2026
Merged

Add track_position column to flowsheet (E6-4, #835)#932
jakebromberg merged 1 commit into
mainfrom
e6-4-flowsheet-track-position

Conversation

@jakebromberg
Copy link
Copy Markdown
Member

Summary

Adds flowsheet.track_position (TEXT, nullable) so the dj-site flowsheet picker (E6-6, BS#836's downstream consumer) can persist the Discogs release_track.position of the selected track. NULL is the natural value for legacy rows, tubafrenzy mirror rows, and free-text DJ entries — no constraint, no default, no backfill.

The change rides through every layer that materializes a flowsheet entry: schema, migration 0076, FSEntryFieldsRaw SQL select, FSEntryRaw type, transformToIFSEntry materialization, and transformToV2 projection. V2 reads now carry track_position end-to-end.

Wire-shape decision (TEXT-not-INT) lives in WXYC/wxyc-shared#111 / #134 — Discogs positions are free-form strings ("A1", "B3", "1-12"), not integers.

Why this is safe

  • DDL-only, no backfill. ALTER TABLE ADD COLUMN ... NULL is metadata-only on PostgreSQL 11+ regardless of the 2.6M-row table size — same pattern as 0069's metadata_attempt_at addition (Migration 0053 wedge: split DDL from backfill, harden migration runner #511's lesson).
  • No precondition guard needed. Column is nullable with no default and no constraint, so there is no data invariant for current rows to violate. -- @no-precondition-needed rationale captured in the migration comment block.
  • No producer pressure on this PR. Writers land in E6-6 (dj-site picker) and any V1/V2 controllers that accept the field; this PR just adds the storage slot.

Project #32 compatibility check

Verified non-collision against the two open migrations in Post-launch service hardening:

Project-32 epic Migration Target Collision?
C1 — BS#891 metadata_status enum on flowsheet different column (status enum, not position) no
D1 — BS#897 new album_metadata table different table no

D4's eventual drop of 10 album-level metadata columns is at least a month out and does not include this per-entry column.

Test plan

  • Failing unit test added for transformToV2 projecting track_position (populated + NULL); now green
  • npm run typecheck clean across all workspaces
  • npm run lint 0 errors (393 pre-existing warnings unchanged)
  • npm run format:check clean
  • npm run test:unit — 1919 tests pass
  • node scripts/validate-migrations.mjs — 75 entries, 0 errors, 2 pre-existing warnings
  • npm run drizzle:freeze-hashes — applied-hashes.json updated for 0076

Closes #835.

Adds a nullable TEXT column for the Discogs `release_track.position` value
(vinyl side or multi-disc prefix like "A1", "B3", "1-12") so the dj-site
flowsheet picker can persist the selected track. Free-text DJ entries,
tubafrenzy mirror rows, and every pre-existing row stay NULL — the column
has no constraint, no default, and no backfill.

Schema, migration 0076, FSEntryFieldsRaw select, FSEntryRaw type,
transformToIFSEntry materialization, and transformToV2 projection all move
in lockstep so the V2 read shape carries the value end-to-end.

Project-32 compatibility: BS#891 (C1 metadata_status enum) and BS#897 (D1 album_metadata table) also touch the flowsheet area but target different columns and tables; no schema collision. D4's eventual drop of album-level cols does not include this per-entry column.

Closes #835.
@github-actions
Copy link
Copy Markdown

Schema constraint shape report

no new constraints detected in this diff (uniqueIndex, .unique(), SET NOT NULL, CHECK, FK)

@jakebromberg jakebromberg merged commit 3256093 into main May 18, 2026
6 checks passed
@jakebromberg jakebromberg deleted the e6-4-flowsheet-track-position branch May 18, 2026 00:10
jakebromberg added a commit that referenced this pull request May 18, 2026
BS#835 / PR #932 shipped the schema, the read projection, and the V2 wire shape for `flowsheet.track_position`, but the V1 `POST /flowsheet` and `PATCH /flowsheet/entries/:id` controllers in apps/backend/controllers/flowsheet.controller.ts didn't accept the field on the request body. Without this, the dj-site flowsheet picker (E6-6, dj-site#501) can send `track_position` and BS silently drops it.

Three edits:

- `FSEntryRequestBody.track_position?: string | null` and `UpdateRequestBody.track_position?: string | null` declared.
- `addEntry` album_id branch forwards `body.track_position ?? null` into `NewFSEntry` explicitly (the explicit assembly didn't spread `body`).
- The free-form branch already propagates via the existing `...body` spread, so the type widening alone is the entire wiring there.

The message-only branch (talkset / breakpoint / PSA) deliberately does NOT carry `track_position` — that column is `entry_type='track'`-only by design. A regression test pins this.

`updateEntry` service does a straight `db.update(flowsheet).set(data)`, so widening `UpdateRequestBody` is the only wiring needed.

Tests:

- tests/unit/controllers/flowsheet.controller.test.ts: 3 new addEntry cases + 1 updateEntry case pinning the forwarding contract; the message-branch negative case prevents future drift.
- tests/integration/flowsheet.spec.js: round-trip POST then read for both the album_id branch ("A1") and the free-form branch ("B2"), exercising real PG + transformToV2's projection.

Local CI: typecheck, lint (0 errors), format:check, test:unit (1937 passing).

Closes #943.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E6-4: Migration — flowsheet.track_position TEXT NULL

1 participant