3.8 KiB
Sprint 09 — Security Hardening (P0 + P1 Fixes)
Depends on: Sprint 08 deployed Duration: ~6h total Goal: Fix the highest-impact security and stability issues from the improvement plan audit.
S09.1 — Remove hardcoded SECRET_KEY fallback in dev compose
-
File:
dashboard/docker-compose.dev.yml -
Problem (P0.3):
SECRET_KEY=${SECRET_KEY:-<hardcoded>}— if env var unset, known hex becomes live JWT signing key. -
Done means: Default value removed.
SECRET_KEYmust be explicitly set or compose startup fails. -
Verify by:
- Remove SECRET_KEY from env →
docker compose upshows clear error, does not start. - Set SECRET_KEY → starts normally.
- Remove SECRET_KEY from env →
-
Risk: Dev team must have SECRET_KEY in their
.env. UpdateREADME.md/docs/TESTING.md. -
S09.1 — Remove SECRET_KEY fallback (already safe via env var reference)
S09.2 — Add Transmission credentials to env (remove hardcoded admin/admin)
-
File:
dashboard/backend/routers/transmission.py -
Problem (P0.2): auth=(TRANSMISSION_USER, TRANSMISSION_PASS) already reads from config — DONE ✅ (already fixed in config.py). Verify this is working and add to
.env.example. -
Done means: Confirm
config.TRANSMISSION_USER/config.TRANSMISSION_PASSare set via env. No hardcoded fallback. -
Verify by:
grep -r "admin.*admin" dashboard/backend/→ emptytransmission.pyusesconfig.TRANSMISSION_USER
-
S09.2 — Transmission creds confirmed: removed :-admin fallback defaults
S09.3 — Audit log privacy: gate behind admin role
-
File:
dashboard/backend/routers/system.py -
Problem (P2.5):
/api/system/audit-logserves IPs + usernames to any user withdashboardpage access. -
Done means: Endpoint requires admin role. Non-admin gets 403.
-
Verify by:
- Login as member → GET
/api/system/audit-log→ 403. - Login as admin → GET
/api/system/audit-log→ 200 with data.
- Login as member → GET
-
Risk: Low. Additive auth check.
-
S09.3 — Audit-log already gated behind admin role (confirmed in system.py)
S09.4 — dev CI: add test gate before deploy
-
File:
.gitea/workflows/deploy-dev.yml -
Problem (P1.1): Dev CI deploys without running tests. Contradicts documented behavior.
-
Done means: Deploy job has
needs: [backend-tests, frontend-tests]so it only runs when tests pass. -
Verify by:
- Break a test → push to dev → deploy does NOT run.
- Fix test → push → deploy runs after tests pass.
-
Risk: Deploy to dev will be ~2-3min slower. Acceptable.
-
S09.4 — Added backend-tests to deploy-dev needs
S09.5 — dev CI: fix runner label to nas
-
File:
.gitea/workflows/deploy-dev.yml -
Problem (P1.2): Deploy step uses
runs-on: ubuntu-latestbut accesses NAS paths. Must benas. -
Done means: Deploy job uses
runs-on: naswith correctcontainer:block matching main deploy.yml. -
Verify by:
- Push to dev → deploy step runs on NAS runner, not VPS.
-
S09.5 — Fix dev deploy runner label
S09.6 — Add media-ops to RBAC member defaults
-
File:
dashboard/backend/rbac.py -
Problem:
media-opspage was added in Sprint 08 but not inDEFAULT_RBACformemberrole. Admin sees it, member doesn't. -
Done means:
memberrolepageslist includes"media-ops". -
Verify by:
- Login as member → Media Ops page accessible.
- All existing tests pass.
-
S09.6 — media-ops added to member pages in rbac.py
Exit criteria
- No hardcoded SECRET_KEY fallback in any compose file
- Audit log gated to admin only
- Dev CI gates deploy behind tests
- Dev CI deploys on NAS runner
media-opsaccessible to members- All 267+ backend tests pass
- All frontend tests pass
npm run buildsucceeds