# Sprint 03 — Configuration Externalization **Depends on:** S02 (auth boundaries must be clear before touching config) **Duration:** ~8h **Goal:** Move hardcoded IPs/URLs/credentials into environment variables, expand .gitignore, add secret scanning to CI. --- ## S03.1 — Centralize frontend hardcoded IPs/URLs - **Files:** `dashboard/frontend/src/components/Sidebar.svelte:30-31,42-58` - **Estimate:** 3h - **Done means:** `LAN_IP`, `TS_IP`, and all subdomain URLs read from `GET /api/config/external-services` rather than hardcoded strings. Config endpoint returns a JSON map of service names to URLs. - **Verify by:** 1. Change `MUSIC_URL` env var on backend → restart → sidebar shows new URL 2. All sidebar links still work 3. Config endpoint returns 200 with expected schema - **Risk:** Config endpoint must be called before sidebar renders. Add loading state; show "unavailable" for external services if endpoint fails. - [ ] S03.1 — Centralize frontend hardcoded IPs/URLs ## S03.2 — Centralize hardcoded domain in email templates - **Files:** `dashboard/backend/services/email_service.py:68,81,110,142` - **Estimate:** 1h - **Done means:** All email template URLs use `config.DASHBOARD_URL` env var (default `https://nas.jimmygan.com`) instead of hardcoded strings. - **Verify by:** 1. Set `DASHBOARD_URL=https://dev.nas.jimmygan.com` → emails contain dev URLs 2. Unset → emails use default `https://nas.jimmygan.com` - **Risk:** Requires adding `DASHBOARD_URL` to config.py and compose files. Low risk. - [ ] S03.2 — Centralize hardcoded domain in email templates ## S03.3 — Document SSH host defaults in config.py - **Files:** `dashboard/backend/config.py:25-39` - **Estimate:** 0.5h - **Done means:** Comment block explains hardcoded SSH defaults are for development only and must be overridden in production. No code changes. - **Verify by:** Read config.py → comment is present and clear. - **Risk:** Doesn't remove hardcoded values — full removal deferred to S06. - [ ] S03.3 — Document SSH host defaults in config.py ## S03.4 — Add TRANSMISSION_URL to config - **Files:** `dashboard/backend/config.py`, `dashboard/backend/routers/transmission.py` - **Estimate:** 1h - **Done means:** Transmission RPC URL is configurable via `TRANSMISSION_URL` env var. Pairs with S00.2 credential fix. - **Verify by:** 1. Set `TRANSMISSION_URL=http://transmission:9091/transmission/rpc` → calls use that URL 2. Unset → uses default `http://host.docker.internal:9091/transmission/rpc` - **Risk:** Low — pairs naturally with S00.2. - [ ] S03.4 — Add TRANSMISSION_URL to config ## S03.5 — Expand root .gitignore - **Files:** `.gitignore` - **Estimate:** 0.5h - **Done means:** Root `.gitignore` covers: `.DS_Store`, `*.pyc`, `__pycache__/`, `venv/`, `.venv/`, `.vscode/`, `.idea/`, `*.log`, `.env.local`, `.env.production`, `*.egg-info/`. - **Verify by:** 1. `touch .DS_Store && git status` → not shown as untracked 2. `touch test.log && git status` → not shown 3. Existing tracked files unaffected - **Risk:** None — standard ignores. - [ ] S03.5 — Expand root .gitignore ## S03.6 — Add gitleaks to CI test workflow - **Files:** `.gitea/workflows/test.yml` - **Estimate:** 2h - **Done means:** `test.yml` includes a `gitleaks detect` step on PRs to `main`. No secrets trigger false positives (or `.gitleaks.toml` excludes known safe patterns). - **Verify by:** 1. Push test commit with `SECRET_KEY=test123` → gitleaks step fails 2. Push normal commit → gitleaks step passes 3. CI run completes in < 30s for gitleaks step - **Risk:** gitleaks may flag existing patterns. Configure `.gitleaks.toml` to whitelist CI test keys and `.env.example` placeholders. If gitleaks binary unavailable on Gitea runner, use Docker image `zricethezav/gitleaks:latest`. - [ ] S03.6 — Add gitleaks to CI test workflow --- ## Exit criteria - [ ] Sidebar external service URLs come from config endpoint (no hardcoded IPs/domains) - [ ] Email templates use configurable `DASHBOARD_URL` - [ ] config.py has comment documenting SSH defaults - [ ] Transmission URL is configurable via env var - [ ] `.DS_Store` and `*.log` not shown in `git status` - [ ] `gitleaks detect` runs in CI on PRs to main - [ ] All backend tests pass - [ ] All frontend tests pass