- Add JWT token auth to OPC WebSocket (unauthenticated → 403, per-user tracking) - Externalize Transmission RPC credentials to TRANSMISSION_USER/PASS env vars - Remove hardcoded SECRET_KEY fallback from dev compose - Rate-limit passkey register options endpoint at 5/minute - Add PDD (docs/improvement-plan.md) and sprint specs (specs/) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4.2 KiB
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 fromGET /api/config/external-servicesrather than hardcoded strings. Config endpoint returns a JSON map of service names to URLs. -
Verify by:
- Change
MUSIC_URLenv var on backend → restart → sidebar shows new URL - All sidebar links still work
- Config endpoint returns 200 with expected schema
- Change
-
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_URLenv var (defaulthttps://nas.jimmygan.com) instead of hardcoded strings. -
Verify by:
- Set
DASHBOARD_URL=https://dev.nas.jimmygan.com→ emails contain dev URLs - Unset → emails use default
https://nas.jimmygan.com
- Set
-
Risk: Requires adding
DASHBOARD_URLto 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_URLenv var. Pairs with S00.2 credential fix. -
Verify by:
- Set
TRANSMISSION_URL=http://transmission:9091/transmission/rpc→ calls use that URL - Unset → uses default
http://host.docker.internal:9091/transmission/rpc
- Set
-
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
.gitignorecovers:.DS_Store,*.pyc,__pycache__/,venv/,.venv/,.vscode/,.idea/,*.log,.env.local,.env.production,*.egg-info/. -
Verify by:
touch .DS_Store && git status→ not shown as untrackedtouch test.log && git status→ not shown- 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.ymlincludes agitleaks detectstep on PRs tomain. No secrets trigger false positives (or.gitleaks.tomlexcludes known safe patterns). -
Verify by:
- Push test commit with
SECRET_KEY=test123→ gitleaks step fails - Push normal commit → gitleaks step passes
- CI run completes in < 30s for gitleaks step
- Push test commit with
-
Risk: gitleaks may flag existing patterns. Configure
.gitleaks.tomlto whitelist CI test keys and.env.exampleplaceholders. If gitleaks binary unavailable on Gitea runner, use Docker imagezricethezav/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_Storeand*.lognot shown ingit statusgitleaks detectruns in CI on PRs to main- All backend tests pass
- All frontend tests pass