Commit Graph

10 Commits

Author SHA1 Message Date
null a6c9b6cb1c refactor(server): migrate 8 leaf services + apiError to TypeScript (.cts)
Batch of low-blast-radius modules: utils/apiError, and services statusRuntime,
loginFingerprint, auditService, transactionMatchState, updateCheckService,
advisoryFilterService, bankSyncConfigService.

- types/http.d.ts: shared permissive Express-ish Req/Res/Next/Router types
  (@types/express isn't installed; handlers are dynamic) — for apiError's
  errorHandler now and the routes/middleware batches next.
- Every require of a migrated module updated to the explicit .cts extension.
- Confirmed + documented the Node rule: a .cts needs at least one `import`
  statement or type-stripping never activates (node --check fails on the first
  type token); import-less modules lead with an `import type`.

Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-06 10:47:16 -05:00
null 005b0b7b64 refactor(server): migrate 10 services to TypeScript (.cts)
Continues the incremental server TS migration (after utils/*.mts and
paymentValidation.cts): converts 10 services to .cts (CommonJS TypeScript,
run natively via Node type-stripping — no build step), type-checked by
tsconfig.server.json.

Migrated: totpService, amountSuggestionService, encryptionService,
paymentAccountingService, statusService, aprService, driftService,
analyticsService, spendingService, billMerchantRuleService.

- types/db.d.ts: shared minimal better-sqlite3 Db/Statement types (the lib
  ships none), reused across the migrated modules.
- Every require of a migrated service updated to the explicit .cts extension
  (extensionless require does not resolve .cts) across routes / services /
  db migrations / server.js / workers / tests — require-only changes.
- package.json: check:server find pattern now includes *.cts (it silently
  skipped .cts before, so paymentValidation.cts had no node --check gate).

Behavior-preserving (types only). Verified: typecheck:server 0,
check:server 0, full server suite 226/226, real boot → /api/health 200.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-06 10:35:29 -05:00
null 1f57b22ff8 feat(settings): configurable reminder send-time (plan Tier 5)
The daily reminder job ran at a hardcoded 6 AM. Make the hour configurable:
- dailyWorker: resolveReminderHour() reads the global 'reminder_hour' setting
  (clamp 0–23, default 6) as the single source for both the cron expression and
  the next-run display; the task is stored so rescheduleDailyWorker() can restart
  it live (defensively wrapped so a bad value can't take the worker down).
- notifications admin GET/PUT expose reminder_hour; PUT clamps, persists, and
  live-reschedules the worker.
- Admin Email Notifications card: a "Reminder send time" select (account-wide).

It's a global setting by design — there's one shared daily job, so a per-user
hour would require an hourly-worker refactor (out of scope) and would otherwise
be a dead setting.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-05 16:10:25 -05:00
null 3f9a6cf23e feat(server-ts): utils/dates → TypeScript (.mts); utils/ dir now TS (Phase 2)
dates.mts (ESM, typed) joins money.mts — the two most-required server
leaves are now TypeScript. Added .cts to the server tsconfig for the
CJS-module migration path. typecheck:server clean; suite 225 + probe 17/17.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-05 13:48:44 -05:00
null 38c8bbd472 feat(server): add trust proxy, CSRF HTTPS detection, error formatting, dates util (batch 0.38.0) 2026-06-10 19:37:19 -05:00
null 99abca9868 security: WebAuthn / FIDO2 hardware security key 2FA 2026-06-05 22:05:23 -05:00
null a2266635f4 perf: worker N+1 batching, status runtime DB persistence, 'use strict' 2026-06-04 21:32:28 -05:00
null 1f1c505115 fix: daily worker quarterly and annual bill cycle bugs
- getCycleRange() now called per-bill so quarterly/annual bills are
  checked in their full window, not just the calendar month
- Null-safe guard after buildTrackerRow() prevents TypeError on
  cyclically-inactive bills
2026-06-03 21:55:15 -05:00
null 5182754e0f feat(tracker): price-change drift detection with amber insight panel
Detects when a bill's recent payments have diverged from its configured
expected amount for 2+ consecutive months and surfaces it in a new
collapsible amber panel on the Tracker page.

- Migration v0.71: adds `drift_snoozed_until` to bills and
  `notify_amount_change` to users
- New `driftService.getDriftReport()`: computes per-bill payment median
  over last 3 months, flags drift above a user-configurable threshold
  (default 5%, minimum $1 delta)
- New `GET /api/bills/drift-report` and `POST /api/bills/:id/snooze-drift`
  routes (registered before `/:id` to avoid routing conflict)
- `runDriftNotifications()` added to daily worker — sends amber digest
  email per user listing all changed bills with old → new amounts
- `notify_amount_change` wired through profile and notifications routes
- `DriftInsightPanel`: collapsible amber panel with per-bill
  strikethrough old → new amount, ±% badge, TrendingUp/TrendingDown
  icons, "Update to $X.XX" (with undo toast) and "Dismiss" (30 days)
  actions; teal palette for price decreases
- `drift_threshold_pct` setting added to SettingsPage Billing Behavior
- "Notify on price changes" toggle added to ProfilePage notifications

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-30 14:33:55 -05:00
_null b9d1366d46 initial commit 2026-05-03 19:51:57 -05:00