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>
This commit is contained in:
Gan, Jimmy
2026-05-03 13:31:25 +08:00
parent 5c7d185953
commit ddaf3c6cee
16 changed files with 987 additions and 21 deletions
+82
View File
@@ -0,0 +1,82 @@
# Sprint 01 — Production Stability
**Depends on:** S00 (critical security fixes)
**Duration:** ~6h
**Goal:** Restore dev deployment, add test gates, fix broken UI states and inaccurate system data.
---
## S01.1 — Fix dev deploy runner label
- **Files:** `.gitea/workflows/deploy-dev.yml:15`
- **Estimate:** 0.5h
- **Done means:** `runs-on: nas` instead of `runs-on: ubuntu-latest`. CI deploy to dev succeeds.
- **Verify by:** Push a trivial change to `dev` → workflow runs on `nas` runner → deploy succeeds → `curl http://nas:4001/api/health` returns 200
- **Risk:** None — this is the same runner used by `deploy.yml` and `deploy-claude-dev-dev.yml`.
- [ ] S01.1 — Fix dev deploy runner label
## S01.2 — Add test gate to dev deploy
- **Files:** `.gitea/workflows/deploy-dev.yml`
- **Estimate:** 2h
- **Done means:** `deploy-dev.yml` has backend-tests and frontend-tests jobs that must pass before the deploy job runs (via `needs`). Same test pattern as `deploy.yml`.
- **Verify by:**
1. Push code with failing test → tests fail → deploy job skipped
2. Push code with passing tests → tests pass → deploy proceeds
3. Workflow summary in Gitea UI shows test→deploy dependency clearly
- **Risk:** Adds 2-3 minutes to dev deploy cycle. Acceptable trade-off for safety.
- [ ] S01.2 — Add test gate to dev deploy
## S01.3 — Add error handling to Docker.svelte
- **Files:** `dashboard/frontend/src/routes/Docker.svelte:12-15`
- **Estimate:** 1h
- **Done means:** API errors in `load()` are caught. UI shows error state with message and retry button instead of blank page or crash. Same pattern applied to `action()` and `showLogs()`.
- **Verify by:**
1. Stop docker-socket-proxy → navigate to Docker page → see error message "Docker API unavailable" + retry button
2. Start docker-socket-proxy → click retry → containers load
3. During normal operation → no regression (page works as before)
- **Risk:** Low. Add `let error = $state("")` and an `{#if error}` block in the template. Keep existing `loading` state.
- [ ] S01.3 — Add error handling to Docker.svelte
## S01.4 — Fix cpu_percent always returning 0
- **Files:** `dashboard/backend/routers/system.py:53`
- **Estimate:** 0.5h
- **Done means:** First call to `/api/system/stats` returns accurate CPU percentage (non-zero under load).
- **Verify by:**
1. Restart dashboard backend
2. Run `stress --cpu 1` on the NAS
3. Call `/api/system/stats``cpu_percent` > 0
4. Stop stress → next call shows lower value
- **Risk:** `psutil.cpu_percent(interval=0.1)` blocks the request for 100ms. This is acceptable for a system stats endpoint. Alternative: call `cpu_percent()` once at startup (in lifespan) to prime the counter, then use `interval=0` in the endpoint.
- [ ] S01.4 — Fix cpu_percent always returning 0
## S01.5 — Verify production docker-socket-proxy
- **Files:** `dashboard/docker-compose.yml`
- **Estimate:** 2h
- **Done means:** Production docker-socket-proxy container is running and healthy. Docker API calls from dashboard succeed without timeouts.
- **Verify by:**
1. `ssh nas "cd /volume1/docker/nas-dashboard && docker compose ps"` → docker-socket-proxy shows "Up" and "healthy"
2. Navigate to Docker page in production dashboard → containers load within 5 seconds
3. Monitor `/api/docker/containers` response time → < 2 seconds
- **Risk:** If docker-socket-proxy needs to be created from scratch, ensure the compose file defines it correctly.
- [ ] S01.5 — Verify production docker-socket-proxy
---
## Exit criteria
- [ ] Push to `dev` → CI deploys successfully on `nas` runner
- [ ] Failing test blocks dev deploy
- [ ] Docker page shows error state when API unavailable (not blank/crash)
- [ ] `/api/system/stats` reports non-zero CPU under load
- [ ] Production Docker page loads containers within 5 seconds
- [ ] All backend tests pass
- [ ] All frontend tests pass