Voor remote client agent
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
# Remote Client Shares Implementation Phases V1.1
|
||||
|
||||
## Doel
|
||||
|
||||
Dit document splitst `REMOTE_CLIENT_SHARES_V1_DESIGN.md` op in pragmatische implementatiefases.
|
||||
|
||||
Uitgangspunten:
|
||||
|
||||
- geen overengineering
|
||||
- elke fase moet zelfstandig waarde leveren
|
||||
- WebManager mag nooit blokkeren op remote agents
|
||||
- bestaande storage-functionaliteit moet intact blijven
|
||||
- `/Clients` blijft een aparte source, geen uitbreiding van lokale filesystem roots
|
||||
|
||||
---
|
||||
|
||||
## Overzicht
|
||||
|
||||
### Phase 1
|
||||
|
||||
Client registry, identiteit en statusmodel.
|
||||
|
||||
### Phase 2
|
||||
|
||||
Browse van remote client shares via virtuele `Clients` root.
|
||||
|
||||
### Phase 3
|
||||
|
||||
Info, tekstpreview, eenvoudige image preview en download voor remote shares.
|
||||
|
||||
### Later
|
||||
|
||||
Alle write-acties, bookmarks/startup paths en cross-source flows.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Client Registry
|
||||
|
||||
## Doel
|
||||
|
||||
WebManager moet remote agents kennen, identificeren en hun status betrouwbaar kunnen bijhouden.
|
||||
|
||||
## Resultaat
|
||||
|
||||
De backend en UI kunnen een lijst van bekende clients tonen, inclusief stabiele identiteit en basisstatus.
|
||||
|
||||
## In scope
|
||||
|
||||
- remote client registratie
|
||||
- heartbeat endpoint
|
||||
- opslag van client metadata
|
||||
- statusmodel met gescheiden velden
|
||||
- lijstendpoint voor bekende clients
|
||||
- registratie-auth
|
||||
- agent-access-auth contract vastleggen
|
||||
|
||||
## Niet in scope
|
||||
|
||||
- browsen in shares
|
||||
- file operations
|
||||
- download
|
||||
- rename/delete/mkdir
|
||||
|
||||
## Beslissingen
|
||||
|
||||
- `client_id` is leidend
|
||||
- `display_name` is niet leidend
|
||||
- browse-routing mag niet afhankelijk zijn van alleen displaynaam
|
||||
- `last_seen`, `status`, `last_error` en `reachable_at` blijven logisch gescheiden
|
||||
|
||||
## Backendwerk
|
||||
|
||||
Nieuwe onderdelen:
|
||||
|
||||
- repository voor remote clients
|
||||
- service voor registratie en heartbeat
|
||||
- statusafleiding
|
||||
- opslag van auth- en endpointmetadata
|
||||
- routes:
|
||||
- `POST /api/clients/register`
|
||||
- `POST /api/clients/heartbeat`
|
||||
- `GET /api/clients`
|
||||
|
||||
Waarschijnlijk te wijzigen:
|
||||
|
||||
- [main.py](/workspace/webmanager-mvp/webui/backend/app/main.py)
|
||||
- [dependencies.py](/workspace/webmanager-mvp/webui/backend/app/dependencies.py)
|
||||
|
||||
Waarschijnlijk nieuw:
|
||||
|
||||
- `webui/backend/app/api/routes_clients.py`
|
||||
- `webui/backend/app/services/remote_client_service.py`
|
||||
- `webui/backend/app/db/remote_client_repository.py`
|
||||
|
||||
## Agentwerk
|
||||
|
||||
- vaste config inlezen
|
||||
- `client_id` beheren
|
||||
- registratie naar WebManager
|
||||
- periodieke heartbeat
|
||||
- agent-access-token config toevoegen
|
||||
|
||||
## UI-werk
|
||||
|
||||
Minimaal:
|
||||
|
||||
- geen browse-integratie nodig
|
||||
- een eenvoudige clientlijst of debug-status is voldoende
|
||||
|
||||
## Acceptatiecriteria
|
||||
|
||||
- agent kan zich registreren
|
||||
- client verschijnt in `GET /api/clients`
|
||||
- `last_seen` wordt bijgewerkt
|
||||
- `status` wordt afgeleid zonder te flappen
|
||||
- `last_error` en `reachable_at` bestaan als apart concept
|
||||
- server blijft normaal werken als er geen agents bestaan
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Browse via `/Clients`
|
||||
|
||||
## Doel
|
||||
|
||||
Remote clients en hun shares moeten zichtbaar worden in dezelfde browse-ervaring als server storage, zonder lokale services te vervormen.
|
||||
|
||||
## Resultaat
|
||||
|
||||
De gebruiker kan navigeren naar:
|
||||
|
||||
- `/Clients`
|
||||
- `/Clients/<client>`
|
||||
- `/Clients/<client>/<share>`
|
||||
|
||||
## In scope
|
||||
|
||||
- virtuele root `/Clients`
|
||||
- clientlijst als directories
|
||||
- sharelijst per client als directories
|
||||
- browse binnen share
|
||||
- offline foutafhandeling
|
||||
- agent-auth op browsecalls
|
||||
|
||||
## Niet in scope
|
||||
|
||||
- view/download
|
||||
- edit
|
||||
- rename/delete/mkdir
|
||||
- bookmarks/startup paths
|
||||
|
||||
## Beslissingen
|
||||
|
||||
- `/Clients` wordt vroeg in de backend-route afgehandeld
|
||||
- remote paden mogen niet in gewone lokale `PathGuard` resolution terechtkomen
|
||||
- lokale browse-services blijven verantwoordelijk voor alleen lokale server sources
|
||||
|
||||
## Backendwerk
|
||||
|
||||
Waarschijnlijk te wijzigen:
|
||||
|
||||
- [routes_browse.py](/workspace/webmanager-mvp/webui/backend/app/api/routes_browse.py)
|
||||
|
||||
Liever niet verbreden:
|
||||
|
||||
- [path_guard.py](/workspace/webmanager-mvp/webui/backend/app/security/path_guard.py)
|
||||
|
||||
Nieuwe onderdelen:
|
||||
|
||||
- browse-facade voor remote client paden
|
||||
- agent HTTP client met korte timeouts en auth
|
||||
|
||||
## UI-werk
|
||||
|
||||
Waarschijnlijk te wijzigen:
|
||||
|
||||
- [app.js](/workspace/webmanager-mvp/webui/html/app.js)
|
||||
|
||||
Benodigd:
|
||||
|
||||
- rootnavigatie voor `/Clients`
|
||||
- breadcrumbs voor client/share-paden
|
||||
- render van client/status/share directories
|
||||
- nette foutmelding bij offline client
|
||||
|
||||
## Agentwerk
|
||||
|
||||
Nieuwe browse endpoint(s):
|
||||
|
||||
- `GET /health`
|
||||
- `GET /api/list?share=...&path=...`
|
||||
|
||||
## Acceptatiecriteria
|
||||
|
||||
- `/Clients` toont bekende clients
|
||||
- `/Clients/<client>` toont alleen toegestane shares
|
||||
- `/Clients/<client>/<share>` toont directory-inhoud
|
||||
- offline client geeft een snelle fout, geen hang
|
||||
- `/Volumes` gedrag blijft intact
|
||||
- lokale browse-code blijft logisch gescheiden van remote browse-code
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Info, Preview, Download
|
||||
|
||||
## Doel
|
||||
|
||||
Remote shares moeten read-only bruikbaar worden voor dagelijkse taken.
|
||||
|
||||
## Resultaat
|
||||
|
||||
Gebruiker kan bestanden in remote shares inspecteren, bekijken en downloaden.
|
||||
|
||||
## In scope
|
||||
|
||||
- file info
|
||||
- tekstpreview
|
||||
- eenvoudige image preview
|
||||
- download van remote bestanden
|
||||
- expliciete resource-limieten
|
||||
|
||||
## Niet in scope
|
||||
|
||||
- edit
|
||||
- rename/delete/mkdir
|
||||
- upload
|
||||
- cross-source copy/move
|
||||
|
||||
## Beslissingen
|
||||
|
||||
- tekstpreview krijgt een harde limiet
|
||||
- text/binary-detectie moet expliciet zijn
|
||||
- downloads worden gestreamd
|
||||
- geen grote in-memory buffering voor download
|
||||
|
||||
## Backendwerk
|
||||
|
||||
Nieuwe facade of routes voor remote file actions:
|
||||
|
||||
- info
|
||||
- read/view
|
||||
- download
|
||||
|
||||
Belangrijk:
|
||||
|
||||
- backend vertaalt WebManager-pad naar agent-call
|
||||
- timeouts en foutmapping blijven streng
|
||||
- source-aware afhandeling blijft gescheiden van lokale file ops
|
||||
|
||||
Waarschijnlijk geraakt:
|
||||
|
||||
- `routes_files.py` of parallelle remote-fileroute
|
||||
- aparte service-laag voor remote file proxying
|
||||
|
||||
## UI-werk
|
||||
|
||||
Waarschijnlijk te wijzigen:
|
||||
|
||||
- [app.js](/workspace/webmanager-mvp/webui/html/app.js)
|
||||
|
||||
Benodigd:
|
||||
|
||||
- source-aware afhandeling voor `View`
|
||||
- downloadknop moet remote paths ondersteunen
|
||||
- properties/info moet ook werken voor remote paden
|
||||
|
||||
## Agentwerk
|
||||
|
||||
Nieuwe endpoints:
|
||||
|
||||
- `GET /api/info`
|
||||
- `GET /api/read`
|
||||
- `GET /api/download`
|
||||
|
||||
## Acceptatiecriteria
|
||||
|
||||
- file info werkt voor remote paden
|
||||
- tekstbestand kan bekeken worden binnen limieten
|
||||
- afbeelding kan bekeken worden als ondersteund
|
||||
- download van remote bestand werkt via streaming
|
||||
- foutafhandeling blijft lokaal tot betreffende pane/actie
|
||||
|
||||
---
|
||||
|
||||
## Later
|
||||
|
||||
Deze onderdelen horen niet in V1.1.
|
||||
|
||||
### Write-acties
|
||||
|
||||
- mkdir
|
||||
- rename
|
||||
- delete
|
||||
- upload
|
||||
|
||||
### UI-integraties
|
||||
|
||||
- bookmarks voor `/Clients/...`
|
||||
- startup paths voor `/Clients/...`
|
||||
|
||||
### Cross-source flows
|
||||
|
||||
- `/Volumes/...` naar `/Clients/...`
|
||||
- `/Clients/...` naar `/Volumes/...`
|
||||
|
||||
Dit vereist expliciete transfersemantiek en hoort niet in de eerste read-mostly release.
|
||||
|
||||
### Zwaardere netwerkmodellen
|
||||
|
||||
- reverse-connect
|
||||
- tunnelmodel
|
||||
- relay-infrastructuur
|
||||
|
||||
### Sterkere pairing
|
||||
|
||||
- pair codes
|
||||
- per-agent secret rotation
|
||||
- signed registration
|
||||
|
||||
---
|
||||
|
||||
## Aanbevolen volgorde
|
||||
|
||||
1. Phase 1 volledig afronden.
|
||||
2. Daarna Phase 2 volledig afronden.
|
||||
3. Daarna Phase 3 read-only afronden.
|
||||
4. Alles daarna alleen oppakken als een concrete productbehoefte dat rechtvaardigt.
|
||||
|
||||
---
|
||||
|
||||
## Beslisadvies
|
||||
|
||||
Als er snel waarde geleverd moet worden, is de beste minimale keten:
|
||||
|
||||
1. registry
|
||||
2. browse
|
||||
3. info/preview/download
|
||||
|
||||
Daarmee ontstaat een bruikbare remote client bron zonder write-complexiteit, contractbreuk in lokale services of half-afgewerkte transferlogica.
|
||||
@@ -0,0 +1,697 @@
|
||||
# Remote Client Shares V1.1 Design
|
||||
|
||||
## Doel
|
||||
|
||||
Een gebruiker van WebManager moet naast de bestaande server-side storage-roots ook een beperkte set lokale mappen van zijn eigen client-Mac kunnen benaderen, zonder de hele homefolder bloot te geven.
|
||||
|
||||
Voorbeelden van toegestane client-shares:
|
||||
|
||||
- `Downloads`
|
||||
- `Movies`
|
||||
- `Pictures`
|
||||
|
||||
De oplossing moet:
|
||||
|
||||
- simpel blijven
|
||||
- veilig blijven
|
||||
- de bestaande storage-workflow niet breken
|
||||
- WebManager niet laten vastlopen als een remote helper-agent offline is
|
||||
|
||||
---
|
||||
|
||||
## Kernbeslissingen voor V1.1
|
||||
|
||||
Deze beslissingen liggen in V1.1 vast.
|
||||
|
||||
- Remote client shares worden niet opgenomen in `root_aliases`.
|
||||
- `/Clients` wordt een aparte virtuele bron naast `/Volumes`.
|
||||
- Remote paden lopen niet door de bestaande lokale filesystem-resolutie.
|
||||
- `client_id` is intern de enige leidende identiteit.
|
||||
- `display_name` is alleen voor UI-weergave.
|
||||
- De agent werkt alleen met `share key + relatief pad`.
|
||||
- Alle agent-calls vereisen authenticatie, niet alleen registratie.
|
||||
- Offline agents mogen alleen hun eigen subtree beïnvloeden, nooit de rest van de app.
|
||||
- V1 blijft read-mostly: registry, browse, info, preview, download.
|
||||
|
||||
---
|
||||
|
||||
## Waarom niet als gewone root alias
|
||||
|
||||
De huidige backend gaat uit van server-side whitelisted filesystem roots.
|
||||
|
||||
Dat model werkt voor:
|
||||
|
||||
- `/Volumes/...`
|
||||
- gemounte server storage
|
||||
- container-side toegankelijke paden
|
||||
|
||||
Dat model werkt niet goed voor:
|
||||
|
||||
- de lokale schijf van de browsergebruiker
|
||||
- een remote Mac die buiten de server draait
|
||||
- clients die offline kunnen zijn
|
||||
- clients die dynamische IP-adressen hebben
|
||||
|
||||
Daarom mogen remote client shares niet in hetzelfde model worden gestopt als `root_aliases`.
|
||||
|
||||
---
|
||||
|
||||
## Scope V1.1
|
||||
|
||||
### In scope
|
||||
|
||||
- beperkte client-shares: `Downloads`, `Movies`, `Pictures`
|
||||
- lokale helper-agent op macOS
|
||||
- agent registratie in WebManager
|
||||
- heartbeat/status tracking
|
||||
- virtuele `Clients` bron in de WebUI
|
||||
- browse van remote shares
|
||||
- bestand-info
|
||||
- tekstpreview
|
||||
- image preview waar triviaal
|
||||
- download van bestanden
|
||||
- nette offline-afhandeling
|
||||
|
||||
### Expliciet niet in V1.1
|
||||
|
||||
- hele homefolder
|
||||
- willekeurige custom paths buiten de toegestane sharelijst
|
||||
- shell/subprocess execution
|
||||
- rename
|
||||
- mkdir
|
||||
- delete
|
||||
- upload naar remote share
|
||||
- bookmarks voor `/Clients/...`
|
||||
- startup paths voor `/Clients/...`
|
||||
- cross-source copy of move
|
||||
- complete taakrunner-integratie zoals server copy/move tasks
|
||||
- automatische LAN discovery
|
||||
- multi-user auth met OS user mapping
|
||||
|
||||
---
|
||||
|
||||
## Gewenste gebruikerservaring
|
||||
|
||||
In de WebUI komt naast server-storage een extra virtuele bron:
|
||||
|
||||
- `/Volumes`
|
||||
- `/Clients`
|
||||
|
||||
Onder `/Clients` ziet de gebruiker geregistreerde clients, bijvoorbeeld:
|
||||
|
||||
- `MacBook Pro van Jan`
|
||||
- `iMac Woonkamer`
|
||||
|
||||
Onder een client ziet de gebruiker alleen de toegestane shares:
|
||||
|
||||
- `Downloads`
|
||||
- `Movies`
|
||||
- `Pictures`
|
||||
|
||||
Voor de gebruiker kan dat eruitzien als:
|
||||
|
||||
- `/Clients/MacBook-Pro-van-Jan/Downloads`
|
||||
- `/Clients/MacBook-Pro-van-Jan/Movies`
|
||||
- `/Clients/MacBook-Pro-van-Jan/Pictures`
|
||||
|
||||
Maar intern mag routing niet op `display_name` leunen.
|
||||
|
||||
Intern moet WebManager werken met een stabiele client-identiteit en een mappinglaag:
|
||||
|
||||
- `client_id` voor routing en opslag
|
||||
- `display_name` voor weergave
|
||||
- optioneel een afgeleide slug voor browse-url-presentatie
|
||||
|
||||
---
|
||||
|
||||
## Architectuuroverzicht
|
||||
|
||||
Er zijn drie componenten.
|
||||
|
||||
### 1. WebManager backend
|
||||
|
||||
Verantwoordelijk voor:
|
||||
|
||||
- registry van bekende remote clients
|
||||
- status- en heartbeat-tracking
|
||||
- virtuele browse-root `Clients`
|
||||
- proxying van requests naar agents
|
||||
- timeouts en foutafhandeling
|
||||
- scheiding tussen local-source en remote-source afhandeling
|
||||
|
||||
### 2. WebUI frontend
|
||||
|
||||
Verantwoordelijk voor:
|
||||
|
||||
- tonen van `Clients` als extra bron
|
||||
- navigeren binnen client/share paden
|
||||
- offline status tonen
|
||||
- requests afvuren naar gewone WebManager backend-routes
|
||||
|
||||
### 3. Remote helper-agent op macOS
|
||||
|
||||
Verantwoordelijk voor:
|
||||
|
||||
- toegang tot vaste lokale shares
|
||||
- strikte padvalidatie binnen die shares
|
||||
- simpele browse/info/read/download endpoints
|
||||
- zichzelf registreren bij WebManager
|
||||
- heartbeat sturen
|
||||
- auth afdwingen op alle agent-endpoints
|
||||
|
||||
---
|
||||
|
||||
## Bereikbaarheidsmodel
|
||||
|
||||
Dit is de eerste harde productbeslissing.
|
||||
|
||||
### V1.1-keuze
|
||||
|
||||
V1.1 gaat uit van een omgeving waarin WebManager de agent rechtstreeks kan bereiken.
|
||||
|
||||
Dat betekent praktisch:
|
||||
|
||||
- dezelfde LAN
|
||||
- of een expliciet configureerbaar agent-endpoint
|
||||
- of een deployment waar server en client netwerkmatig direct verbonden zijn
|
||||
|
||||
### Waarom deze keuze
|
||||
|
||||
Dit is het simpelste model dat functioneel klopt zonder reverse tunnels, websockets als transportlaag, of extra relay-infrastructuur.
|
||||
|
||||
### Wat V1.1 niet probeert op te lossen
|
||||
|
||||
Deze versie garandeert niet dat een agent achter willekeurige NAT/firewall altijd bereikbaar is.
|
||||
|
||||
Dus:
|
||||
|
||||
- self-registration blijft het discoverymodel
|
||||
- direct bereikbare agent-endpoint blijft het V1-transportmodel
|
||||
- reverse-connect of tunnelmodellen zijn uitgesteld
|
||||
|
||||
### Fallback
|
||||
|
||||
Een handmatige endpoint override blijft toegestaan als operationele fallback, bijvoorbeeld:
|
||||
|
||||
- `http://192.168.1.25:8765`
|
||||
|
||||
Maar dat is geen hoofdmodel en geen productbelofte.
|
||||
|
||||
---
|
||||
|
||||
## Hoe de remote agent bekend wordt in WebManager
|
||||
|
||||
### Gekozen model: agent registreert zichzelf
|
||||
|
||||
De agent meldt zichzelf actief aan bij WebManager. Niet andersom.
|
||||
|
||||
Dat betekent:
|
||||
|
||||
- geen handmatig client-IP nodig als hoofdmodel
|
||||
- geen server-naar-client discovery nodig
|
||||
- geen afhankelijkheid van LAN-broadcasting
|
||||
- geen probleem als het client-IP wisselt, zolang het geregistreerde endpoint actueel is
|
||||
|
||||
### Registratiestroom
|
||||
|
||||
Bij starten van de agent:
|
||||
|
||||
1. de agent leest lokale config
|
||||
2. de agent bepaalt:
|
||||
- `client_id`
|
||||
- `display_name`
|
||||
- `shares`
|
||||
- `endpoint`
|
||||
3. de agent registreert zich bij WebManager
|
||||
4. WebManager slaat client-record op of werkt het bij
|
||||
5. de agent stuurt periodieke heartbeats
|
||||
|
||||
### Benodigde velden bij registratie
|
||||
|
||||
Voorstel:
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "f4b2c8f8-2b1b-4d89-9ed2-8d6d7b1f3abc",
|
||||
"display_name": "MacBook Pro van Jan",
|
||||
"platform": "macos",
|
||||
"agent_version": "1.1.0",
|
||||
"endpoint": "http://192.168.1.25:8765",
|
||||
"shares": [
|
||||
{ "key": "downloads", "label": "Downloads" },
|
||||
{ "key": "movies", "label": "Movies" },
|
||||
{ "key": "pictures", "label": "Pictures" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Backend bewaart per client
|
||||
|
||||
- `client_id`
|
||||
- `display_name`
|
||||
- `platform`
|
||||
- `agent_version`
|
||||
- `endpoint`
|
||||
- `shares`
|
||||
- `last_seen`
|
||||
- `status`
|
||||
- `last_error`
|
||||
- `reachable_at`
|
||||
- eventueel `registration_token_id`
|
||||
|
||||
### Heartbeat
|
||||
|
||||
De agent stuurt elke 15-30 seconden een heartbeat.
|
||||
|
||||
Bijvoorbeeld:
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "f4b2c8f8-2b1b-4d89-9ed2-8d6d7b1f3abc",
|
||||
"agent_version": "1.1.0"
|
||||
}
|
||||
```
|
||||
|
||||
### Statusmodel
|
||||
|
||||
Deze velden moeten logisch gescheiden blijven:
|
||||
|
||||
- `last_seen`
|
||||
Laatste succesvolle heartbeat van de agent.
|
||||
- `status`
|
||||
Afgeleide UI-status, bijvoorbeeld `online` of `offline`.
|
||||
- `last_error`
|
||||
Laatste connect- of browsefout richting agent.
|
||||
- `reachable_at`
|
||||
Laatste moment waarop een directe agent-call echt succesvol was.
|
||||
|
||||
Belangrijk:
|
||||
|
||||
- een heartbeat bepaalt niet automatisch dat elke browse-call werkt
|
||||
- een enkele browse-timeout mag niet blind `last_seen` overschrijven
|
||||
- status mag niet gaan flappen op basis van één los incident
|
||||
|
||||
### Aanbevolen statusregels
|
||||
|
||||
- `online` als `last_seen` recent is
|
||||
- `offline` als heartbeat-timeout overschreden is
|
||||
- extra foutdetails via `last_error`
|
||||
- optioneel UI-label zoals `online with recent errors` later, maar niet nodig in V1.1
|
||||
|
||||
---
|
||||
|
||||
## Authenticatie en beveiliging
|
||||
|
||||
### Backend registratie-auth
|
||||
|
||||
Registratie vereist een bearer token.
|
||||
|
||||
Bijvoorbeeld:
|
||||
|
||||
- `Authorization: Bearer <registration-token>`
|
||||
|
||||
### Agent endpoint-auth
|
||||
|
||||
Alle agent-calls vereisen authenticatie. Niet alleen registratie.
|
||||
|
||||
Dus ook:
|
||||
|
||||
- `/health`
|
||||
- `/api/list`
|
||||
- `/api/info`
|
||||
- `/api/read`
|
||||
- `/api/download`
|
||||
|
||||
moeten beschermd zijn.
|
||||
|
||||
### V1.1 minimum
|
||||
|
||||
Voor V1.1 volstaat een eenvoudige gedeelde agent-token, bijvoorbeeld:
|
||||
|
||||
- WebManager bewaart een secret per client of per installatie
|
||||
- backend stuurt dat token mee op elke agent-call
|
||||
- agent weigert requests zonder geldig token
|
||||
|
||||
Voorbeeld:
|
||||
|
||||
- `Authorization: Bearer <agent-access-token>`
|
||||
|
||||
### Niet doen in V1.1
|
||||
|
||||
- open agent-HTTP API zonder auth
|
||||
- browse/download endpoints publiek bereikbaar maken op het LAN
|
||||
|
||||
---
|
||||
|
||||
## Virtueel padmodel
|
||||
|
||||
Remote client shares krijgen een aparte namespace.
|
||||
|
||||
Voorstel voor de gebruikersweergave:
|
||||
|
||||
- `/Clients`
|
||||
- `/Clients/<client-display>`
|
||||
- `/Clients/<client-display>/<share-label>`
|
||||
- `/Clients/<client-display>/<share-label>/subdir/file.ext`
|
||||
|
||||
Intern moet de backend dit mappen naar:
|
||||
|
||||
- `client_id`
|
||||
- `share_key`
|
||||
- relatief share-pad
|
||||
|
||||
Belangrijk:
|
||||
|
||||
- dit zijn logische WebManager-paden
|
||||
- het zijn geen echte lokale backend filesystem-paden
|
||||
- ze mogen niet door de bestaande lokale `PathGuard` resolved worden
|
||||
|
||||
### Consequentie voor de codebasis
|
||||
|
||||
`/Clients/...` moet vroeg in routing worden onderschept door een aparte browse- of source-facade.
|
||||
|
||||
Dus:
|
||||
|
||||
- niet de lokale `PathGuard` uitbreiden tot remote sources
|
||||
- niet overal `if remote` in bestaande lokale services strooien
|
||||
- wel een duidelijke scheiding tussen local source en remote source
|
||||
|
||||
---
|
||||
|
||||
## Share-validatie in de agent
|
||||
|
||||
De agent werkt niet met vrije absolute paden.
|
||||
|
||||
De agent heeft een vaste share-map, bijvoorbeeld:
|
||||
|
||||
```json
|
||||
{
|
||||
"downloads": "/Users/jan/Downloads",
|
||||
"movies": "/Users/jan/Movies",
|
||||
"pictures": "/Users/jan/Pictures"
|
||||
}
|
||||
```
|
||||
|
||||
Een request bevat dan:
|
||||
|
||||
- `share = downloads`
|
||||
- `path = Some/Subdir/file.txt`
|
||||
|
||||
Niet:
|
||||
|
||||
- `/Users/jan/...`
|
||||
|
||||
### Validatieregels
|
||||
|
||||
- onbekende `share` weigeren
|
||||
- `..` weigeren
|
||||
- pad resolven binnen de gekozen share-root
|
||||
- symlink escape blokkeren
|
||||
- alleen toegestane bestandshandelingen toestaan
|
||||
|
||||
---
|
||||
|
||||
## Read, preview en download limieten
|
||||
|
||||
V1.1 moet resource-grenzen expliciet vastleggen.
|
||||
|
||||
### Tekstpreview
|
||||
|
||||
- maximum grootte voor tekstpreview vastleggen
|
||||
- voorstel: zelfde orde als huidige server-side preview/edit-limieten, of kleiner
|
||||
- grote tekstbestanden niet volledig in memory laden voor preview
|
||||
|
||||
### Binary versus text
|
||||
|
||||
- agent moet tekstpreview alleen teruggeven voor ondersteunde teksttypes
|
||||
- binaire content mag niet per ongeluk als tekst in JSON-responses worden gepusht
|
||||
|
||||
### Download
|
||||
|
||||
- downloads moeten gestreamd worden
|
||||
- geen volledige bestand-buffering in memory
|
||||
|
||||
### Image preview
|
||||
|
||||
- alleen triviale image preview in V1.1
|
||||
- geen zware thumbnail-pipeline in deze fase
|
||||
|
||||
---
|
||||
|
||||
## Offline gedrag
|
||||
|
||||
Dit is een harde eis.
|
||||
|
||||
WebManager mag niet vastlopen als de agent niet draait.
|
||||
|
||||
### Backendregels
|
||||
|
||||
- alle agent-calls krijgen korte timeouts, bijvoorbeeld 1-3 seconden
|
||||
- connect- of timeoutfouten worden vertaald naar nette app-fouten
|
||||
- offline agent blokkeert nooit globale pagina-initialisatie
|
||||
- browse- en file-fouten blijven lokaal tot betreffende request
|
||||
|
||||
### Frontendregels
|
||||
|
||||
- `/Clients` mag laden, ook als sommige clients offline zijn
|
||||
- offline clients mogen zichtbaar blijven in de lijst
|
||||
- browsen in offline subtree toont foutmelding
|
||||
- andere panes blijven bruikbaar
|
||||
- geen endless spinner
|
||||
|
||||
---
|
||||
|
||||
## API-ontwerp
|
||||
|
||||
## 1. Backend registry endpoints
|
||||
|
||||
### `POST /api/clients/register`
|
||||
|
||||
Registreert of update een remote agent.
|
||||
|
||||
### `POST /api/clients/heartbeat`
|
||||
|
||||
Werkt `last_seen` bij.
|
||||
|
||||
### `GET /api/clients`
|
||||
|
||||
Geeft bekende clients terug met:
|
||||
|
||||
- `client_id`
|
||||
- `display_name`
|
||||
- `status`
|
||||
- `last_seen`
|
||||
- `last_error`
|
||||
- `shares`
|
||||
|
||||
---
|
||||
|
||||
## 2. Backend browse facade voor UI
|
||||
|
||||
De frontend blijft praten met gewone WebManager-routes.
|
||||
|
||||
### `GET /api/browse?path=/Clients`
|
||||
|
||||
Geeft alle bekende clients terug als directories.
|
||||
|
||||
### `GET /api/browse?path=/Clients/<client>/`
|
||||
|
||||
Geeft shares van die client terug als directories.
|
||||
|
||||
### `GET /api/browse?path=/Clients/<client>/<share>/...`
|
||||
|
||||
Backend vertaalt dit naar een agent-call.
|
||||
|
||||
Belangrijk:
|
||||
|
||||
- browse facade bepaalt eerst of pad onder `/Clients` valt
|
||||
- alleen niet-remote paden mogen daarna naar bestaande lokale browse-paths
|
||||
|
||||
---
|
||||
|
||||
## 3. Agent endpoints
|
||||
|
||||
Eenvoudig houden. Geen shell.
|
||||
|
||||
### `GET /health`
|
||||
|
||||
Gezondheidscheck met auth.
|
||||
|
||||
### `GET /api/list?share=downloads&path=subdir`
|
||||
|
||||
Directory-inhoud binnen een share.
|
||||
|
||||
### `GET /api/info?share=downloads&path=file.txt`
|
||||
|
||||
Metadata.
|
||||
|
||||
### `GET /api/read?share=downloads&path=file.txt`
|
||||
|
||||
Tekstpreview.
|
||||
|
||||
### `GET /api/download?share=downloads&path=file.txt`
|
||||
|
||||
Gestreamde download.
|
||||
|
||||
---
|
||||
|
||||
## Haalbaarheid
|
||||
|
||||
## Goed haalbaar in V1.1
|
||||
|
||||
- client registry
|
||||
- heartbeat online/offline
|
||||
- virtuele `Clients` root
|
||||
- browse
|
||||
- file info
|
||||
- tekstpreview
|
||||
- eenvoudige image preview
|
||||
- gestreamde download
|
||||
|
||||
## Bewust uitgesteld
|
||||
|
||||
- rename
|
||||
- mkdir
|
||||
- delete
|
||||
- upload
|
||||
- bookmarks/startup paths
|
||||
- cross-source copy
|
||||
- cross-source move
|
||||
- unified history
|
||||
- task-runner integratie
|
||||
|
||||
---
|
||||
|
||||
## Veranderingen per gebied
|
||||
|
||||
## Backend
|
||||
|
||||
Nieuwe onderdelen:
|
||||
|
||||
- client registry repository
|
||||
- client registry service
|
||||
- routes voor register/heartbeat/list
|
||||
- browse/source facade voor `Clients/...`
|
||||
- agent HTTP client met harde timeouts en auth
|
||||
|
||||
Bestaande onderdelen die waarschijnlijk geraakt worden:
|
||||
|
||||
- [routes_browse.py](/workspace/webmanager-mvp/webui/backend/app/api/routes_browse.py)
|
||||
Om `/Clients` vroeg te routeren.
|
||||
- [dependencies.py](/workspace/webmanager-mvp/webui/backend/app/dependencies.py)
|
||||
Voor nieuwe registry- en agent-services.
|
||||
- [app/main.py](/workspace/webmanager-mvp/webui/backend/app/main.py)
|
||||
Voor nieuwe routers.
|
||||
|
||||
Liever niet verbreden:
|
||||
|
||||
- [path_guard.py](/workspace/webmanager-mvp/webui/backend/app/security/path_guard.py)
|
||||
Deze hoort lokaal filesystemgericht te blijven.
|
||||
- [file_ops_service.py](/workspace/webmanager-mvp/webui/backend/app/services/file_ops_service.py)
|
||||
Deze service is nu server-filesystemgericht en moet niet vervuild raken met remote transportlogica.
|
||||
|
||||
## Frontend
|
||||
|
||||
Waarschijnlijk aanpassen:
|
||||
|
||||
- [app.js](/workspace/webmanager-mvp/webui/html/app.js)
|
||||
Voor:
|
||||
- extra virtuele root
|
||||
- render van clients en shares
|
||||
- offline status
|
||||
- source-aware browse/view/download/info flows
|
||||
- [index.html](/workspace/webmanager-mvp/webui/html/index.html)
|
||||
Alleen als extra statuslabels of clientindicatoren nodig zijn
|
||||
|
||||
## Remote agent
|
||||
|
||||
Te baseren op:
|
||||
|
||||
- [finder_commander/app/main.py](/workspace/webmanager-mvp/finder_commander/app/main.py)
|
||||
- [finder_commander/run-local.sh](/workspace/webmanager-mvp/finder_commander/run-local.sh)
|
||||
- [finder_commander/requirements.txt](/workspace/webmanager-mvp/finder_commander/requirements.txt)
|
||||
|
||||
Maar vereenvoudigd:
|
||||
|
||||
- geen shell command endpoint
|
||||
- geen hele home-root
|
||||
- alleen `share key + relatief pad`
|
||||
- registratie en heartbeat toevoegen
|
||||
- auth afdwingen op alle endpoints
|
||||
|
||||
---
|
||||
|
||||
## Minimale agent-config
|
||||
|
||||
Voorstel lokaal configbestand:
|
||||
|
||||
```json
|
||||
{
|
||||
"webmanager_base_url": "https://webmanager.example.com",
|
||||
"registration_token": "registration-secret",
|
||||
"agent_access_token": "agent-secret",
|
||||
"client_id": "f4b2c8f8-2b1b-4d89-9ed2-8d6d7b1f3abc",
|
||||
"display_name": "MacBook Pro van Jan",
|
||||
"shares": {
|
||||
"downloads": "/Users/jan/Downloads",
|
||||
"movies": "/Users/jan/Movies",
|
||||
"pictures": "/Users/jan/Pictures"
|
||||
},
|
||||
"listen_host": "0.0.0.0",
|
||||
"listen_port": 8765,
|
||||
"public_endpoint": "http://192.168.1.25:8765"
|
||||
}
|
||||
```
|
||||
|
||||
Opmerking:
|
||||
|
||||
- `public_endpoint` is het endpoint dat WebManager gebruikt
|
||||
- `listen_host` en `public_endpoint` hoeven niet identiek te zijn
|
||||
|
||||
---
|
||||
|
||||
## Open keuzes die bewust zijn uitgesteld
|
||||
|
||||
Deze keuzes zijn echt later werk, niet meer V1.1:
|
||||
|
||||
- reverse-connect of tunnelmodel
|
||||
- cross-source copy
|
||||
- cross-source move
|
||||
- bookmarks/startup paths voor `/Clients/...`
|
||||
- write-acties op remote shares
|
||||
- sterkere pairing of key rotation
|
||||
|
||||
---
|
||||
|
||||
## Beslisadvies
|
||||
|
||||
Aanbevolen implementatievolgorde voor V1.1:
|
||||
|
||||
1. agent registry + heartbeat
|
||||
2. virtuele `Clients` root in browse
|
||||
3. online/offline status met gescheiden statusvelden
|
||||
4. browse/info/preview/download voor remote shares
|
||||
|
||||
Niet in V1.1:
|
||||
|
||||
5. write-acties
|
||||
6. bookmarks/startup paths
|
||||
7. cross-source flows
|
||||
|
||||
---
|
||||
|
||||
## Samenvatting
|
||||
|
||||
De juiste V1.1-richting is:
|
||||
|
||||
- geen hele homefolder
|
||||
- wel beperkte shares zoals `Downloads`, `Movies`, `Pictures`
|
||||
- remote helper-agent op macOS
|
||||
- agent registreert zichzelf bij WebManager
|
||||
- WebManager bewaart `client_id`-geleide registry en status
|
||||
- `/Clients` wordt een aparte virtuele bron
|
||||
- remote paden blijven buiten lokale filesystem services
|
||||
- alle agent-calls vereisen auth
|
||||
- offline agents mogen nooit de rest van WebManager verstoren
|
||||
|
||||
Dit model is haalbaar, beperkt in scope, en houdt de bestaande lokale storage-architectuur schoon.
|
||||
Reference in New Issue
Block a user