## Summary
Merges the `develop` branch into `main`, delivering the "Recently Completed" feature (#6) plus several UI and infrastructure improvements.
## Changes
### Feature: Recently Completed History
- New [`GET /api/history/recent`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/server/routes/history.js) endpoint — returns Sonarr/Radarr history filtered to the last N days, scoped to the authenticated user's tag
- New [`historyFetcher`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/server/utils/historyFetcher.js) utility — dedicated fetcher with 5-minute cache, event classification (`imported`/`failed`), and multi-instance support
-`RECENT_COMPLETED_DAYS` env var (default 7, max 90), overridable per-request via `?days=N`- Admin `?showAll=true` returns all tagged items with per-tag Emby user classification (matched/unmatched badges) — consistent with active downloads behaviour
- Failed imports surfaced with distinct styling; `failureMessage` exposed to admins only
### UI: Tab layout
- Active Downloads and Recently Completed split into two tabs
- Tab selection persisted in `localStorage`- History loads lazily on first tab activation; background refresh continues regardless of active tab
- Show All toggle reloads both tabs immediately
### Design: Light theme refresh
- Replaced purple/violet background with a clean off-white/blue-grey page background derived from the logo palette
- Accent, series, and interactive colours aligned to the teal/steel blue tones in the logo
- All text/background combinations verified WCAG AA compliant (≥ 4.5:1); previously failing colours (`--text-muted`, `--footer-text`, unmatched tag) corrected
- Dark and Mono themes unchanged
### Infrastructure & quality
- Unit and integration tests added for the history endpoint and fetcher — 141 tests passing ([`tests/unit/historyFetcher.test.js`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/tests/unit/historyFetcher.test.js), [`tests/integration/history.test.js`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/tests/integration/history.test.js))
- [ARCHITECTURE.md](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/docs/ARCHITECTURE.md) updated: directory structure, route table, cache keys, env vars, API reference, component diagram; Mermaid diagrams replace ASCII art
- [`README.md`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/README.md) updated with feature description and `RECENT_COMPLETED_DAYS` config entry
- Legacy `.env.example` removed (superseded by [.env.sample](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/.env.sample)
## Closes
Closes #6
```markdown
## Summary
Merges the `develop` branch into `main`, delivering the "Recently Completed" feature (#6) plus several UI and infrastructure improvements.
## Changes
### Feature: Recently Completed History
- New [`GET /api/history/recent`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/server/routes/history.js) endpoint — returns Sonarr/Radarr history filtered to the last N days, scoped to the authenticated user's tag
- New [`historyFetcher`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/server/utils/historyFetcher.js) utility — dedicated fetcher with 5-minute cache, event classification (`imported`/`failed`), and multi-instance support
- `RECENT_COMPLETED_DAYS` env var (default 7, max 90), overridable per-request via `?days=N`
- Admin `?showAll=true` returns all tagged items with per-tag Emby user classification (matched/unmatched badges) — consistent with active downloads behaviour
- Failed imports surfaced with distinct styling; `failureMessage` exposed to admins only
### UI: Tab layout
- Active Downloads and Recently Completed split into two tabs
- Tab selection persisted in `localStorage`
- History loads lazily on first tab activation; background refresh continues regardless of active tab
- Show All toggle reloads both tabs immediately
### Design: Light theme refresh
- Replaced purple/violet background with a clean off-white/blue-grey page background derived from the logo palette
- Accent, series, and interactive colours aligned to the teal/steel blue tones in the logo
- All text/background combinations verified WCAG AA compliant (≥ 4.5:1); previously failing colours (`--text-muted`, `--footer-text`, unmatched tag) corrected
- Dark and Mono themes unchanged
### Infrastructure & quality
- Unit and integration tests added for the history endpoint and fetcher — 141 tests passing ([`tests/unit/historyFetcher.test.js`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/tests/unit/historyFetcher.test.js), [`tests/integration/history.test.js`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/tests/integration/history.test.js))
- [ARCHITECTURE.md](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/docs/ARCHITECTURE.md) updated: directory structure, route table, cache keys, env vars, API reference, component diagram; Mermaid diagrams replace ASCII art
- [`README.md`](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/README.md) updated with feature description and `RECENT_COMPLETED_DAYS` config entry
- Legacy `.env.example` removed (superseded by [.env.sample](https://git.i3omb.com/Gandalf/sofarr/src/branch/develop/.env.sample)
## Closes
Closes #6
```
par keyword is not supported in the PlantUML version on the Gitea runner.
Replace with a group block (universally supported) and a spanning note
to convey the parallelism.
server/index.js:
- Import http and https modules
- Resolve TLS_ENABLED early (before Helmet) so upgradeInsecureRequests
CSP directive fires when TLS is active directly (not only via proxy)
- loadTlsCredentials() reads TLS_CERT/TLS_KEY (defaulting to bundled
snakeoil) and returns null on failure (graceful HTTP fallback)
- Start https.createServer or http.createServer depending on credentials
- Startup banner now shows protocol, TLS cert path, and snakeoil warning
certs/:
- Add bundled snakeoil self-signed certificate (RSA 2048, 10yr, SAN for
localhost + 127.0.0.1) for out-of-the-box HTTPS without configuration
- .gitignore allows only snakeoil.{crt,key} — real certs must not be
committed
Dockerfile:
- COPY certs/ into image so snakeoil default is always available
- HEALTHCHECK updated to https:// with --no-check-certificate
docker-compose.yaml:
- Port now exposes HTTPS directly by default
- TLS_CERT/TLS_KEY/TLS_ENABLED/TRUST_PROXY documented with Option A/B
- cert volume mount examples added (commented out)
- healthcheck updated to https with --no-check-certificate
.env.sample:
- New TLS/HTTPS section with TLS_ENABLED, TLS_CERT, TLS_KEY
- openssl self-signed cert generation example included
docs/ARCHITECTURE.md:
- Configuration table: TLS_ENABLED, TLS_CERT, TLS_KEY env vars added
- Docker image section: TLS default behaviour documented
- Docker Compose example: Option A (direct TLS) / Option B (proxy) layout
- Security checklist: HTTPS now first item, updated for TLS modes
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
server/index.js: - Import http and https modules - Resolve TLS_ENABLED early (before Helmet) so upgradeInsecureRequests CSP directive fires when TLS is active directly (not only via proxy) - loadTlsCredentials() reads TLS_CERT/TLS_KEY (defaulting to bundled snakeoil) and returns null on failure (graceful HTTP fallback) - Start https.createServer or http.createServer depending on credentials - Startup banner now shows protocol, TLS cert path, and snakeoil warning certs/: - Add bundled snakeoil self-signed certificate (RSA 2048, 10yr, SAN for localhost + 127.0.0.1) for out-of-the-box HTTPS without configuration - .gitignore allows only snakeoil.{crt,key} — real certs must not be committed Dockerfile: - COPY certs/ into image so snakeoil default is always available - HEALTHCHECK updated to https:// with --no-check-certificate docker-compose.yaml: - Port now exposes HTTPS directly by default - TLS_CERT/TLS_KEY/TLS_ENABLED/TRUST_PROXY documented with Option A/B - cert volume mount examples added (commented out) - healthcheck updated to https with --no-check-certificate .env.sample: - New TLS/HTTPS section with TLS_ENABLED, TLS_CERT, TLS_KEY - openssl self-signed cert generation example included docs/ARCHITECTURE.md: - Configuration table: TLS_ENABLED, TLS_CERT, TLS_KEY env vars added - Docker image section: TLS default behaviour documented - Docker Compose example: Option A (direct TLS) / Option B (proxy) layout - Security checklist: HTTPS now first item, updated for TLS modes