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

11 KiB

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

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:

{
  "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:

{
  "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.