# Research: Remote Single-File Copy To Host ## Relevante file analysis ### Backend - [routes_files.py](/workspace/webmanager-mvp/webui/backend/app/api/routes_files.py) Bevat de bestaande lokale upload-route (`POST /api/files/upload`) en de remote read-only Phase 3 routes (`view`, `info`, `download`, `image`) via `RemoteFileService`. - [routes_copy.py](/workspace/webmanager-mvp/webui/backend/app/api/routes_copy.py) Bevat de bestaande copy-route (`POST /api/files/copy`) die volledig uitgaat van host-side source en host-side destination. - [file_ops_service.py](/workspace/webmanager-mvp/webui/backend/app/services/file_ops_service.py) Bevat lokale file-acties. Relevant is vooral `upload()`, omdat die host-write doet na `PathGuard`-validatie van een doeldirectory. - [copy_task_service.py](/workspace/webmanager-mvp/webui/backend/app/services/copy_task_service.py) Bevat task-opbouw, destination-validatie en taakcreatie voor copy, maar gaat uit van een lokale bron die via `PathGuard` naar een host-pad resolveert. - [remote_file_service.py](/workspace/webmanager-mvp/webui/backend/app/services/remote_file_service.py) Bevat al de benodigde remote read-path parsing, share-validatie via registry, agent-auth, error mapping en een gestreamde `prepare_download()` naar de agent. - [filesystem_adapter.py](/workspace/webmanager-mvp/webui/backend/app/fs/filesystem_adapter.py) Bevat de feitelijke host-write helpers: - `write_uploaded_file(path, file_stream, overwrite=False)` - `copy_file(source, destination, on_progress=None)` `copy_file` vereist een lokale bron op de host en is dus niet bruikbaar voor remote input. `write_uploaded_file` schrijft een inkomende stream naar een hostpad en is conceptueel het dichtstbij. - [path_guard.py](/workspace/webmanager-mvp/webui/backend/app/security/path_guard.py) Houdt host-write validatie strikt lokaal. Dat moet zo blijven; remote paden mogen hier niet als bronsemantiek in terechtkomen. - [tasks_runner.py](/workspace/webmanager-mvp/webui/backend/app/tasks_runner.py) Bevat task-based copy/move uitvoering, maar alleen voor host-side bronpaden. Wel relevant als patroon voor een aparte remote-to-host worker. - [schemas.py](/workspace/webmanager-mvp/webui/backend/app/api/schemas.py) Bevat bestaande `CopyRequest` en upload/copy response-modellen. Voor een aparte feature is waarschijnlijk een nieuw requestmodel nodig. ### Frontend - [app.js](/workspace/webmanager-mvp/webui/html/app.js) Relevante bestaande flows: - `uploadFileRequest()` gebruikt uitsluitend `/api/files/upload` - `startCopySelected()` gebruikt uitsluitend `/api/files/copy` - remote browse/view/download is al source-aware - remote copy is nu bewust geblokkeerd Dit bevestigt dat upload-flow en copy-flow momenteel twee losse UI-contracten zijn. ### Agent - [finder_commander/app/main.py](/workspace/webmanager-mvp/finder_commander/app/main.py) Agent heeft al wat voor deze feature nodig is: - strikte `share + relative path` validatie - `GET /api/info` - `GET /api/download` Voor remote single-file copy naar host is geen nieuwe remote write-API nodig. ## Oordeel over hergebruik van upload-internals ### Bestaande upload-functionaliteit aanpassen? Nee. Reden: - de bestaande upload-route, upload-requestvorm en upload-UI werken al goed - upload is browser -> host via multipart/form-data - de gewenste feature is agent/remote -> host via backend-proxy/stream - dat is een ander contract, andere foutbron en andere bronsemantiek ### Interne host-write logica hergebruiken? Ja, maar alleen op intern helper/service-niveau. Concreet oordeel: - `FilesystemAdapter.copy_file()` is niet geschikt voor hergebruik Reden: vereist een lokale host-bronpad als source. - `FilesystemAdapter.write_uploaded_file()` is deels relevant Reden: dit doet precies de host-write van een inkomende stream naar een doelbestand. - Direct hergebruik van `FileOpsService.upload()` is niet verstandig Reden: die methode is semantisch en contractueel gekoppeld aan multipart upload en `UploadFile`. Best passende richting: - niet hergebruiken via bestaande upload-endpoints of upload-flow - wel overwegen om de onderliggende stream-naar-bestand write logica te hergebruiken of te veralgemeniseren in `FilesystemAdapter` - voorkeur: een nieuwe sibling-helper zoals `write_stream_file(...)` of een kleine interne extractie, zodat upload ongewijzigd blijft en remote copy dezelfde veilige host-write primitief kan gebruiken ## Ontwerpvoorstel ### Feature `Copy remote file to host` ### Scope - alleen single file - alleen source onder `/Clients/...` - alleen destination op host-side lokale map - geen mappen - geen overwrite in eerste change request tenzij expliciet gewenst - geen upload-route hergebruik - geen brede refactor ### Backendontwerp Voeg een aparte backend feature toe, niet via `POST /api/files/upload` en niet via bestaande `POST /api/files/copy`. Voorkeursvorm: - nieuwe route, bijvoorbeeld `POST /api/files/remote-copy` - request bevat: - `source`: remote bestandspad onder `/Clients/...` - `destination_dir`: host-directory pad Nieuwe service, bijvoorbeeld: - `RemoteCopyToHostService` Verantwoordelijkheden: 1. valideer dat `source` een remote `/Clients/...` file is 2. valideer dat `destination_dir` een host-directory is via bestaande lokale `PathGuard` 3. haal remote metadata op of resolve remote naam via bestaande `RemoteFileService` 4. bouw destination pad als `destination_dir/` 5. faal op bestaand doelbestand in eerste versie 6. open remote download-stream via aparte interne helper op `RemoteFileService` 7. schrijf gestreamd naar host met een aparte interne host-write helper 8. map fouten strikt: - remote unavailable blijft lokale actie-fout - host permission/path-conflict blijft gewone host-fout ### Aanbevolen interne hergebruikslijn - laat `RemoteFileService` een interne streaming primitive aanbieden, bijvoorbeeld een variant op de huidige remote download-open logica zonder HTTP-response voor browser-download - laat `FilesystemAdapter` een aparte stream-write helper aanbieden voor generieke inkomende streams - laat upload zijn bestaande publieke route en flow behouden ### Frontendontwerp Geen wijziging aan upload-UI. Kleine aparte UI-feature: - toon een aparte actie alleen als: - bronpane een remote file-selectie heeft van exact 1 bestand - doelpane op een host/local directory staat - de actie roept de nieuwe backend-route aan - na succes: - refresh beide panes - toon lokale foutmelding bij falen Voorkeur: - aparte actie of expliciete source-aware branch voor "Copy remote file to host" - niet de bestaande upload-flow hergebruiken ### Agentontwerp Geen nieuwe agent-endpoints nodig in deze scope. De bestaande `GET /api/download` is voldoende als read-only bron voor streaming. ## Acceptance criteria - een enkel bestand onder `/Clients/...` kan naar een host-directory worden gekopieerd - de destination moet een host/local directory zijn - mappen als remote bron worden geweigerd - remote -> remote wordt geweigerd - host -> remote wordt geweigerd - overwrite gebeurt niet impliciet; bestaand doelbestand geeft een nette fout - bestaande upload-route, upload-contract en upload-UI blijven ongewijzigd - bestaande lokale copy-flow blijft ongewijzigd - remote fouten blijven lokaal tot deze actie - host-write blijft onder bestaande lokale `PathGuard`-regels vallen - data wordt gestreamd; geen volledige file-buffer in memory ## Klein plan 1. Voeg een research-backed change request toe voor een aparte route `POST /api/files/remote-copy`. 2. Voeg een kleine service toe die alleen remote single-file source + local destination_dir ondersteunt. 3. Voeg een interne streaming helper toe in `RemoteFileService` voor remote bestand-inname door backend. 4. Voeg een aparte interne host-write helper toe in `FilesystemAdapter` voor generieke stream-naar-bestand writes, zonder upload-API te wijzigen. 5. Voeg minimale frontend wiring toe voor een aparte "Copy remote file to host"-actie. 6. Test stapsgewijs: - success path remote file -> local dir - bestaand doelbestand - remote directory rejected - remote failure stays local - upload-regressie: bestaande `/api/files/upload` blijft ongewijzigd ## Expliciete lijst van wat buiten scope blijft - remote mappen kopiƫren - remote write-acties - remote -> remote - host -> remote - aanpassing van bestaande upload-routes - aanpassing van upload-requestcontract - aanpassing van upload-UI - brede refactor van copy/upload/task-infrastructuur - bookmarks/startup paths - remote task-runner verbreding buiten deze ene actie