# Roadmap to v0.0.5 (completed)

## Must Fix — Done

- [x] **Log rotation** — `~/.sitedrop/server.log` rotates when it exceeds 5 MB, keeping one `.log.1` backup. Rotation happens at startup and on SIGHUP so operators can trigger it manually.
- [x] **`sitedrop logs` command** — Tail the server log from the CLI. `sitedrop logs` prints the last 20 lines; `sitedrop logs -f` follows in real time.
- [x] **Backup and restore** — `sitedrop backup` creates a `.tar.gz` of all sites and server config. `sitedrop restore <file>` extracts it back with path traversal protection.
- [x] **Config versioning** — `"config_version": 1` field in `server.json`. On load, migrates old configs automatically. Future-version configs log a warning.

## Test Coverage

183 tests passing across 9 test files. Added:
- Config versioning (default, save/load, migration, future version warning)
- Log rotation (large/small/missing files, backup replacement)
- `logs` command (line count, empty file, missing file, custom -n)
- `backup` command (archive creation, no config error, default filename)
- `restore` command (extraction, running server warning, path traversal rejection, invalid archive)
- SIGHUP handler registration

---

# Roadmap to v0.0.4 (completed)

## Must Fix — Done

- [x] **Token revocation on password change** — Rotate the JWT secret in `server.json` whenever the password is changed via `POST /api/password`. Returns a fresh token in the response. All previously issued tokens are instantly invalidated.
- [x] **PID file staleness detection** — Before acting on a PID from `~/.sitedrop/server.pid`, verify the process actually belongs to sitedrop/uvicorn by checking `/proc/{pid}/cmdline` on Linux (falls back to trusting PID on macOS/BSD).
- [x] **HTTPS support** — Pass `--ssl-keyfile` and `--ssl-certfile` options through `sitedrop start` to uvicorn. Paths stored in `server.json` so `restart` preserves them.
- [x] **Upload overwrite protection** — `PUT /api/sites/{name}` with `If-None-Match: *` returns 412 if site exists. Client sends this header by default; `--force` flag omits it. CLI prompts for confirmation on overwrite.

---

# Roadmap to v0.0.3 (completed)

## Must Fix — Done

- [x] **Version bump** — Bumped to `0.0.3` in both `pyproject.toml` and `__init__.py`
- [x] **2 tests fail when run as root** — Switched from chmod-based permission tests to mocking `Path.write_text`
- [x] **Background server logs** — Redirected to `~/.sitedrop/server.log` instead of discarding via `subprocess.PIPE`
- [x] **Graceful shutdown on `stop`** — Polls after SIGTERM for up to 5s, falls back to SIGKILL, cleans up PID file
- [x] **Config crashes on corrupted JSON** — Both `ClientConfig.load()` and `ServerConfig.load()` catch errors and fall back to defaults

## Test Improvements — Done

- [x] Fixed root-user test failures (mock instead of chmod)
- [x] Added tests for background process flow (graceful shutdown, SIGKILL fallback, log redirection)

## Test Coverage

132 tests passing across 9 test files. Added:
- Graceful shutdown (SIGTERM + poll)
- SIGKILL fallback after timeout
- Background start logs to file
- `info` command (not logged in, valid/expired/invalid token)
- Delete confirmation (abort, proceed, `--yes` flag)
- Health check endpoint (200, no auth required)
- Dynamic list columns (long names)
- Server config chmod 600
- CSP header on API responses, absent on served sites
- `restart` command (not running, help)

---

# Roadmap to v0.0.2 (completed)

What needed to happen before cutting the v0.0.2 release.

## Must Fix — Done

- [x] **Unbounded file uploads** — Added 10 MB limit, returns 413
- [x] **UTF-8 decode errors** — Returns 400 with clear message
- [x] **Network error handling in client** — All httpx calls wrapped with timeout (30s) and user-facing error messages via `SitedropError`
- [x] **File I/O errors** — `storage.put()`, `ServerConfig.save()` catch OSError; PID file handles corrupt content gracefully
- [x] **Server URL validation** — Client rejects anything that isn't http:// or https://

## Should Fix — Done

- [x] **Security headers** — `X-Content-Type-Options: nosniff` and `X-Frame-Options: DENY` on all responses
- [x] **Logging** — Python `logging` module, logs auth attempts, uploads, and deletes to stderr
- [x] **Silent server start failures** — `sitedrop start` waits 0.5s and checks if process is still alive before reporting success
- [x] **Site name length limit** — Names over 240 characters are rejected
- [x] **PID file robustness** — Corrupt PID file treated same as missing

## Polish — Done

- [x] **Config path via environment variable** — `SITEDROP_CONFIG` and `SITEDROP_CLIENT_CONFIG` override defaults
- [x] **README gaps** — Added sections for Limits, API Error Codes, Security, Environment Variables, and Troubleshooting
- [x] **Password storage tradeoff documented** — Explained in Security section
- [x] **Rate limiting on auth** — 5 attempts per minute per IP, returns 429

## Test Coverage

103 tests passing. Covers:
- Auth (bcrypt, JWT, expiry, wrong secret)
- Storage (CRUD, name validation, length limits, write errors)
- API routes (all endpoints, auth, errors, size limits, UTF-8, rate limiting, security headers)
- Site serving (HTML, 404, invalid names, updates)
- Client API (login, upload, list, delete, token refresh, network errors, URL validation)
- CLI (all commands, error states, corrupted PID file)
- Config (save/load, env vars, permissions, corruption)
