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)¶
- Module boundary:
docs/FINANCES-APP-SPEC.md+ eslintno-restricted-importsregex rules both directions; module lint debt cleared. finance.job_runs+finance.alert_statemigration.lib/finance-simplefin.ts(28 accounts live).app/api/finance/jobs/[job]runner, bearerFINANCE_JOBS_TOKEN(appended to~/.forge-secrets/creatortrack-auth.env), owner identity via core.login, run log in job_runs, fail-loud notify.lib/finance-jobs/sync.ts: idempotent (verified run1 26 new / run2 0), cross-source reconcile ported, zero-balances now FAILS the run.lib/finance-jobs/categorize.ts+finance.user_rules(410 rules seeded on clone; JSON import at cutover): 8812/8812 parity with the Python engine.lib/finance-jobs/recurring.ts: 90 total matches SQLite; user-curated rows survive.lib/finance-jobs/holdings.ts: live Yahoo pricing 17/17, SSGA xlsx via newfflatedep, Vanguard JSON, 6 funds refreshed.lib/finance-jobs/alerts.ts+finance.alert_feedmigration: 8 real alerts on clone, dedup verified.lib/finance-jobs/snapshot.ts(55 accounts, idempotent) +lib/finance-jobs/receipts.ts(+erpnextList/erpnextUploadFilein lib/erpnext; attach path unexercised, zero receipts exist).
Also fixed this session (prod)¶
finance.*PG mirror was frozen since 07-03: workspace re-slug brokeforge_finance_migrate_to_lifeos.py(default slug nowjustin). Mirror reloaded, current.
Discovered dependencies / notes¶
- Task 16.5 added to plan:
forge_erpnext_daily_post.pyreads finance.db and stampsFINDB-<sqlite id>; must repoint to PG before SQLite retires. Old ids preserved inlegacy_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>.mtsfrom the worktree;server-onlyimports need lazy import or fail under tsx. - Drizzle
sqlexpands arrays as tuples: usein ${arr}, never= any(${arr}).
Phase B also complete (same session, Tasks 11-15)¶
/api/finance/transactions: per-txn + bulk edit (first txn write surface in CreatorTrack; sticky user_category verified against the categorize job).- recurring/action + categorize/apply routes rewritten native (python helpers + JSON sidecars retired; flag = review_flagged; rules upsert finance.user_rules).
/api/finance/budgets(FLEX_KEY-aware upsert),/api/finance/manual-values(append-only), Sync button runs the native pipeline via after().- 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. - Bridge DELETED (
lib/finance-bridge.ts, ComingSoon.tsx); Connect = native pipeline bootstrap. No finance path reaches :8096. - 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.
npx next build --webpackpasses (Turbopack still rejects the worktree symlink, known gotcha).
Phase C COMPLETE (Justin said "keep going", same night)¶
- 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 as1000000 + 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. - 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) viascripts/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. forge-finances.servicedisabled, :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).- Homepage tile -> app.creatortrack.ai/finances (served live from disk).
- 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]