6.4 KiB
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, passwordStart1234!, flaggedmust_change_password = true. - Any account (seeded admin or created user) with
must_change_password = trueis 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:
adminanduser. Both roles can browse/download/stream all configured roots (no per-user folder restrictions in this cycle). Onlyadmincan access the user-management screens (create user, reset a user's password / forcemust_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
Secureby 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 theSecurecookie attribute so login works over plainhttp://(e.g.http://localhost:PORTon 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 <video> playback regardless of Content-Type) —
this limitation must be documented, not silently promised.
Objective: allow downloading any file and streaming video files directly, with zero server-side transcoding/encoding (server is slow), by serving raw bytes with HTTP Range support.
- Download endpoint streams the raw file bytes as-is with correct
Content-Type/Content-Disposition. - Video files are served with full HTTP
Rangerequest support (seek, partial content, resumable) so the browser's native<video>player can stream/seek without any server-side re-encoding. - No media processing (no thumbnailing, no transcoding, no format conversion) is performed anywhere in this cycle.
Priority 4 — Admin: user management
Objective: admin can manage user accounts from the web UI.
- Admin-only screens: list users, create user (sets a temporary password,
must_change_password = true), reset a user's password, disable/delete a user. - User management routes are protected the same way as everything else: unauthenticated access is impossible, and non-admin authenticated users get a 403, not a redirect that leaks existence of the page.
Cross-cutting
- Tech stack: Go backend (per
AGENTS.mdvalidation commands), SQLite for users/sessions, server-rendered HTML templates + minimal vanilla JS frontend, single Docker container image. - Documentation:
README.mdmust cover container build/run, volume mount- root config format, first-login/admin credential flow, forced password change, and the reverse-proxy/TLS + Range-header-passthrough requirement. Documentation updates are in-scope for every task that touches these behaviors, not a follow-up.
Open questions for later cycles (explicitly out of scope for now)
- Per-user/per-root permission restrictions (currently: all authenticated users see all roots).
- File upload, rename, delete, or any write operations from the UI (currently: read-only browsing/download/streaming).
- Search across folders.