Files
nas-tools/specs/sprint-03-config-externalization.md
T
Gan, Jimmy ddaf3c6cee security: Sprint 00 — critical security fixes (OPC WS auth, Transmission creds, SECRET_KEY, passkey rate limit)
- 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>
2026-05-03 13:31:25 +08:00

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 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