Commit Graph

73 Commits

Author SHA1 Message Date
null 5eed5932b4 feat: replace native confirm() with shadcn/ui AlertDialog (v0.23.3)
- TrackerPage: confirm('Mark as paid?') → AlertDialog with dynamic bill name
- DataPage: window.confirm('Import SQLite?') → AlertDialog for import confirmation
- Both dialogs use proper shadcn/ui components (AlertDialogAction/Cancel)
- Theme-aware, accessible, consistent with app design system
- STRUCTURE.md: corrected tech stack (Vite+React, not Next.js)
- Version bumped to 0.23.3
2026-05-10 14:36:59 -05:00
null 7c3cfd1715 docs: update README.md, ERM, FUTURE.md, HISTORY.md
README.md updates:
- Added billing cycles (weekly/biweekly/quarterly/annual), history ranges,
  monthly income/starting amounts, migration rollback, audit logging,
  auth-mode/OIDC config, CSRF protection details
- Added INIT_REGULAR_USER/PASS and SESSION_CLEANUP_INTERVAL_MS env vars
- Added CSRF env vars (CSRF_HTTP_ONLY, CSRF_SAME_SITE, CSRF_SECURE,
  CSRF_COOKIE_NAME)
- Noted export limitation: cycle_type, cycle_day, history_ranges omitted
- Fixed: CSP is now implemented with per-request nonces (was 'deferred')
- Added: default admin restricted from tracker routes, session rotation
  on password change, audit logging
- Cleaned up demo server formatting, project structure listing, scripts
- Removed authLogin.js from project structure (file was deleted in v0.23.2)

Engineering_Reference_Manual.md:
- Removed stale authLogin.js duplicate route note (file no longer exists)
- Removed 401/403 error detail from login endpoint (simplified)
- Updated version to 0.23.2

FUTURE.md:
- Marked notification privacy leak (CRITICAL) as FIXED v0.23.2
- Marked duplicate login route (LOW) as FIXED v0.23.2
- Updated current version to v0.23.2

HISTORY.md:
- Added v0.23.2 entry with security fix and route consolidation details
2026-05-10 12:42:45 -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 78f95f784e fix: remove duplicate login route (authLogin.js), consolidate into auth.js
- Deleted routes/authLogin.js (orphaned duplicate login handler)
- Removed authLoginRouter import and mount from server.js
- Rate limiter now runs as standalone middleware on /api/auth/login
- Added try/catch to auth.js login handler (was only in deleted file)
- Consistent audit log variable naming (username vs req.body.username)
- No functionality change — login flow works identically
2026-05-10 12:20:50 -05:00
null 24bac8e506 docs: refresh engineering reference manual 2026-05-10 11:49:05 -05:00
null 52db06001f v0.23.1: migration rollback capability
- Add rollbackMigration() function in db/database.js with transaction safety
- Add POST /api/admin/migrations/rollback endpoint (admin-only)
- Rollback SQL for v0.44 (indexes), v0.45 (audit_log table), v0.46 (cycle columns)
- Error codes: NOT_APPLIED (404), ROLLBACK_NOT_SUPPORTED (422)
- Audit logging for rollback events
- Fix duplicate migrationStartTime declaration from v0.23.0 commit
- Fix broken migration completion audit log from v0.23.0 commit
- Fix DB path exposure (uses path.basename() now)
2026-05-10 10:44:39 -05:00
null 53783aaec5 v0.23.0: Detailed migration logging with timing, error context, and audit logging
- Added [migration] logging for each migration step (applying, completed, timing)
- Added [migration-error] logging with elapsed time on failures
- Added [migration] All migrations completed in Xms total timing
- Added lazy getLogAudit() for audit logging of migration failures (avoids circular dep)
- Changed DB path log to basename only (Hudson rec: reduce info disclosure)
- Version bumped to 0.23.0
2026-05-10 09:45:39 -05:00
null ee960c5c5a fix: remove circular dependency in database.js audit logging
- Remove logAudit import and call from db/database.js (circular dep with auditService)
- database.js init code uses console.log instead
- logAudit remains in setup/firstRun.js and server.js (safe, no circular dep)
2026-05-10 04:28:34 -05:00
null eb86da1e69 v0.22.3: fix ENV-seeded users skip first-login flow, add audit logging
- setup/firstRun.js: reset first_login=0, must_change_password=0 on update
- server.js: reset flags for existing regular users + add logAudit
- db/database.js: fix must_change_password=0 in init code (was 1)
- Add logAudit calls for seed.flag_reset events
- database.js uses console.log for init-time resets (avoids circular dep)
- Hudson audit: 6/6 PASS after audit logging fix
2026-05-10 04:24:51 -05:00
null 9647275854 docs: add HISTORY.md for v0.22.2 2026-05-10 03:57:31 -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 65849fc554 v0.22.1: N+1 Query Optimization
- Batch queries replace per-bill loops in tracker and analytics
- monthly_bill_state, payments, prev month payments batched with WHERE IN
- Empty billIds guards prevent SQL errors
- Hudson security audit: 5/5 PASS (SQL injection, empty IN, user scoping, data leakage, type safety)
2026-05-10 03:29:09 -05:00
null 5c35b20c00 docs: update HISTORY, FUTURE, DEVELOPMENT_LOG for v0.22.0 2026-05-10 03:14:40 -05:00
null d67fe6e61d v0.22.0: React Query Migration
- Added @tanstack/react-query and @tanstack/react-query-devtools
- Created useTracker, useBills, useCategories custom hooks (useQueries.js)
- Migrated TrackerPage from manual useState/useEffect to useQuery
- Added QueryClientProvider with 2min staleTime, 1 retry, refetchOnWindowFocus: false
- Added ReactQueryDevtools for development
- Fixed error handling: useRef pattern prevents duplicate toast notifications
- Replaced load() callback with refetch() from useQuery
- Hudson security audit: 4/5 PASS (1 FAIL fixed: error handling toast duplication)
2026-05-10 03:10:43 -05:00
null 314159d241 v0.21.1: Loading Skeletons & Async State
- Reusable Skeleton component (line, circle, card, button, input variants)
- TrackerPage: skeleton cards, rows, buckets with aria-busy attributes
- BillsPage: skeleton rows during loading
- Bug fix: double closing brace />}} on Bucket component
- Hudson security audit: 5/5 PASS
2026-05-10 01:35:41 -05:00
null ac4b4653a5 docs: update DEVELOPMENT_LOG for v0.21.0 pipeline completion 2026-05-10 01:24:47 -05:00
null cfb074c7cd v0.21.0: 3-Month Trend Indicator on Tracker
- Backend: 3-month payment aggregation with year-wrapping, trend object in API (direction, percent_change, 3_month_avg)
- Frontend: TrendIndicator component (arrow + percentage + label), TrendCard with purple gradient
- Bug fix: Bishop fixed 3-month query to JOIN through bills for user scoping (payments table has no user_id)
- Bug fix: Ripley removed duplicate TrendIndicator function definition
- Hudson security audit: 5/5 PASS (SQL injection, user scoping, date wrapping, division by zero, XSS)
2026-05-10 01:22:51 -05:00
null 38394a8bcd docs: update DEVELOPMENT_LOG for v0.20.9 pipeline completion 2026-05-10 00:54:19 -05:00
null 4990bf47f6 v0.20.9: Previous Month Paid column on Tracker
- Backend: previous month calculation with year wrapping (Jan→Dec)
- Backend: previous_month_paid per bill row, previous_month_total in summary
- Frontend: 'Last Month' column in desktop table with muted text
- Frontend: 'Last Month' in mobile view, summary card for prev month total
- Hudson security audit: 5/5 PASS (SQL injection, date wrapping, user scoping, auth, XSS)
2026-05-10 00:52:23 -05:00
null 08975582f2 docs: update DEVELOPMENT_LOG for v0.20.8 completion 2026-05-10 00:41:08 -05:00
null bd796d61c0 v0.20.8: Billing cycle sub-categories + server-side cycle_day validation
- Migration v0.46: cycle_type (monthly/weekly/biweekly/quarterly/annual) and cycle_day columns
- Server-side validation: cycle_type whitelist, cycle_day validated per type
  - monthly: 1-31 integer
  - weekly/biweekly: day name enum
  - quarterly/annual: free text (max 50 chars)
- BillModal UI: conditional cycle_day selector (ordinal/weekday/text)
- Hudson audit: 4/5 PASS, fixed medium-risk cycle_day validation gap
2026-05-10 00:39:11 -05:00
null 5f8c366c70 docs: update DEVELOPMENT_LOG for v0.20.7 pipeline completion 2026-05-10 00:19:13 -05:00
null e184fed88a v0.20.7: Keyboard navigation and ARIA accessibility
- Skip-to-content link for keyboard users (sr-only/focus:not-sr-only pattern)
- aria-expanded and aria-haspopup on Tracker menu dropdown
- aria-label on footer, role='main' and aria-labelledby on layout wrapper
- Main content wrapped in <main> with unique id from React useId()
- Fixed build error: useId imported from react, not react-router-dom
- Hudson security audit: 5/5 PASS (no XSS, no DOM clobbering, no injection)
2026-05-10 00:18:36 -05:00
null 39f3577f04 docs: update DEVELOPMENT_LOG for v0.20.6 pipeline completion 2026-05-10 00:03:50 -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 4f1eec36f5 docs: update DEVELOPMENT_LOG for v0.20.5 pipeline completion 2026-05-09 23:42:19 -05:00
null 8e7f977fef v0.20.5: Bulk payment input validation
- Request body must contain `payments` array (breaking change from raw array)
- Max 50 items per bulk request
- Per-item validation: bill_id (integer regex + parseInt), paid_date (YYYY-MM-DD), amount (finite number >= 0)
- Duplicate detection using bill_id + paid_date + amount composite key — skipped, not rejected
- Response format: { created, skipped, errors }
- Security fix: bill_id type coercion attack (parseInt('1abc') bypass) blocked via regex check
- Security fix: Infinity amount bypass blocked via isFinite() check
- Hudson audit: 5/7 PASS, 2 FAIL fixed (type coercion + Infinity)
2026-05-09 23:41:28 -05:00
null 565b837196 docs: update DEVELOPMENT_LOG, FUTURE.md, HISTORY.md for v0.20.4 2026-05-09 23:25:43 -05:00
null 35e09430c9 v0.20.4: Explicit migration dependency management
- Added dependsOn field to all 17 versioned migrations
- Added validateMigrationDependencies() function for dependency validation
- Migrations with unmet dependencies are skipped with error log (no crash)
- Dependency satisfaction logged: [migration] vX depends on [vY] — satisfied
- appliedVersions Set tracks newly applied migrations for subsequent checks
- Hudson security audit: 7/7 PASS
2026-05-09 23:24:51 -05:00
null 38937c4d2d docs: update DEVELOPMENT_LOG.md with Hudson audit results for v0.20.3 2026-05-09 22:45:11 -05:00
null 1fd4f49758 v0.20.3: Performance indexes on frequently queried columns
- Added v0.44 migration with 4 indexes:
  - idx_bills_user_name ON bills(user_id, name)
  - idx_payments_method ON payments(method)
  - idx_monthly_starting_amounts_user ON monthly_starting_amounts(user_id)
  - idx_import_history_imported_at ON import_history(imported_at)
- Fixed nested transaction bug in migration run() function
- Hudson security audit: 7/7 PASS
2026-05-09 22:44:38 -05:00
null 60bae8163b docs: update FUTURE.md, HISTORY.md, DEVELOPMENT_LOG.md for v0.20.2 2026-05-09 22:35:58 -05:00
null d34316844e v0.20.2: Transaction wrapping for database migrations
- All migrations (versioned, legacy, unversioned) now run within
  BEGIN/COMMIT with ROLLBACK on failure
- v0.40 migration uses try/finally to guarantee PRAGMA foreign_keys
  is always re-enabled, even on error paths
- Clear transaction boundary logging (BEGIN/COMMIT/ROLLBACK)
- Hudson security audit: 6/7 PASS, FK fix applied for v0.40 edge case
2026-05-09 22:34:50 -05:00
null 04a0ecbb80 fix: correct dev log version from 0.21.0 to 0.20.1 2026-05-09 22:09:59 -05:00
null 5c0ff4277f docs: v0.20.1 changelog 2026-05-09 22:01:40 -05:00
null 0cd8423a19 v0.20.1: code splitting, version badge on roadmap, roadmap nav link
- React.lazy + Suspense for all page components (except LoginPage)
- PageLoader component for loading states
- Version badge on admin roadmap page
- Version in /api/about-admin response
- Roadmap nav link for admins (dropdown + sidebar)
- /admin/roadmap route
2026-05-09 22:01:19 -05:00
null d8888af845 feat: add Roadmap nav link for admins
- Added Roadmap link in dropdown menu (below About), admin-only
- Added Roadmap in admin sidebar nav
- Added /admin/roadmap route pointing to AboutPage with admin prop
- Uses Map icon from lucide-react
2026-05-09 21:26:39 -05:00
null 852da29b4d v0.20.0: admin dashboard with roadmap and activity log
- New AdminDashboard component with Roadmap and Activity Log
- Color-coded priority cards (🔴🟠🟡🔵💭) with collapsible sections
- CRITICAL/HIGH expanded by default, others collapsed
- Activity log shows DEVELOPMENT_LOG entries in reverse chronological order
- Admin-only rendering, non-admins see standard About page
- Custom scrollbar styles for admin panels
- Version bumped to 0.20.0 (Bishop)
2026-05-09 21:14:21 -05:00
null c04d3ba27e v0.19.4: bump version to 0.19.4 in package.json and login screen 2026-05-09 20:25:05 -05:00
null 3a1d6133f6 docs: v0.19.4 changelog, remove completed session cleanup from FUTURE.md 2026-05-09 20:21:22 -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
null c7b92f757b v0.19.3: update DEVELOPMENT_LOG 2026-05-09 19:47:54 -05:00
null 9f9c3a2080 v0.19.3: update HISTORY.md and FUTURE.md 2026-05-09 19:47:30 -05:00
null d55827d497 v0.19.3: legacy DB login fix, migration run functions, security hardening
- Reset default admin password when INIT_ADMIN_PASS is set on legacy DBs
- Added run() functions to all legacy migration entries (reconcileLegacyMigrations)
- Migrations that aren't present in legacy DB now actually execute
- v0.40 ownership migration assigns to first admin (not first user)
- Removed username from password reset log (info disclosure fix)
- must_change_password enforced after legacy password reset
2026-05-09 19:47:00 -05:00
null 9d257d9d5e v0.19.2: update version to 0.19.2 in version.js and package.json 2026-05-09 18:52:00 -05:00
null 4e91bed343 v0.19.2: add React Error Boundaries for crash recovery
Added ErrorBoundary component wrapping all routes in App.jsx.
Shows friendly fallback UI with Try Again and Reload buttons
instead of white screen crash. Logs component stack to console.
2026-05-09 18:33:02 -05:00
null a9cdf846fe v0.19.2: fix legacy DB migration login failure + security hardening
CRITICAL fix: Users upgrading from pre-migration-tracking databases
(now get 'invalid username/password' because schema_migrations table
doesn't exist. Added handleLegacyDatabase() and
reconcileLegacyMigrations() to detect and reconcile legacy DBs.

Security fixes:
- Path traversal: replaced sanitizePath() with ALLOWED_FILES allowlist
- Public /about bypass: added admin route guard in App.jsx
- Sensitive info exposure: expanded redactSensitiveContent() patterns
- Error message path leaks: generic error messages only
- Race condition: wrapped in db.transaction() in server.js
- Password validation: INIT_REGULAR_PASS min 8 chars with process.exit(1)

All verified by Bishop (build + runtime) and Private_Hudson (security).
2026-05-09 18:25:25 -05:00
null cf2ed37c1e feat: add INIT_REGULAR_USER env var, move bill_history_ranges to v0.42 migration
- Add INIT_REGULAR_USER/INIT_REGULAR_PASS for non-admin test user creation
- Regular user created at startup with role='user', not admin
- Move bill_history_ranges from inline to versioned migration v0.42
- Clean up FUTURE.md: remove completed items, add skip-first-login item
2026-05-09 16:38:28 -05:00
null 6c7d481494 feat: add admin about page with security hardening
- Add /api/about-admin endpoint (admin-only, path traversal protection, content redaction, error sanitization)
- Add /admin/about route with RequireAuth admin guard
- Add adminActionLimiter rate limiting on about-admin endpoint
- Add rehype-sanitize XSS prevention in AboutPage.jsx
- Add aboutAdmin API client endpoint
- Create HISTORY.md with version bump convention (patch/minor/major)
- Update Engineering Reference Manual with about-admin docs and security measures
- Add INIT_REGULAR_USER/INIT_REGULAR_PASS env vars to docs
- Update FUTURE.md with critical regular user env var item
2026-05-09 16:25:12 -05:00
null 6c730635ec docs: add bill_history_ranges cleanup to FUTURE.md 2026-05-09 15:20:17 -05:00