From 22f4939b242376ea8d613467d03a2ee97f58d40e Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Fri, 12 Jun 2026 21:53:45 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20move=20Phase=209=20=C2=A79.1=20from=20P?= =?UTF-8?q?LAN=20to=20COMPLETED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- COMPLETED.md | 25 +++++++++++++++++++++++++ PLAN.md | 19 ------------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/COMPLETED.md b/COMPLETED.md index 88bdc0c..00e862a 100644 --- a/COMPLETED.md +++ b/COMPLETED.md @@ -6,6 +6,31 @@ Newest entries at the top. Group by phase/wave header (mirroring `PLAN.md` / `CM --- +## Phase 9 — Release Medium Types + +### 9.1 Wave 1 — Data model + migration + +**Landed:** 2026-06-12 on dev. + +- **What:** New `ReleaseMedium` enum (`Cut, Session, Mix`) in `DeepDrftModels/Enums/`. `ReleaseEntity` gains `ReleaseMedium Medium` (default `Cut`) plus 1:1 nav properties to two new metadata entities. New `SessionMetadata` (`HeroImageEntryKey`) and `MixMetadata` (`WaveformEntryKey`) entities, each 1:1 with `ReleaseEntity`. EF configurations + migration. +- **Why:** Every other wave reads this schema. The discriminator-plus-optional-table shape is the load-bearing decision of the phase; it must land first and land right. +- **Shape:** + - `ReleaseMedium` enum with `Cut = 0` (default — existing/migrated releases stay studio cuts with no discriminator data migration). + - `Medium` column on `releases`; `ReleaseConfiguration` documents the `ReleaseType`-only-for-`Cut` invariant *and* the named `CutMetadata`-rejected exception (see the phase intro above). + - `session_metadata` and `mix_metadata` tables, each with a unique FK to `releases` (1:1). `MixMetadata.WaveformEntryKey` is a vault entry key (resolved — see open question), not an inline blob. + - Migration is **additive only** — no data migration of existing rows beyond defaulting `Medium = Cut`. Lower risk than the Phase 8 normalization. +- **Prerequisite:** Phase 8 §8.0 normalization (`ReleaseEntity` exists) — already landed. +- **Acceptance criteria:** + - `ReleaseMedium` enum exists; `ReleaseEntity.Medium` defaults to `Cut`. + - `SessionMetadata` / `MixMetadata` entities + EF configs + migration applied; solution compiles and existing releases read back as `Cut`. + - The invariant is documented in `ReleaseConfiguration` (no DB constraint — a deliberate choice; EF supports check constraints, see the phase intro). +- **Open questions:** + - **Resolved — waveform storage:** vault blob + `WaveformEntryKey`. Settled by the server-side trigger design (9.2.B): the API computes and stores the datum vault-side; SQL holds only the entry key, so a JSON column never enters the flow. This wave adds only the SQL column — the vault write rides the existing vault abstraction server-side. + +**Completion note:** `ReleaseMedium` enum with `Cut`, `Session`, `Mix` values implemented in `DeepDrftModels/Enums/`. `ReleaseEntity` extended with `Medium` column (default `Cut`) and 1:1 nav properties to `SessionMetadata` and `MixMetadata`. New entities added with their EF configurations. Additive migration `AddReleaseMedium` authored and applied. `ReleaseDto` updated with `Medium` field and nested metadata DTOs. `TrackConverter` updated. Solution builds; existing releases read back as `Cut`; acceptance criteria met. + +--- + ## Phase 8 — CMS Track Browser ### 8.6 "Music through Every Medium" home page section diff --git a/PLAN.md b/PLAN.md index f68f8e6..a182c5b 100644 --- a/PLAN.md +++ b/PLAN.md @@ -165,25 +165,6 @@ Sequenced as four waves. Wave 1 is a prerequisite for everything; within Waves 2 --- -### 9.1 Wave 1 — Data model + migration `[prerequisite gate]` - -- **What:** New `ReleaseMedium` enum (`Cut, Session, Mix`) in `DeepDrftModels/Enums/`. `ReleaseEntity` gains `ReleaseMedium Medium` (default `Cut`) plus 1:1 nav properties to two new metadata entities. New `SessionMetadata` (`HeroImageEntryKey`) and `MixMetadata` (`WaveformEntryKey`) entities, each 1:1 with `ReleaseEntity`. EF configurations + migration. -- **Why:** Every other wave reads this schema. The discriminator-plus-optional-table shape is the load-bearing decision of the phase; it must land first and land right. -- **Shape:** - - `ReleaseMedium` enum with `Cut = 0` (default — existing/migrated releases stay studio cuts with no discriminator data migration). - - `Medium` column on `releases`; `ReleaseConfiguration` documents the `ReleaseType`-only-for-`Cut` invariant *and* the named `CutMetadata`-rejected exception (see the phase intro above). - - `session_metadata` and `mix_metadata` tables, each with a unique FK to `releases` (1:1). `MixMetadata.WaveformEntryKey` is a vault entry key (resolved — see open question), not an inline blob. - - Migration is **additive only** — no data migration of existing rows beyond defaulting `Medium = Cut`. Lower risk than the Phase 8 normalization. -- **Prerequisite:** Phase 8 §8.0 normalization (`ReleaseEntity` exists) — already landed. -- **Acceptance criteria:** - - `ReleaseMedium` enum exists; `ReleaseEntity.Medium` defaults to `Cut`. - - `SessionMetadata` / `MixMetadata` entities + EF configs + migration applied; solution compiles and existing releases read back as `Cut`. - - The invariant is documented in `ReleaseConfiguration` (no DB constraint — a deliberate choice; EF supports check constraints, see the phase intro). -- **Open questions:** - - **Resolved — waveform storage:** vault blob + `WaveformEntryKey`. Settled by the server-side trigger design (9.2.B): the API computes and stores the datum vault-side; SQL holds only the entry key, so a JSON column never enters the flow. This wave adds only the SQL column — the vault write rides the existing vault abstraction server-side. - ---- - ### 9.2 Wave 2 — API: medium reads + metadata uploads A new `api/release` controller — the medium unit is the *release*, not the track, so medium browse and metadata uploads are release-cardinal rather than bolted onto `api/track/page`.