Commit Graph

9 Commits

Author SHA1 Message Date
null 80b3bcc17b fix: HIGH+MEDIUM batch — 10 fixes (v0.24.0)
HIGH:
- Admin toggle-paid: removed cross-user admin branch, now requires ownership
- Analytics crash: imported missing standardizeError
- Export data loss: added cycle_type, cycle_day, bill_history_ranges to exports
- Single-user lockout: removed unnecessary sessions join from getSingleModeUser

MEDIUM:
- Password rate limiter: scoped to change-password only, not all profile routes
- Profile session invalidation: fixed req.sessionId → req.cookies[COOKIE_NAME]
- CSRF default: httpOnly now defaults to false (matches SPA double-submit pattern)
- CSRF password routes: removed csrfSkip for password change endpoints
- Notification due-day: calendar day comparison instead of timestamp floor
- Upcoming bills: clamped days to 1-365, default 30 for invalid input

FUTURE.md: marked all 10 items as FIXED, bumped version refs
HISTORY.md: added v0.24.0 entry
2026-05-10 15:25:47 -05:00
null 6b1ef7dcfa fix: notification privacy leak — per-user bills no longer sent to all recipients (v0.23.2)
CRITICAL security fix: In per-user notification mode, the notification runner
was fetching ALL active bills globally and sending each bill's details to
every opted-in recipient regardless of ownership. This meant User A's bill
names, amounts, and due dates could be emailed to User B.

Fix: Added ownership filter in the recipient loop:
  if (allowUserConfig && bill.user_id !== recipient.id) continue;

Also added a defensive guard for bills with no user_id (orphaned bills),
which are now skipped with a console.warn instead of being broadcast.

Global notification mode (single admin recipient) is unaffected.

Security audit: Private_Hudson confirmed the fix is airtight. All other
routes (bills, payments, tracker, analytics, export, calendar, summary,
categories) properly scope data by user_id.

Version bump: 0.23.1 → 0.23.2 (security patch)
2026-05-10 12:34:53 -05:00
null c4a3593241 v0.22.2: Session Token Rotation on Auth Events
- invalidateOtherSessions() in authService.js: deletes all sessions except current
- Password change (auth.js + profile.js) now invalidates all other sessions
- Password change rotates current session ID (sets new cookie)
- New POST /api/auth/logout-all endpoint (deletes all sessions + clears cookie)
- Audit logging for logout.all and password.change
- Added last_password_change_at to auth.js change-password for consistency
- Hudson security audit: 6/6 PASS
2026-05-10 03:55:14 -05:00
null 7503a54f81 v0.20.6: Audit logging for critical operations
- New audit_log table (migration v0.45) with indexes
- logAudit() service with try/catch safety (never crashes app)
- Audit events: login.success, login.failure, logout, password.change, role.change, csrf.failure, profile.update, profile.settings.update
- All events include ip_address and user_agent
- No passwords, tokens, or session IDs logged
- Hudson security audit: 7/7 PASS
2026-05-10 00:03:12 -05:00
null 399882f282 v0.19.4: session token expiry cleanup
- Added cleanupExpiredSessions() in db/database.js
- v0.43 migration: sessions.created_at column
- Startup cleanup + periodic cleanup every 24h (configurable via SESSION_CLEANUP_INTERVAL_MS)
- Per-user expired session cleanup on login and createSession
- Input validation on SESSION_CLEANUP_INTERVAL_MS (rejects 0, negative, >7d)
- Bishop verified all tests pass
- Hudson security audit: 5 PASS, 1 FAIL (interval validation — fixed)
2026-05-09 20:19:46 -05:00
kaspa 4d1709aea3 push 2026-05-09 13:03:36 -05:00
_null 3228332e8c push 2026-05-04 23:34:24 -05:00
_null d1efeece04 push 2026-05-04 20:12:57 -05:00
_null b9d1366d46 initial commit 2026-05-03 19:51:57 -05:00