Skip to content

Handoff: Finances native rebuild, Phase A complete (2026-07-05)

Plan: finances-native-rebuild-2026-07-05 (approved, full native rebuild) Branch: feat/finances-native in /home/justinwieb/forge-suite-wt/feat/finances-native (worktree; node_modules symlinked to forge-suite) Dev DB: ct_finances_native (clone of creatortrack_dev_base; both have the 3 new migrations applied)

Done (Tasks 1-10, one commit each)

  1. Module boundary: docs/FINANCES-APP-SPEC.md + eslint no-restricted-imports regex rules both directions; module lint debt cleared.
  2. finance.job_runs + finance.alert_state migration.
  3. lib/finance-simplefin.ts (28 accounts live).
  4. app/api/finance/jobs/[job] runner, bearer FINANCE_JOBS_TOKEN (appended to ~/.forge-secrets/creatortrack-auth.env), owner identity via core.login, run log in job_runs, fail-loud notify.
  5. lib/finance-jobs/sync.ts: idempotent (verified run1 26 new / run2 0), cross-source reconcile ported, zero-balances now FAILS the run.
  6. lib/finance-jobs/categorize.ts + finance.user_rules (410 rules seeded on clone; JSON import at cutover): 8812/8812 parity with the Python engine.
  7. lib/finance-jobs/recurring.ts: 90 total matches SQLite; user-curated rows survive.
  8. lib/finance-jobs/holdings.ts: live Yahoo pricing 17/17, SSGA xlsx via new fflate dep, Vanguard JSON, 6 funds refreshed.
  9. lib/finance-jobs/alerts.ts + finance.alert_feed migration: 8 real alerts on clone, dedup verified.
  10. lib/finance-jobs/snapshot.ts (55 accounts, idempotent) + lib/finance-jobs/receipts.ts (+ erpnextList/erpnextUploadFile in lib/erpnext; attach path unexercised, zero receipts exist).

Also fixed this session (prod)

  • finance.* PG mirror was frozen since 07-03: workspace re-slug broke forge_finance_migrate_to_lifeos.py (default slug now justin). Mirror reloaded, current.

Discovered dependencies / notes

  • Task 16.5 added to plan: forge_erpnext_daily_post.py reads finance.db and stamps FINDB-<sqlite id>; must repoint to PG before SQLite retires. Old ids preserved in legacy_findb_id.
  • PNC Bank needs re-auth at bridge.simplefin.org (live SimpleFIN warning on every sync).
  • Testing pattern: PGDATABASE=ct_finances_native npx tsx <script>.mts from the worktree; server-only imports need lazy import or fail under tsx.
  • Drizzle sql expands arrays as tuples: use in ${arr}, never = any(${arr}).

Phase B also complete (same session, Tasks 11-15)

  1. /api/finance/transactions: per-txn + bulk edit (first txn write surface in CreatorTrack; sticky user_category verified against the categorize job).
  2. recurring/action + categorize/apply routes rewritten native (python helpers + JSON sidecars retired; flag = review_flagged; rules upsert finance.user_rules).
  3. /api/finance/budgets (FLEX_KEY-aware upsert), /api/finance/manual-values (append-only), Sync button runs the native pipeline via after().
  4. Icon subsystem native: lib/finance-icons.ts (iconKey = recurring norm-key ALWAYS, localize-to-/finance-icon, Brandfetch/Iconify searches); all 3 icon routes native. Verified live incl. logo localization.
  5. Bridge DELETED (lib/finance-bridge.ts, ComingSoon.tsx); Connect = native pipeline bootstrap. No finance path reaches :8096.
  6. Hardening: fflate dropped for a node:zlib zip reader (shared node_modules gets pruned by other agents' npm runs); 504 SPY constituents verified through it.
  7. npx next build --webpack passes (Turbopack still rejects the worktree symlink, known gotcha).

Phase C COMPLETE (Justin said "keep going", same night)

  1. Archives: forge-backups/finances-cutover-20260705/ (finance.db 4.8MB + pg_dump). 16.5. ERPNext daily post: already ran FINANCE_SOURCE=lifeos; patched to include PG-native rows as 1000000 + pg_id (legacy ids top at 98,684, no collision, reversible); dry-run pending set identical across both sources. Receipts job matches the same key.
  2. Branch merged to main, prod rebuilt + restarted (proxy.ts: /api/finance/jobs cookie-exempt). Prod migrations applied, 410 user rules + 137 legacy alert-state keys imported. New user timers forge-creatortrack-finance-{sync,snapshot,receipts} (07/13/19h, Sun 18h, 08h) via scripts/forge_creatortrack_finance_jobs.sh; legacy forge-finance-* timers disabled. Supervised prod run: all 5 jobs green, 5 new txns landed in PG, 5 real alerts paged once.
  3. forge-finances.service disabled, :8096 closed. finances/receipts.justinsforge.com tunnel ingress -> :3070 with host redirects (next.config) to app.creatortrack.ai/finances (CF token couldn't edit redirect rules; origin-side redirect instead).
  4. Homepage tile -> app.creatortrack.ai/finances (served live from disk).
  5. Registered: reference_creatortrack_finance_module; old reference marked RETIRED; MEMORY.md updated.

Next

  • Phase D (20-32): surface-by-surface rebuild WITH Justin on a dev slot, CreatorTrack design system (components/ui, Geist, workspace shell); delete finances.css + Outfit at the final pass. Also fold in: receipt CAPTURE flow (old phone-upload surface died with Flask; zero receipts existed), SSGA as_of cosmetic gap (Investments pass), PNC re-auth reminder.
  • Optional cleanup once confident: drop legacy unit files, remove /finance-migrate script + finance.db from active tree, retire the 8096 ingress entries entirely.

[Claude Code]