In this release we added payment matching: money that lands in an account binds itself to the invoice it settles, what it cannot decide alone goes to a queue, and the rules behind it are a list you can read, reorder and rewrite. Indian workspaces get an April to March financial year, seven currencies joined the list, and rules gained a full editor when adding a transaction to one and a way to be managed through MCP. On the fixes side, editing a recurring schedule moves its next occurrence, synced card installments inherit the category you gave the first one, a credit card bill no longer shrinks when a charge is tagged as a transfer, and the payees list holds up at the size a bank sync makes it.
Features
- Payments match the invoices they settle. Every transaction that comes in, whether synced, imported or typed by hand, is checked against open invoices and linked when the evidence is clear: same client, exact amount, inside the date window. One payment can settle several invoices and an invoice can be paid in parts. What is plausible but not certain waits under Rules with the evidence attached, to link or decline in one click, from the queue, the invoice or the transaction row. A history says what happened and whether you or the rules did it, and open invoices now count in the cash forecast (#817)
- Matching rules are yours. Each threshold is a row under Rules: how close the amount must be, how wide the date window is, whether the payer must be known, whether a match links or asks. Reorder them, edit them, write your own, delete the shipped ones and bring them back, or export the set to a file and import it elsewhere (#817)
- Indian financial year. A workspace with
tax_jurisdiction = INreports on an April to March year, with INR grouping and day-first dates. By @SaikumarMadel (#841) π - Adding a transaction to a rule opens the full editor, pre-filled with the rule's conditions and actions, instead of a bare description field. Closes #905, by @vhsantos26 (#906) π
- Rules through MCP. An agent can list rules, preview what one would do, and propose a create, update or delete that you confirm in the existing proposal UI. Closes #908, by @DanielSuhett (#910) π
- Seven new currencies. Chinese yuan, closes #832, and Malaysian ringgit, closes #921, by @shaynhornik (#940, #939) π Β· Egyptian pound, closes #922, by @archibullo (#923) π Β· Thai baht, closes #865, by @deeepanshu (#903) π Β· UAE dirham, by @asankahh (#945) π Β· Moldovan leu, closes #878, by @maxpricop (#885) π Β· Pakistani rupee, closes #866, by @7487 (#867) π
Fixes
- Editing a recurring schedule left its next occurrence where it was. Changing the start date, day of month or frequency now moves the pointer to the first date of the new schedule, so projections follow the edit. Closes #942, by @rhuanbarreto (#943) π
- Synced card installments inherit their category. Once you categorise one installment of a purchase, the next ones arrive with the same category instead of blank, with your rules still taking precedence. By @panga (#894) π
- A credit card bill shrank when a charge was tagged as a transfer. The bill total reused the reporting filter, so a charge under a transfer or ignored category dropped out of what you owe the bank. Closes #647, by @vhsantos26 (#649) π
- Widening a card's date range could hide billed charges. A hand-picked window that matched no bill asked the backend for unbilled rows only, so the list and its total got smaller as the range got bigger (#874)
- The payees list holds up at the size a sync creates. Long names truncate instead of widening the table, the list is paginated, and the detail card no longer displaces it. Closes #709, by @jrvidotti (#710) π
- Payees with a legacy type made the list fail. Rows imported long ago as
transfer,employerormerchantare read as untyped instead of returning a 500. Closes #830, by @wolfgang-aura (#875) π - A sync failed on a counterparty with a non-ASCII capital in its name. The payee lookup compared a database lowercase with a Python one, which disagree on a C-locale Postgres, so the second transaction naming "MΓLLER GmbH" tripped the unique constraint and took the whole sync down. Closes #678 (#683)
- CSV import preselects the categories it already recognises, so a column that matches an existing category by name shows up chosen in the preview. By @joaolucenalima (#812) π
- Gemini through an OpenAI-compatible connection rejected tool results. Thought signatures on tool calls are kept through streaming, persistence and replay, and the
/v1beta/openaipath no longer gets an extra/v1. Closes #884, by @11VitorAlves11 (#889) π - OIDC-only deployments could not remove an old 2FA or passkey. The dialogs are reachable in a remove-only mode for users who enrolled before the switch. By @ADolkun (#898) π
- Disabling 2FA blamed the code for every failure, including a wrong password. The real reason is shown, and the fields carry the right autocomplete hints. By @ADolkun (#891) π
- Leaving the login page mid-passkey prompt still spent the challenge. The ceremony is dropped when the page is gone, and the passkey button no longer flashes in on first paint. By @ADolkun (#892) π
- Helm: 502 from nginx on Kubernetes. The frontend resolves the backend by its fully qualified service name,
frontend.backendUrloverrides it, and/apiis routed straight to the backend in both the Ingress and the HTTPRoute. By @jorishaenseler15 (#868) π
Under the hood
Migrations 086 to 089 run automatically on upgrade and add the matching rules, suggestions and history tables; nothing existing is rewritten Β· CI now fails on any pytest or ESLint warning, with the previous forty cleared, by @ADolkun (#873) π Β· the JWT expiry test uses a fake clock instead of sleeping, by @ADolkun (#893) π Β· one CI run in ten was failing on a random test because SQLite turned all-digit UUIDs into floats (#948) Β· uv moved to 0.12.15 (#858, #928), Helm to 4.3.0 (#929) and the backend dependencies were refreshed (#859, #931)
Thanks @SaikumarMadel, @vhsantos26, @DanielSuhett, @shaynhornik, @archibullo, @deeepanshu, @asankahh, @maxpricop, @7487, @rhuanbarreto, @panga, @jrvidotti, @wolfgang-aura, @joaolucenalima, @11VitorAlves11, @ADolkun and @jorishaenseler15 for the code and the reviews, and @e3mydu1f, @yikeat, @doubleOZ, @aiexpert-Azan, @kodazavr and @adheizal for the reports π
Full Changelog: v0.15.1...v0.16.0