# ROADMAP Goal: build a small, lightweight, container-based file browser web app that lets an admin mount arbitrary host folders and browse/stream/download their contents through a login-gated web UI, in light and dark themes. ## Priority 1 — Authentication & access control Objective: absolutely no content, file listing, download, or streaming is reachable without an authenticated session. Login is the only unauthenticated page/route (plus static login assets). - Login page (username/password) is the only page reachable while unauthenticated; every other route (file listing, file content, download, stream, admin) requires a valid server-side session. - Server-side session cookie: random session ID, HTTP-only + Secure + SameSite cookie, session record (with expiry, e.g. 7-day sliding window) stored in SQLite. Logout deletes the session server-side. - Passwords hashed with bcrypt (or equivalent), never stored/logged in plaintext. - Seed data on first startup: admin user `boss@zecevic-ninja.com`, password `Start1234!`, flagged `must_change_password = true`. - Any account (seeded admin or created user) with `must_change_password = true` is redirected to a forced "change your password" screen immediately after login and cannot reach any other page (including file browsing) until the password is changed. New password must differ from the temporary/old one and meet a minimum strength rule (documented in the plan). - Two roles: `admin` and `user`. Both roles can browse/download/stream all configured roots (no per-user folder restrictions in this cycle). Only `admin` can access the user-management screens (create user, reset a user's password / force `must_change_password`, delete/disable a user). - App assumes it runs behind a reverse proxy (nginx/Traefik/Caddy) for TLS; the app itself serves plain HTTP inside the container. This assumption and the required reverse-proxy config (incl. passing through HTTP Range headers) must be documented in `README.md`. - Session cookies are `Secure` by default (required for any real/production deployment, per the TLS assumption above). For local development/testing only, an explicit opt-in switch (env var, off by default) may disable the `Secure` cookie attribute so login works over plain `http://` (e.g. `http://localhost:PORT` on a non-loopback-only bind, or a LAN IP). This switch must default to the secure behavior, must be clearly documented as unsafe for anything but local testing, and must not weaken any other auth/session behavior (forced password change, session expiry, HttpOnly, SameSite all remain unchanged). ## Priority 2 — Folder browsing UI Objective: a light, simple, low-dependency UI (server-rendered HTML + minimal vanilla JS, no SPA build pipeline) with light/dark theme, for browsing configured root folders. - Multiple named roots are configurable via a config file / env var read at container startup (each entry: container path + display name). Roots are fixed host-to-container Docker volume mounts; adding/removing a root requires editing the config and restarting the container (a Docker/host constraint, not an app limitation) — this must be documented clearly in `README.md`. - After login, user sees the list of configured roots, can enter subfolders, see breadcrumb navigation, and go back up. All path handling must be strictly confined inside each root (no path traversal outside the mounted root, symlink escapes rejected). - Folder view lists files and subfolders (name, type, size, modified time for files). - Theme: light and dark mode, user-toggleable, minimal/clean styling (no heavy CSS/JS framework). ## Priority 3 — File download & video streaming (no transcoding) Note: video-type detection and `Content-Type` for streaming/download must not depend on the container's OS-level MIME database (e.g. `/etc/mime.types`, `/usr/share/mime/globs2`) — the minimal Alpine runtime image ships none of these, and Go's built-in `mime` fallback table does not include any video extensions. Video extensions (`.mp4`, `.m4v`, `.mov`, `.webm`, `.mkv`, `.avi`, `.mpg`/`.mpeg`, `.wmv`, `.flv`, at minimum) must be recognized and given a correct `Content-Type` via an extension table built into the app itself. `.mkv` (Matroska) must still be downloadable, but in-browser inline streaming of `.mkv` is inherently browser-dependent (most browsers do not support the MKV container for native `