# Migration note — `epc_property.source` (predicted-EPC slot) **For the team to action before merging the EPC Prediction production-wiring branch.** The model-side code is done and tested against the SQLModel-built test DB; the **production Drizzle schema needs a matching column** that this repo does not own. ## What changed in code (this branch) Per **ADR-0031**, a Property can now hold a **lodged** EPC and a **predicted** EPC (EPC Prediction gap-fill) at the same time. The two are distinguished by a new `source` discriminator on the `epc_property` row: - `infrastructure/postgres/epc_property_table.py` — `EpcPropertyModel` gains `source: str = Field(default="lodged")`. - `repositories/epc/epc_postgres_repository.py` — `save(..., source="lodged")` writes it; `_delete_for_property` is now per-source (idempotency no longer wipes the other slot); `get_for_property` / `get_for_properties` filter `source = 'lodged'`; new `get_predicted_for_property` / `get_predicted_for_properties` read `source = 'predicted'`. The test database is built from the SQLModel mirrors via `create_all`, so tests already exercise the column. **Production is not** — hence this note. ## Required Drizzle migration On the `epc_property` table: 1. **Add column** `source` — `text` (or your enum), **NOT NULL**, **default `'lodged'`**. The default backfills every existing row as a real EPC, which is correct (all current rows are lodged). 2. **Relax any single-row-per-property uniqueness.** If a unique constraint / index exists on `epc_property(property_id)`, it must become **`(property_id, source)`** — a property may now have one `lodged` row and one `predicted` row. (Verify whether such a constraint exists; the SQLModel mirror has none, but the production schema may.) 3. **Recommended index** `(property_id, source)` — every predicted/lodged read filters on both columns. ## Allowed values `source ∈ {'lodged', 'predicted'}` (see `EpcSource` in `repositories/epc/epc_repository.py`). No other values are written. ## Why ADR-0031: predicted EPCs are stored in their own slot rather than overwriting the lodged `epc`, so (a) provenance is structural — the Validation Cohort excludes predicted-sourced Properties and the UI flags them — and (b) lodged + predicted coexist, which the planned **EPC Anomaly Flags** feature needs (compare a Property's lodged EPC against its predicted one).