- data/users.json store; existing single account migrates to first admin
- Roles: admin (settings, import, users) and viewer (read-only, own password)
- Live role/disabled lookup; per-user session epoch so password changes,
resets and disabling sign that user out everywhere
- Login brute-force lockout (5 fails -> 5 min), constant-time unknown-user check
- /api/users CRUD with last-admin and self-lockout safeguards
- Account page (own password + admin user management); role-aware header
- Min password length 8; recovery token resets the primary admin and clears lockouts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Protected /dashboard route with PBKDF2 password + HMAC-signed cookies
- First-run setup flow at /dashboard/setup
- Records Ambient station readings to daily JSONL files in app/data/station/
- Deduplicates on dateutc so 1-min polling never writes duplicate rows
- Dashboard charts: temp, humidity/dew, wind+gusts, wind rose, pressure,
rain rate, rain accumulation, UV, solar radiation
- History range selector: 1h / 6h / 24h / 7d / 30d / 90d / 1y / 2y / 3y
- Auto-downsamples to 720 points for long ranges
- Cron interval changed from 10 min to 1 min (with dedup guard)
- app/data/ added to .gitignore (contains keys and session secret)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>