Files
webmanager-mvp/project_docs/LOCAL_UPLOAD_V1_DESIGN.md
T
2026-03-13 13:44:41 +01:00

234 lines
8.0 KiB
Markdown

# Local Upload v1
## 1. Doel
Local upload voegt nu direct waarde toe omdat de app al een bruikbare dual-pane bestandsworkflow heeft, maar nog geen ingang om bestanden vanaf de lokale machine de beheerde storage in te brengen. Dat gat is functioneel groot: browse, rename, move, copy en delete bestaan al, maar import ontbreekt.
Binnen de dual-pane workflow is de meest natuurlijke semantiek:
- bron: lokale machine via de native browser file picker
- doel: `currentPath` van het actieve paneel
Dat houdt het model eenvoudig en voorspelbaar. De gebruiker kiest eerst waar in de storage hij staat, en uploadt daarna naar die locatie.
## 2. Scope
Aanbevolen scope voor v1:
- upload van lokale bestanden via browser naar storage
- target = `currentPath` van het actieve paneel
- native browser file picker gebruiken
- single-file upload
- multi-file upload
- geen folder upload in v1
- geen drag & drop in v1
- geen resumable upload
- geen chunked upload
Motivatie:
- Multi-file upload via de native picker is klein en nuttig.
- Folder upload verhoogt de complexiteit direct sterk: recursie, conflictgedrag, voortgang, directory-creatie, mixed failures.
- Drag & drop is UX-matig aantrekkelijk, maar voegt event-complexiteit en extra foutpaden toe zonder dat het nodig is voor een eerste bruikbare versie.
- Chunking/resume is pas zinvol als gewone multipart upload aantoonbaar onvoldoende is.
## 3. Startgedrag / UI
Voor v1:
- een `Upload` knop links van `F1 Settings` in de onderbalk/topactiezone waar die nu logisch past
- klik op `Upload` opent direct de native browser file picker
- de upload werkt altijd naar het actieve paneel
- de UI toont compact en expliciet:
- `Upload to: <currentPath van actief paneel>`
Aanbevolen flow:
1. gebruiker activeert een paneel
2. gebruiker klikt `Upload`
3. browser opent native file picker
4. gebruiker kiest 1 of meerdere bestanden
5. upload start naar `currentPath` van actief paneel
6. voortgang wordt zichtbaar
7. na afronding wordt het actieve paneel refreshed
Belangrijk:
- de actieve-paneelcontext moet vooraf duidelijk zijn
- de knop hoeft niet disabled te zijn zolang een geldig `currentPath` bestaat
- als een modal open is, moet `Upload` niet tegelijk een nieuwe flow starten
## 4. Voortgang
Aanbevolen v1-model:
- één compacte upload-progress UI per lopende uploadbatch
- globale voortgang over de batch
- daarnaast compacte status per huidig bestand indien nodig
V1 hoeft niet meteen een volledige task-UI te hergebruiken. De eenvoudigste bruikbare richting is:
- één uploadstatusblok of kleine modal
- toont:
- totaal aantal bestanden
- huidig bestand
- globale voortgangsbalk of percentage
Aanbevolen velden in de UI:
- `Uploading 3 files to /Volumes/...`
- `2/3 files`
- huidige bestandsnaam
- percentage of bytes-progress voor de actieve upload
Dit is lichter dan de bestaande task-list volledig integreren in v1.
## 5. Backend-impact
Er is zeer waarschijnlijk een nieuw upload-endpoint nodig, bijvoorbeeld:
- `POST /api/files/upload`
Verwachte vorm:
- multipart/form-data
- target path als apart veld, bijvoorbeeld `target_path`
- één of meerdere file parts
Veiligheidsmodel:
- `target_path` altijd via bestaande `path_guard`
- target moet binnen whitelist/toegestane roots vallen
- target moet bestaan
- target moet een directory zijn
- bestandsnamen niet vertrouwen vanuit clientpad-informatie
- alleen de basename van het gekozen lokale bestand gebruiken
- validatie van naam via bestaande naamregels (`validate_name` of equivalent)
- geen client-side padsegmenten overnemen
Traversalpreventie:
- geen directorystructuur uit de browser aan serverzijde interpreteren in v1
- geen relatieve paden uit multipart metadata vertrouwen
- ieder bestand wordt server-side gemapt naar:
- `target_path / validated_basename`
## 6. Conflictgedrag
Ontwerp voor Engelstalige keuzes:
- `Overwrite`
- `Overwrite all`
- `Skip`
- `Cancel`
Aanbevolen v1-gedrag:
- conflictcontrole gebeurt server-side per bestand
- bij conflict in een batch wordt de batch niet stil doorgezet
- de UI toont een compacte conflictmodal voor het huidige conflicterende bestand
- de gebruiker kiest één actie
Semantiek:
- `Overwrite`: alleen huidig conflicterend bestand overschrijven
- `Overwrite all`: huidig en alle volgende conflicten automatisch overschrijven
- `Skip`: huidig conflicterend bestand overslaan en doorgaan
- `Cancel`: resterende batch stoppen
Aanbevolen v1-realisatie:
- conflict afhandelen per bestand binnen de uploadbatch-flow
- geen complexe vooraf-scan van alle conflicten nodig
- geen rollback
Belangrijk:
- ook directoryconflicten moeten duidelijk zijn
- als target al een directory met dezelfde naam bevat voor een file-upload, moet dat als conflict/typefout behandeld worden
## 7. Grote bestanden / performance
Aanbevolen v1:
- gewone multipart upload
- geen chunking
- geen resumable upload
Motivatie:
- technisch het eenvoudigst
- breed ondersteund door browser en backendstack
- voldoende voor een eerste bruikbare versie
Risico:
- zeer grote bestanden kunnen lang duren of mislukken bij netwerkonderbreking
- dat risico moet in v1 geaccepteerd en netjes gecommuniceerd worden
V1 hoeft daarom niet meer te doen dan:
- voortgang tonen
- foutmelding tonen bij mislukking
- geen herstart of resume bieden
## 8. Relatie met tasks/history
Aanbevolen v1:
- upload opnemen in `history`
- upload niet meteen in het generieke `tasks` model stoppen
Motivatie:
- upload heeft wel auditwaarde, dus history is logisch
- task-integratie maakt de slice groter: background execution, task persistence, progress mapping, polling-UI integratie
- voor een eerste bruikbare upload is een lichtere directe UI-flow met history-opslag pragmatischer
History v1 voor upload zou moeten registreren:
- operation = `upload`
- status = `completed` / `failed`
- destination = doelpad
- path of source-naam waar nuttig
- error_code / error_message bij failure
Als later blijkt dat uploads langlopend worden of meerdere gelijktijdige uploads normaal zijn, kan task-integratie in v2 logisch worden.
## 9. Regressierisico
Belangrijkste risico's:
- security: onbetrouwbare bestandsnamen of target path misbruik
- grote bestanden: timeouts of langlopende requests
- foutafhandeling: deels geslaagde batch zonder duidelijke feedback
- UI-complexiteit: conflictflow kan snel onrustig worden
- actieve-paneelcontext: upload naar verkeerd paneel/pad als context niet duidelijk is
- conflictafhandeling: onduidelijke semantiek rond overwrite/skip
Laag-regressierisico aanpak:
- target altijd expliciet koppelen aan actief paneel
- geen folder upload
- geen drag & drop
- geen chunking/resume
- compacte conflictmodal per bestand
- direct paneelrefresh na succesvolle upload(s)
## 10. Teststrategie
Backend golden tests:
- upload single file success
- upload multi-file success
- target path not found
- target path is file -> type_conflict
- traversal blocked
- invalid root alias
- invalid filename blocked
- conflict -> already_exists of equivalent
- overwrite success
- skip/cancel flow indien servercontract dat nodig maakt
UI smoke/regressietests:
- `Upload` knop aanwezig links van `F1 Settings`
- geen uploadstart als ongeldige UI-context aanwezig is
- targetpaneel-context zichtbaar in uploadflow
- progress UI verschijnt
- conflictkeuze-UI verschijnt met:
- `Overwrite`
- `Overwrite all`
- `Skip`
- `Cancel`
Handmatige validatie:
- upload 1 klein bestand
- upload meerdere bestanden
- conflict op bestaand bestand
- overwrite all werkt over meerdere conflicten
- skip laat batch doorgaan
- cancel stopt batch
- actief paneel bepaalt doelpad correct
- history bevat upload-resultaten
## 11. Aanbeveling
Aanbevolen v1-richting met laag regressierisico:
- native browser file picker
- single + multi-file upload
- target = `currentPath` van actief paneel
- geen folder upload
- geen drag & drop
- gewone multipart upload
- directe voortgangsweergave in lichte upload-UI
- conflictafhandeling per bestand met:
- `Overwrite`
- `Overwrite all`
- `Skip`
- `Cancel`
- wel history-integratie
- nog geen task-integratie
Dit is de kleinste versie die echt bruikbaar is, zonder meteen te ontsporen in mediaserver- of synchronisatiecomplexiteit.