feat(app): reconciliatie fase 2 — code leest/schrijft nieuw datamodel #65

Closed
janpeter wants to merge 0 commits from feat/reconcile-fase2 into main
Owner

Wat

Alle applicatiecode schakelt over op het gereconcilieerde datamodel uit fase 1 (PR #64, gemerged):

  • Feiten (media_type/ext/image_hash/filesize) op asset
  • State (favorite/trash/permanent delete) per bestand in asset_state (besluit A)
  • Provenance in asset_source
  • ImmichAsset + ImmichPersonAsset_v2 als leesmodel (vervangt lees-gebruik van ImmichPersonAsset, die als sync-landing blijft tot fase 3a)

Per module

  • library-import runner: één transactie schrijft asset (met feiten), assetState, assetSource, importFile mét asset_id, placement, album-teller, en koppelt zowel ImmichPersonAsset als ImmichAsset op filename.
  • library-import repository: ensureImportAlbum onderhoudt de NOT NULL FK root.album_id; placement-filters lezen via import_file.asset.state.
  • storage: libraryImportFileToMediaFile mapt via importFile.asset.
  • slideshow: select met geneste asset; zichtbaarheids-/favorite-/trash-filters via asset.state; output-interface ongewijzigd.
  • slideshow-actions (kritiek schrijfpad): trash/favorite/permanent-delete upserten assetState; permanent delete ruimt collection-links van alle images van de asset. Collecties blijven bewust image-gebaseerd (lidmaatschap).
  • immich person-browser: leest ImmichAsset × ImmichPersonAsset_v2; src = /api/slideshow-media/<filename> bij koppeling, anders fallback naar oude proxy-URL (die netjes 404't). Vervangt PR #62.
  • duplicates: joins via ImmichAsset (asset_id, geen filename-match); merge zet asset_id op verplaatste import files (NOT NULL FK — échte bug, gevangen door integratietest); favorite-overdracht op asset-niveau.
  • slideshow-media route: zoekt asset op media_filename, source_path via asset.sources[0].
  • src/lib/assets/media-assets.ts verwijderd: collisie-diagnostiek is onmogelijk op het nieuwe model.

Bewust niet aangeraakt

  • scripts/sync-immich*.ts en src/lib/immich/sync.ts — de Immich API is uitgeruimd; deze schrijven alleen naar landing-tabellen. Worden opgeruimd in fase 3a.
  • src/actions/immich-people.ts — raakt alleen ImmichPerson-namen, geen gewijzigde tabellen.

Testen

  • 301/301 tests groen tegen een testdb met het productieschema + beide fase-1 migraties.
  • npm run build groen.

Volgorde (ontwerp §6)

  1. Deze PR eerst deployen (code is voorwaarts-compatibel: leest nieuw model, maar legacy-kolommen op slideshow_image worden nog geschreven tot fase 3a).
  2. Daarna in het onderhoudswindow: expand-migratie → backfill (npm run reconcile:backfill) → constraints-migratie → rooktest.

Stackt op fase 1 (#64, gemerged). Fase 3a pas na ≥1 week stabiel draaien.

## Wat Alle applicatiecode schakelt over op het gereconcilieerde datamodel uit fase 1 (PR #64, gemerged): - **Feiten** (media_type/ext/image_hash/filesize) op `asset` - **State** (favorite/trash/permanent delete) per bestand in `asset_state` (besluit A) - **Provenance** in `asset_source` - **`ImmichAsset` + `ImmichPersonAsset_v2`** als leesmodel (vervangt lees-gebruik van `ImmichPersonAsset`, die als sync-landing blijft tot fase 3a) ## Per module - **library-import runner**: één transactie schrijft asset (met feiten), assetState, assetSource, importFile mét `asset_id`, placement, album-teller, en koppelt zowel `ImmichPersonAsset` als `ImmichAsset` op filename. - **library-import repository**: `ensureImportAlbum` onderhoudt de NOT NULL FK `root.album_id`; placement-filters lezen via `import_file.asset.state`. - **storage**: `libraryImportFileToMediaFile` mapt via `importFile.asset`. - **slideshow**: select met geneste asset; zichtbaarheids-/favorite-/trash-filters via `asset.state`; output-interface ongewijzigd. - **slideshow-actions** (kritiek schrijfpad): trash/favorite/permanent-delete upserten `assetState`; permanent delete ruimt collection-links van alle images van de asset. Collecties blijven bewust image-gebaseerd (lidmaatschap). - **immich person-browser**: leest `ImmichAsset × ImmichPersonAsset_v2`; src = `/api/slideshow-media/<filename>` bij koppeling, anders fallback naar oude proxy-URL (die netjes 404't). **Vervangt PR #62.** - **duplicates**: joins via `ImmichAsset` (asset_id, geen filename-match); merge zet `asset_id` op verplaatste import files (NOT NULL FK — échte bug, gevangen door integratietest); favorite-overdracht op asset-niveau. - **slideshow-media route**: zoekt `asset` op media_filename, source_path via `asset.sources[0]`. - **`src/lib/assets/media-assets.ts` verwijderd**: collisie-diagnostiek is onmogelijk op het nieuwe model. ## Bewust niet aangeraakt - `scripts/sync-immich*.ts` en `src/lib/immich/sync.ts` — de Immich API is uitgeruimd; deze schrijven alleen naar landing-tabellen. Worden opgeruimd in fase 3a. - `src/actions/immich-people.ts` — raakt alleen ImmichPerson-namen, geen gewijzigde tabellen. ## Testen - 301/301 tests groen tegen een testdb met het productieschema + beide fase-1 migraties. - `npm run build` groen. ## Volgorde (ontwerp §6) 1. **Deze PR eerst deployen** (code is voorwaarts-compatibel: leest nieuw model, maar legacy-kolommen op `slideshow_image` worden nog geschreven tot fase 3a). 2. Daarna in het onderhoudswindow: expand-migratie → backfill (`npm run reconcile:backfill`) → constraints-migratie → rooktest. Stackt op fase 1 (#64, gemerged). Fase 3a pas na ≥1 week stabiel draaien.
feat(app): reconciliatie fase 2 — code leest/schrijft nieuw datamodel
All checks were successful
CI / docker-build (pull_request) Successful in 1m16s
5fe08905e7
Alle applicatiecode schakelt over op het gereconcilieerde model uit fase 1:
feiten op asset, state in asset_state (per bestand), provenance in
asset_source, ImmichAsset + ImmichPersonAsset_v2 als leesmodel.

- library-import runner: transactie schrijft asset (met feiten), assetState,
  assetSource, importFile met asset_id, en koppelt zowel ImmichPersonAsset
  als ImmichAsset op filename; album wordt verzekerd via ensureImportAlbum.
- library-import repository: ensureImportAlbum(rootId, name) onderhoudt de
  NOT NULL FK root.album_id; prepareLibraryImportSource maakt album vóór
  root en repareert album_id bij bestaande roots; placement-filters lezen
  via import_file.asset.state.
- storage: libraryImportFileToMediaFile mapt via importFile.asset
  (state/sources/feiten); actionImageId blijft image-gebaseerd.
- slideshow: IMAGE_SELECT met geneste asset (feiten + state + sources);
  zichtbaarheids-, favorite- en trash-filters via asset.state;
  output-interface SlideshowImageRow ongewijzigd.
- slideshow-actions: trash/favorite/permanent-delete upserten assetState
  (state per bestand, besluit A); assertAssetIdForImage vertaalt image-id
  naar asset_id; permanent delete ruimt collection-links van alle images
  van de asset. Collecties blijven bewust image-gebaseerd (lidmaatschap).
- home-tellers via asset/assetState (semantiek per bestand).
- immich person-browser: leest ImmichAsset × ImmichPersonAsset_v2 met
  asset.media_filename; src = /api/slideshow-media/<filename> bij
  koppeling, anders fallback naar oude proxy-URL. Lost PR #62 in.
- immich asset-people: raw SQL over v2-join × ImmichAsset × ImmichPerson.
- duplicates preview/execute/reference-checks: joins via ImmichAsset
  (asset_id, geen filename-match); merge zet asset_id op verplaatste
  import files (NOT NULL FK) en draagt favorite over op asset-niveau;
  delete-guard uitgebreid met immich_assets.
- slideshow-media route: zoekt asset op media_filename, source_path via
  asset.sources[0].
- src/lib/assets/media-assets.ts verwijderd: collisie-diagnostiek is
  onmogelijk op het nieuwe model.

Bewust niet aangeraakt: scripts/sync-immich*.ts en src/lib/immich/sync.ts
(Immich API is uitgeruimd; landing-tabellen blijven tot fase 3a).
src/actions/immich-people.ts raakt alleen ImmichPerson-namen, buiten scope.

Tests: 301/301 groen tegen testdb met productieschema + fase-1 migraties;
npm run build groen.
s4m-codex-reviewer left a comment

Verdict: APPROVED

Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.

Findings

  • Geen blokkerende of error-severity findings gevonden.

De diff volgt de actieve datamodel-reconciliatie richting: asset als canonical record, state op asset_state, provenance via asset_source, LibraryImportRoot.album_id als harde FK, en Immich-normalisatie via ImmichAsset + ImmichPersonAsset_v2. De aangepaste tests dekken de belangrijkste lees- en schrijfpaden die door deze omschakeling geraakt worden.

# Verdict: APPROVED Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden. ## Findings - Geen blokkerende of error-severity findings gevonden. De diff volgt de actieve datamodel-reconciliatie richting: asset als canonical record, state op `asset_state`, provenance via `asset_source`, `LibraryImportRoot.album_id` als harde FK, en Immich-normalisatie via `ImmichAsset` + `ImmichPersonAsset_v2`. De aangepaste tests dekken de belangrijkste lees- en schrijfpaden die door deze omschakeling geraakt worden.
Author
Owner

Gemerged via lokale merge (merge-commit f8dd4f1 op main): de Forgejo-merge-endpoint bleef 405 geven ondanks conflictvrije diff. Conflict met de eerder gemergede #62 in src/lib/immich/person-browser.ts(+test) is opgelost door de fase-2-versie te nemen, die de lokale-src-logica van #62 volledig overneemt op het nieuwe datamodel. Suite 301/301 groen en build groen op de gemergede main. Branch feat/reconcile-fase2 mag weg.

Gemerged via lokale merge (merge-commit `f8dd4f1` op `main`): de Forgejo-merge-endpoint bleef 405 geven ondanks conflictvrije diff. Conflict met de eerder gemergede #62 in `src/lib/immich/person-browser.ts`(+test) is opgelost door de fase-2-versie te nemen, die de lokale-src-logica van #62 volledig overneemt op het nieuwe datamodel. Suite 301/301 groen en build groen op de gemergede main. Branch `feat/reconcile-fase2` mag weg.
janpeter closed this pull request 2026-07-30 11:08:13 +02:00
All checks were successful
CI / docker-build (pull_request) Successful in 1m16s

Pull request closed

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
janpeter/Media-Organizer!65
No description provided.