Files
webmanager-mvp/PLAN.md
T
2026-03-11 09:39:41 +01:00

366 lines
11 KiB
Markdown

# PLAN.md
Notitie: `project_docs/SPARRING_GPT_PROJECT_PROMPT.md` is niet gevonden in deze repository op 10 maart 2026. Dit plan is opgesteld op basis van de overige documenten in `project_docs/`.
## 1. Doel van de applicatie
De applicatie is een webgebaseerde storage manager voor self-hosted omgevingen, met een veilige browserinterface om bestanden te beheren binnen strikt whitelisted root directories.
Kernwaarde van v1:
- veilige en voorspelbare filesystem-operaties binnen whitelist
- transparant taakmodel voor langlopende copy/move acties
- stabiele API-contracten die met golden tests bewaakt worden
## 2. V1 scope en out-of-scope
In scope voor v1:
- directory browsing binnen whitelist roots
- file-operaties: `rename`, `delete`, `mkdir`
- task-based operaties: `copy`, `move`
- task status/progress polling
- bookmarks CRUD (minimaal: list/create/delete)
- history logging van uitgevoerde operaties
- security path controls: canonicalisatie, traversal-blocking, symlink escape blocking
Out-of-scope voor v1:
- user management en authenticatie/autorisatie
- fijnmazig permissions management
- cloud storage integraties
- distributed/multi-node storage
- geavanceerde job scheduling (prioriteiten, parallel queue tuning, retry policy)
- recycle bin/undo functionaliteit
## 3. Voorgestelde architectuur voor eerste versie
Technische stack:
- Backend: Python + FastAPI
- Frontend: lichte JavaScript UI (zonder zwaar framework)
- Opslag: SQLite voor tasks, bookmarks, history
Architectuur v1 (monolithisch, modulair):
- `API-laag` (FastAPI routes): validatie, response-shaping, HTTP foutcodes
- `Service-laag`: use-case logica (browse, file ops, tasks, bookmarks)
- `Filesystem-laag`: gecapsuleerde filesystem calls
- `Security/path-guard`: centrale pad-resolutie en whitelist enforcement
- `Task-runner`: background worker voor copy/move met persistente status
- `Repository-laag`: SQLite toegang voor tasks/bookmarks/history
Datastroom copy/move:
1. API ontvangt request en valideert payload.
2. `path_guard` valideert source/destination tegen whitelist en security regels.
3. Service maakt task-record aan met status `queued`.
4. Worker pakt task op, zet status op `running`, voert operatie uit, werkt progress bij.
5. Bij afronding: status `completed` of `failed`; resultaat en fouten worden opgeslagen.
## 4. Voorgestelde backend projectstructuur
```text
backend/
app/
main.py
config.py
logging.py
api/
schemas.py
errors.py
routes_browse.py
routes_files.py
routes_tasks.py
routes_bookmarks.py
services/
browse_service.py
file_ops_service.py
task_service.py
bookmark_service.py
history_service.py
security/
path_guard.py
fs/
filesystem_adapter.py
tasks/
worker.py
progress.py
transitions.py
db/
sqlite.py
models.py
migrations/
001_init.sql
repositories/
task_repo.py
bookmark_repo.py
history_repo.py
tests/
unit/
test_path_guard.py
test_task_transitions.py
feature/
test_browse_flow.py
test_file_ops_flow.py
test_task_flow.py
regression/
test_path_traversal_blocked.py
test_unicode_filenames.py
test_large_directory_listing.py
golden/
test_api_browse_golden.py
test_api_errors_golden.py
```
Richtlijnen:
- security checks alleen via `path_guard.py` (geen ad-hoc checks in routes)
- filesystem calls alleen via `filesystem_adapter.py`
- API shapes blijven stabiel en worden bewaakt met golden tests
## 5. Belangrijkste API endpoints voor versie 1
Browse:
- `GET /api/browse?path=<root-relative>`
File-operaties:
- `POST /api/files/rename`
- `POST /api/files/delete`
- `POST /api/files/mkdir`
- `POST /api/files/copy` (task-based)
- `POST /api/files/move` (task-based)
Tasks:
- `GET /api/tasks/{task_id}`
- `GET /api/tasks`
Bookmarks:
- `GET /api/bookmarks`
- `POST /api/bookmarks`
- `DELETE /api/bookmarks/{id}`
## 6. Browse contract (v1 aangescherpt)
Padmodel:
- API accepteert in v1 alleen `root-relative` paden met expliciete root alias.
- Voorstel requestvorm: `GET /api/browse?path=<root>/<subpath>`
- Voorbeelden: `storage1/`, `storage1/series`, `archive/docs/2026`
- Absolute host paths worden niet geaccepteerd in publieke API om ambiguiteit te vermijden.
Succesresponse:
```json
{
"path": "storage1/series",
"directories": [
{
"name": "ShowA",
"path": "storage1/series/ShowA",
"modified": "2026-03-10T12:00:00Z"
}
],
"files": [
{
"name": "episode.mkv",
"path": "storage1/series/episode.mkv",
"size": 734003200,
"modified": "2026-03-10T11:30:00Z"
}
]
}
```
Metadata velden (v1):
- voor directories: `name`, `path`, `modified`
- voor files: `name`, `path`, `size`, `modified`
- `modified` als UTC ISO-8601 string
- geen checksum/mime in v1
Hidden files beleid:
- default: hidden entries (`.`-prefixed) niet tonen.
- optioneel query-flag: `show_hidden=true` voor expliciete opname.
- `.` en `..` worden nooit teruggegeven.
Foutresponses:
- `400` bij ongeldige `path` parameter of malformed input
- `403` bij pad buiten whitelist / security-blokkade
- `404` als pad niet bestaat
- `409` als padtype mismatch (bijv. file i.p.v. directory)
- `500` bij onverwachte I/O fout
## 7. Delete gedrag (veiligheidsuitwerking v1)
Endpoint:
- `POST /api/files/delete`
- request: `{ "path": "<root-relative>", "recursive": false }`
Gedrag files vs directories:
- file delete: direct verwijderen indien pad valide is
- directory delete:
- standaard alleen lege directory (`recursive=false`)
- non-empty directory geeft `409 directory_not_empty`
- recursive delete alleen bij expliciet `recursive=true`
Non-empty directories:
- zonder recursive: blokkeren met heldere foutmelding
- met recursive: toegestaan binnen whitelist, met strikte guard tegen symlink escapes tijdens traversal
Foutafhandeling:
- `404` target bestaat niet
- `403` security/path violations
- `409` directory non-empty zonder recursive of operation conflict
- `500` onverwachte filesystem fout
Bevestigingsaannames:
- backend voert geen interactieve confirm uit
- frontend moet destructive acties bevestigen voordat endpoint wordt aangeroepen
- voorstel frontend: extra bevestigingstekst voor recursive delete
## 8. Task/progress model (concreet v1)
Progress model:
- primaire metriek: bytes (`done_bytes`, `total_bytes`) voor copy/move van files
- secundaire metriek voor directory-operaties: `done_items`, `total_items`
- API retourneert beide waar beschikbaar
Als totaal onbekend is:
- `total_bytes` en/of `total_items` blijven `null`
- client toont indeterminate progress state
- `done_*` kan wel oplopen
Partial failure gedrag:
- v1 policy: fail-fast per task
- eerste fatale fout zet task op `failed`
- reeds verplaatste/gekopieerde items blijven staan (geen rollback in v1)
- response bevat `failed_item` en foutdetails
Eindstatussen v1:
- `completed`
- `failed`
- `queued` en `running` als tussenstatussen
- `canceled` nog niet in v1
## 9. Voorstel SQLite schema (v1)
Tabel `tasks`:
- `id TEXT PRIMARY KEY`
- `operation TEXT NOT NULL` (`copy`/`move`)
- `source_path TEXT NOT NULL`
- `destination_path TEXT NOT NULL`
- `status TEXT NOT NULL` (`queued`/`running`/`completed`/`failed`)
- `done_bytes INTEGER NULL`
- `total_bytes INTEGER NULL`
- `done_items INTEGER NULL`
- `total_items INTEGER NULL`
- `current_item TEXT NULL`
- `error_code TEXT NULL`
- `error_message TEXT NULL`
- `failed_item TEXT NULL`
- `created_at TEXT NOT NULL`
- `started_at TEXT NULL`
- `finished_at TEXT NULL`
Indexen:
- `idx_tasks_status_created_at(status, created_at DESC)`
- `idx_tasks_created_at(created_at DESC)`
Tabel `bookmarks`:
- `id INTEGER PRIMARY KEY AUTOINCREMENT`
- `label TEXT NOT NULL`
- `path TEXT NOT NULL UNIQUE`
- `created_at TEXT NOT NULL`
- `updated_at TEXT NOT NULL`
Tabel `history`:
- `id INTEGER PRIMARY KEY AUTOINCREMENT`
- `operation TEXT NOT NULL`
- `path TEXT NULL`
- `source_path TEXT NULL`
- `destination_path TEXT NULL`
- `status TEXT NOT NULL`
- `task_id TEXT NULL`
- `error_code TEXT NULL`
- `error_message TEXT NULL`
- `created_at TEXT NOT NULL`
Indexen:
- `idx_history_created_at(created_at DESC)`
- `idx_history_operation_created_at(operation, created_at DESC)`
- `idx_history_task_id(task_id)`
## 10. API error model (v1)
Standaard error shape:
```json
{
"error": {
"code": "path_outside_whitelist",
"message": "Requested path is outside allowed roots",
"details": {
"path": "storage1/../../etc"
}
}
}
```
Errorvelden:
- `code`: machine-readable, stabiel voor clientlogica
- `message`: mens-leesbare samenvatting
- `details`: optioneel object met context (geen gevoelige hostpaths)
Voorgestelde error codes:
- security/path:
- `path_outside_whitelist`
- `path_traversal_detected`
- `symlink_escape_detected`
- `invalid_root_alias`
- not found/conflict/validation:
- `path_not_found`
- `already_exists`
- `directory_not_empty`
- `invalid_request`
- `validation_error`
- operationeel:
- `io_error`
- `internal_error`
HTTP mapping:
- `400`: `invalid_request`, `validation_error`
- `403`: security/path errors
- `404`: `path_not_found`, `task_not_found`, `bookmark_not_found`
- `409`: `already_exists`, `directory_not_empty`, type conflicts
- `500`: `io_error`, `internal_error`
## 11. Minimale frontend-notitie voor v1
Hoofdschermen:
- `Browser view`: directory listing + acties (rename/delete/mkdir/copy/move)
- `Tasks view`: lijst met actieve/recente taken en detailstatus
- `Bookmarks`: snelle navigatie naar opgeslagen paden
Task polling:
- bij actieve taken elke 1-2 seconden `GET /api/tasks/{id}` of batch `GET /api/tasks`
- polling stopt automatisch bij eindstatus (`completed`/`failed`)
- UI toont determinate progress bij bekende totalen, anders indeterminate indicator
Foutweergave:
- fouten tonen met `error.message`
- client-logica kan op `error.code` beslissen (bijv. specifieke melding voor `directory_not_empty`)
- destructive acties (delete, vooral recursive) krijgen expliciete confirm-dialog
## 12. Implementatieplan in kleine stappen
1. Backend skeleton opzetten (FastAPI app, routers, config, logging).
2. `path_guard` implementeren met root-alias model en centrale security checks.
3. Unit tests toevoegen voor whitelist/traversal/symlink scenario's.
4. Browse endpoint bouwen volgens aangescherpt contract incl. hidden files beleid.
5. Golden tests toevoegen voor browse success + browse error responses.
6. `rename`, `mkdir`, `delete` implementeren met veilig delete-gedrag (recursive policy).
7. Feature tests toevoegen voor file-operaties incl. non-empty directory fouten.
8. SQLite schema (`tasks`, `bookmarks`, `history`) toevoegen met repositories.
9. Task statusmachine en transitions implementeren + unit tests.
10. Worker voor copy/move implementeren met bytes/items progress.
11. Task endpoints implementeren (`create`, `get`, `list`) met eindstatussen.
12. Feature tests voor copy/move + partial failure gedrag + polling flow.
13. Bookmarks endpoints implementeren + basis tests.
14. Regression tests voor path traversal, unicode, grote/nested directories.
15. Frontend v1 basis flows koppelen (browse, acties, tasks polling, foutweergave).
16. Eindcontrole: volledige test run + golden contract verificatie.
## 13. Governance-notitie
Volgens `CHANGE_POLICY.md` en `SAFE_FILES.md` vallen API-wijzigingen en DB schema-wijzigingen onder "eerst voorstel nodig". Deze aangescherpte `PLAN.md` is het voorstel dat eerst goedgekeurd moet worden. Na expliciete goedkeuring kan implementatie starten.