Files
webmanager-mvp/project_docs/DIRECTORY_MOVE_V1_DESIGN.md
T
2026-03-11 16:21:00 +01:00

8.4 KiB

DIRECTORY_MOVE_V1_DESIGN.md

1. Scope

Doel van Directory Move v1 is om directory-verplaatsing toe te voegen binnen het bestaande move/task/securitymodel, zonder het huidige veiligheidsniveau of de voorspelbaarheid van de backend te verzwakken.

In scope voor v1:

  • directory move als expliciete uitbreiding van de bestaande move-operatie
  • task-based uitvoering
  • conflictcontrole op destination
  • beveiligde padvalidatie via bestaand path_guard
  • duidelijke foutstatussen bij ongeldige of gevaarlijke moves

Out of scope voor v1:

  • geen rollbackmechanisme
  • geen cancel/retry
  • geen gedeeltelijke recovery van half-voltooide cross-root moves
  • geen symlink-following buiten whitelist
  • geen speciale merge- of overwrite-semantiek
  • geen multi-select directory move als aparte batch-semantiek buiten bestaande sequentiële task-aanmaak

2. Same-root versus cross-root

Directory move binnen dezelfde root

Dit is de veiligste en simpelste stap.

Kenmerken:

  • kan meestal native via rename()/move op directoryniveau
  • snel en atomair binnen hetzelfde filesystem/root
  • geen inhoudelijke recursieve file copy nodig
  • veel minder kans op partial failure

Directory move tussen verschillende roots

Dit is aanzienlijk complexer.

Kenmerken:

  • vereist recursieve copy van directory tree
  • daarna delete van source tree
  • progressmeting en foutafhandeling worden lastiger
  • partial failure is realistischer
  • rollback is ingewikkeld en in v1 ongewenst

Aanbevolen scopekeuze

Aanbevolen v1:

  • alleen same-root directory move ondersteunen
  • cross-root directory move nog niet ondersteunen

Reden:

  • sluit goed aan op bestaand taskmodel zonder grote complexiteitsexplosie
  • beperkt regressierisico
  • voorkomt een half-robuste recursieve copy+delete-implementatie zonder rollback

3. Semantiek

Wanneer is het een echte move

Directory move is van toepassing als:

  • source een directory is
  • destination een volledig doelpad is
  • destination nog niet bestaat

Binnen same-root:

  • de operatie gebruikt native rename/move op directoryniveau
  • dit geldt zowel voor verplaatsen naar andere parent als voor directory move binnen dezelfde root met andere naam

Destination bestaat al

Gedrag v1:

  • destination mag niet bestaan
  • response: already_exists

Geen merge in v1.

Nested destinations

Verboden gevallen:

  • source naar een child van zichzelf
  • source naar een pad in eigen subtree

Voorbeeld:

  • source: /Volumes/8TB/Shows
  • destination: /Volumes/8TB/Shows/Archive/Shows

Dit moet direct geblokkeerd worden.

Aanbevolen fout:

  • invalid_request met duidelijke boodschap zoals Destination cannot be inside source

Verplaatsen van map in zichzelf

Ook verboden:

  • destination exact gelijk aan source
  • destination onder source subtree

Dit moet vóór task-creatie worden afgewezen.


4. Taskmodel

Directory move blijft task-based, ook voor same-root moves.

Progressmeting

Voor same-root native directory move is echte byte-progress meestal niet beschikbaar.

Aanbevolen v1:

  • gebruik vooral done_items / total_items
  • voor same-root kan dat minimaal zijn:
    • total_items = 1
    • done_items = 0 -> 1
  • done_bytes / total_bytes mogen null blijven in v1 voor same-root directory move

Fail-fast gedrag

Aanbevolen v1:

  • fail-fast
  • zodra de move-operatie faalt, task -> failed

Partial failure

Voor same-root native directory move is partial failure veel minder waarschijnlijk.

  • of de rename slaagt
  • of de rename faalt

Dus v1-model:

  • geen expliciete partial-successstatus
  • eindstatus blijft:
    • completed
    • failed

Rollback

Geen rollback in v1.

Voor same-root native rename is dat meestal niet nodig. Voor cross-root zou rollback wel relevant worden, maar die scope wordt niet aanbevolen voor v1.


5. Security

Symlinkgedrag in directory trees

Aanbevolen v1-beleid:

  • source directory zelf mag geen symlink zijn
  • bij same-root native rename wordt de tree niet recursief gevolgd of gekopieerd, dus child-symlinks hoeven niet actief gevolgd te worden voor uitvoering
  • toch blijft containmentcontrole op source en destination verplicht

Traversal en containment

  • bron- en destination-pad blijven via bestaand path_guard
  • destination binnen whitelist verplicht
  • destination mag niet buiten root escapen
  • nested destination-in-source moet expliciet extra gevalideerd worden

PathGuard-impact

Bestaand path_guard blijft basis voor:

  • whitelistvalidatie
  • traversalblokkade
  • symlink containment check op bron/destination-resolutie

Aanvullend nodig voor directory move:

  • helper of servicecheck om te bepalen of destination in subtree van source ligt

Escapes buiten whitelist voorkomen

Bij same-root-only v1:

  • containment blijft relatief eenvoudig
  • geen recursieve copy over child nodes nodig
  • dus ook minder attack surface dan cross-root recursieve tree copy

6. Backend-impact

Waarschijnlijk te wijzigen delen:

  • webui/backend/app/services/move_task_service.py
  • webui/backend/app/tasks_runner.py
  • webui/backend/app/fs/filesystem_adapter.py
  • mogelijk webui/backend/app/api/schemas.py alleen als taskdetail-documentatie wordt aangescherpt
  • mogelijk kleine aanvulling in path_guard.py of move-service validatiehelpers

Bestaande move-logica die hergebruikt kan worden

Herbruikbaar:

  • task-creatie
  • repository-persistency
  • statusflow queued -> running -> completed/failed
  • destination-exists checks
  • parent directory validation
  • algemene error mapping

Nieuw voor directory move:

  • source typecheck moet directory toestaan in same-root-case
  • same-root task runner moet directory rename kunnen uitvoeren
  • nested-destination-validatie

Rename binnen zelfde parent blijft apart

Ja.

Aanbevolen scheiding:

  • rename endpoint blijft aparte, directe single-path operatie
  • move blijft task-based voor echte moves
  • ook als een same-root directory move technisch op rename lijkt, blijft het semantisch onderdeel van move

Dat houdt UI- en API-rollen duidelijk.


7. UI-impact

Move-knop en F6 bij exact 1 directory

Aanbevolen gedrag:

  • F6 / Move-knop blijven dezelfde popupflow gebruiken
  • exact 1 directory geselecteerd:
    • zelfde parent + andere naam -> huidige rename route blijft toegestaan
    • andere parent binnen dezelfde root -> task-based directory move toegestaan in v1
    • cross-root destination -> blokkeren met duidelijke melding, bijvoorbeeld:
      • Cross-root directory move is not supported in v1

Multi-select met directories

Aanbevolen v1:

  • geen gemengde halfslimme batchflow
  • als multi-select directories bevat:
    • alleen toestaan als alle geselecteerde directories voldoen aan same-root move-semantiek, of
    • eenvoudiger en veiliger voor v1: nog blokkeren met duidelijke melding

Aanbevolen eerste stap:

  • multi-select met directories nog blokkeren
  • melding:
    • Batch directory move is not supported in v1

Reden:

  • beperkt scope en regressierisico
  • houdt UI-flow voorspelbaar

8. Teststrategie

Golden tests

Toe te voegen voor move-API:

  • same-root directory move success
  • directory destination exists -> already_exists
  • directory source not found
  • directory source is symlink -> blokkade
  • nested destination blocked
  • exact same source/destination blocked
  • cross-root directory move blocked

Regressietests

  • file move success same-root blijft werken
  • file move success cross-root blijft werken als huidige scope dat al ondersteunt
  • rename endpoint blijft ongewijzigd
  • browse en delete blijven ongewijzigd

Securitytests

  • traversal source
  • traversal destination
  • symlink source rejection
  • destination inside source rejection
  • destination outside whitelist rejection

Runtime edge cases

  • rename/move van lege directory
  • rename/move van directory met inhoud binnen same-root
  • permission failure -> io_error
  • destination parent ontbreekt -> bestaande foutmapping

9. Aanbeveling

Aanbevolen v1-richting:

  • alleen same-root directory move ondersteunen
  • cross-root directory move nog niet ondersteunen

Korte motivatie:

  • laagste complexiteit
  • beste aansluiting op bestaand taskmodel
  • minimale partial-failure kans
  • veel kleiner regressie- en securityrisico dan recursieve cross-root tree copy+delete

Praktische v1-scope:

  • exact 1 directory
  • same-root move task-based
  • nested destination geblokkeerd
  • destination exists geblokkeerd
  • cross-root directory move expliciet geweigerd
  • batch directory move nog niet

Dat is de veiligste eerste stap met duidelijke semantiek en goede testbaarheid.