Skip to content

Release v0.3.0 - #144

Merged
marcodonghiaa merged 39 commits into
mainfrom
claude/project-thread-mj17ax
Nov 14, 2026
Merged

marcodonghiaa merged 39 commits into
mainfrom
claude/project-thread-mj17ax

Conversation

@marcodonghiaa

Copy link
Copy Markdown
Owner

Release PR for v0.3.0. It changes no code: only the version, the upgrade notes and the changelog.

  • installer/package.json: version 0.2.0 → 0.3.0. The installer downloads tag v0.3.0 of both repos.
  • UPGRADING.md: the "Unreleased" section becomes v0.3.0 (14 Nov 2026). It adds:
    • a one-line summary
    • "Upgrade with the installer" (npx create-alopex@0.3.0)
    • the manual order: 4 migrations 20261208120000 to 20261211000000, run before the dashboard. No Edge Function changes.
    • two new notes: Installer --help and updating from inside the install (Installer: --help is taken as the folder name #132), and the dashboard fixes
  • site/changelog.html: a new "14 Nov v0.3.0" entry above v0.2.0.
    • New: notes and tags, the Cash flow page, the recurring calendar, regular and one-off income with who paid you.
    • Improved: Back closes panels and dialogs, toasts in dark mode, installer --help and updating, old long rules can be edited again.
    • Upgrade line: npx create-alopex@latest.

What's in v0.3.0:

After merge (Marco):

  1. Tag v0.3.0 on both repos, at main.
  2. cd installer && npm publish. Run npm login first if npm answers 404.

npm test: 368 pass, 0 fail.


Generated by Claude Code

…match pg_cron

- markRefunds (Deno post-sync and Node classify-flow) pairs only rows whose flow_source is
  'default', guarded on it too: a flow you, a rule or a past choice decided is never moved
  to refunded.
- Node sync stores own_counterparty like the Deno sync (same IBAN compare, left out when
  your accounts can't be read).
- Installer: Gemini privacy note says what goes to Google (names, descriptions, amounts,
  imported PDFs) and the free-tier terms.
- README: sync runs in Supabase (pg_cron + Edge Functions), not on your computer.
- package.json: name alopex, real description, version 0.1.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Legacy flows (set before flow_source existed) are what refund pairing always read, so a
refund of a charge from before the upgrade still pairs. Only flows you or a rule decided
stay untouched. Comments no longer claim the dashboard can mark refunds by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
A "not a transfer" flow rule sets flow_source='rule' but keeps the
direction, so the default/legacy-only filter stopped pairing refunds for
those merchants (counted as spend and income). Refunds now skip only
flows set by hand. The update guards flow_type too (new optional alsoIn
in applyGroupedUpdates), so a row a rule turned into a transfer after
the read is left alone. Tests now run against an in-memory table and
check which rows pair, not the query shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
entry_reference is not unique across accounts, so pages could overlap
or skip rows and miss a pair. The Deno side already does this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
A pair whose second write failed, or whose other side you moved to
Transfer or deleted, stayed 'refunded' on one side for good, putting
spend and income off by the amount. Each run now repairs these first:
it finishes a pair whose charge is still plain spend, counts a lone
credit as income again (keeping refund_of, so it can only re-pair with
that same charge, never last month's identical one), and counts a
charge with no live refunded credit as spend again so it pairs anew.
Rows you set by hand are never touched. A credit looks its charge up
by key with no date limit, so pairs at the window edge stay intact.

Also: candidates are read in primary-key order and deduped by key (a
concurrent write could shift a row into two pages), and a failed refund
write now marks the post-sync run as failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
While the Node scheduler still runs, it could pair a credit the Edge
repair reset to income with an older identical charge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
restrict_transaction_updates now guards refund_of too. Only the refund
pairing (service role, trigger skipped) writes it; a signed-in user
setting it could break the pairing query for every user or pair a
credit with any charge (P2-3).

Test: lock-refund-of-migration.test.js "a signed-in user cannot change
refund_of" (also checked on PGlite: user update rejected, service role
and category/flow updates still allowed, rollback reopens it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
A charge lookup that errors now skips that account's repair for the
run (counted as failed, logged by code only) instead of throwing out of
markRefunds, which skipped refunds for every user (also P2-2).

Test: flow.test.ts "a failed charge lookup on one account is counted,
the others still repair and pair".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
`node --test installer/` also ran installer/index.js on Node 22 (real install + Supabase call).
Test: "the installer test command runs only the test files".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Subscription/One-time runs right after categories, not last.
Test: "the README lists the post-sync steps in the order they run".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…ions

post-sync also sends Splitwise expense descriptions to Gemini (categorizeSplitwise).
Test: "both Gemini privacy notes mention Splitwise".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Up/down/up in one rolled-back transaction: a signed-in user can't change or clear refund_of,
still edits category/flow, can't touch other users' rows; the service role still writes it.
Fails against the migration without the lock line (checked on local Postgres 16).
Test: "a rehearsal runs the lock as a signed-in user and as the service role".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
npx create-alopex downloads tag v<installer version>; it was still v0.1.0, so new installs missed
13 migrations. UPGRADING.md gets a v0.2.0 section (installer and manual upgrade order) and the
refund_of note now says post-sync must be redeployed too.
Test: "UPGRADING.md has a section for the installer version".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…changelog

FAQ (and its JSON-LD) said Gemini sees transaction descriptions; it also gets names, amounts,
Splitwise descriptions and imported PDFs, and the free tier may train on them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
Before, any first argument was the install folder, so --help installed into ./--help.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
… (polish-1 B1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…arting with - (polish-1 B2/B3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
On Windows cmd expands %VAR% even inside quotes, so tar -C would unpack elsewhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
… in lib (polish-3 F9, F11)

main() now only applies lib.startup(argv), so help/refuse/install is covered without
spawning the installer (a spawn test would start a real install if it broke).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…alopex/alopex (polish-5 I1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…ide the install; mark Codespaces-only steps (polish-5 I1, I2, I5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…ish-5 I1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
… it too (polish-5 I1 re-audit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…ding (polish-5 I5 re-audit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
…r, after asking (polish-5 I1 re-audit 2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
… (polish-5 I1 re-audit nit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ob4vvxZYctk2yjxFjnvCL
@vercel

vercel Bot commented Nov 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
myfinances Ready Ready Preview Nov 14, 2026 6:48am UTC

@coderabbitai

coderabbitai Bot commented Nov 14, 2026

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c4eb6ec1-e0ad-4d8c-bbcd-62124c08d5af
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@marcodonghiaa
marcodonghiaa merged commit 6989cd5 into main Nov 14, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants