Skip to content

v1.13.0

Choose a tag to compare

@github-actions github-actions released this 28 Jul 01:48
· 1029 commits to main since this release

The foreign-currency and attachments release.

You can now record a transaction in the currency it was actually charged in — Monize converts it to the account currency at a rate you can see and override — and every foreign purchase rolls up into a per-account fee breakdown so you can tell what those "no foreign fee" cards really cost you.

This release also makes the app easier to learn: a "What's New" digest greets you after each update, and a set of interactive guided tours can walk you through the app step by step, highlighting the real buttons as they go, and new accounts start from the language and currency your browser already implies.

Transactions can now carry file attachments — receipts, invoices, statements — stored in the database, on disk, or in S3, and attachable by asking the AI Assistant.

Investments gain price history and buy/sell markers straight from Top Movers, loans gain a fixed monthly-budget simulation, new installs get country-aware default categories, and a large Row-Level Security foundation lands quietly under the hood.

Foreign-Currency Transactions

Enter a transaction in the currency you were charged

Bought something abroad, or paid a bill in another currency? On a normal transaction you can now pick the entry currency right next to the Amount field, type the amount exactly as it appears on your statement, and Monize converts it to the account's currency for you — showing the exchange rate and the converted total side by side. The rate is fetched for the transaction's date and is fully editable, so you can match your bank to the cent. Split transactions support foreign-currency entry too, so a single foreign receipt can still be divided across categories. (#931, #933)

See what foreign currency really costs you

Accounts that see foreign-currency activity gain a dedicated Foreign-Currency Fees section on their detail page, broken out separately from the ordinary transaction register. It summarizes the fees you paid per currency, charts them over time, and exports to CSV and PNG. Accounts that have foreign transactions but charge no explicit fee still get the register view, so you can review the activity even when there's nothing to add up. (#935, #949)

Transaction Attachments

Attach receipts and invoices to a transaction

Transactions can now carry file attachments. Add them while you're entering a transaction in the New Transaction window, or attach them later from an existing one. The Transactions list gains an attachment count column — positioned between Tags and Amount — and an attachments filter (Any / Yes / No) so you can pull up everything still missing a receipt. (#971, #972)

Choose where the bytes live

Attachment storage is pluggable via ATTACHMENT_STORAGE_PROVIDER:

  • database (default) — bytes are stored in PostgreSQL, so there is nothing extra to provision and attachments are included in your backups.
  • local — bytes are written to a folder in the container (ATTACHMENT_CONTAINER_DIR, mapped from ATTACHMENT_HOST_DIR). Files are sharded into id-prefixed subdirectories so the folder stays fast as it grows. (Thanks @WMP. #974)
  • s3 — bytes go to S3 or any S3-compatible service (MinIO, Cloudflare R2, Backblaze B2), with optional prefix, custom endpoint, path-style addressing, and either explicit credentials or the default AWS credential chain.

With local or s3, only attachment metadata is included in a Monize backup — back up the directory or bucket alongside it. Every setting is documented in .env.example.

Attach files by asking

The AI Assistant and the MCP server can attach files too. Drop a receipt into the chat and ask Monize to record the transaction — the assistant matches the file by name or position, shows the filenames and sizes on the confirmation card, and only writes them once you confirm. The same rules apply on both surfaces: attachments ride along on a single create or update, capped at 5 files of 5 MB each per transaction, and are rejected on deletes, transfers, and multi-row batches. (#977)

Learning Monize

A "What's New" digest after every update

After an update, Monize now shows a What's New modal summarizing the release's highlights, with a link out to the full notes on GitHub. You control it from Settings — a toggle decides whether it opens automatically, and the version label at the bottom of Settings (and on the login screen) reopens it any time. The digest appears at login rather than on every page refresh, and a new version is also announced on the first refresh after a deploy. Brand-new accounts don't see it on their first login, so it never covers first-run onboarding. If you launch a mini-tour from the digest, the digest comes back when that tour ends. (#951, #952, #965, #970)

Interactive guided tours

New, lightweight guided tours can lead you through the app itself: each step navigates to the right screen, spotlights the actual control, and explains it in a sentence before moving on. A New User Introduction walks the core flow — customizing the dashboard, the Tools menu, accounts, recording a transaction (including payees, categories, splits, and foreign currency), then Bills & Deposits, Investments, budgets, and reports — with a couple of interactive steps where you click the highlighted button and the tour follows along. Start it from the Getting Started card or Settings → Guided tours (where you can also reset your progress). Release-specific mini-tours are offered straight from the What's New modal via "Show me", and your completed and dismissed tours are remembered across devices. A dedicated foreign-currency transactions tour walks through this release's headline feature — picking the entry currency, reading the conversion, and reviewing the fee section. The tour card can be dragged out of the way by its grip handle if it covers something you need to see, and the tour list in Settings is collapsed by default. Every word is translated into all supported languages. (#955, #956, #958)

Start a tour from the dashboard

On the demo instance, a prominent banner at the top of the dashboard invites you to take the introduction tour, so it's always one click away — it reappears on each login and can be dismissed for the session. Once you've finished the tour, the button switches to "Retake the tour."

A first run that starts from what we can detect

The first-run language and currency step no longer assumes English and USD. Both selectors now start from your browser — the currency is derived from the region in your browser's locale and checked against the currency list this instance actually offers, so the common case is a single Continue click and a wrong guess costs one more. The step also runs after an SSO first login: an account an identity provider just provisioned used to land straight on the dashboard and quietly keep the defaults. Returning SSO users, and existing accounts that merely link a new identity, are unaffected. (#978)

Pick your language before you sign in

The corner globe on the login and register screens is replaced by a labelled language dropdown inline in the form, pre-selected from the language your browser asks for. The choice stays in a cookie until you sign in, at which point a deliberate pick is saved to your account. On the demo instance the account is shared, so a language chosen there applies to your visit only and no longer follows the next visitor. (Thanks @WMP. #976)

Import guidance that stays put

The import upload step now carries a persistent notice pointing at the Microsoft Money and Quicken import guides on the wiki, so the format requirements stay visible for the whole import instead of scrolling past once. (#980)

Loans & Mortgages

Plan to a fixed monthly payment

The overpayment simulator gains a "total monthly payment" mode: instead of entering an extra amount, set the total you want to pay each month and the simulator works out the resulting schedule, payoff date, and interest saved. Budget scenarios can be saved alongside your other overpayment scenarios, with an optional window for the overpayment to apply. (Thanks @WMP. #937)

Investments

Price history from Top Movers

Clicking a security in the dashboard's Top Movers widget now opens its price history — a chart plus the underlying rows, so you can see what moved and when without leaving the dashboard. The chart marks your buys and sells along the price line, putting your own trades in context. The history table pages and lazy-loads as you scroll instead of making you click for more, sub-cent prices are kept at full precision, and trades that predate the available price data are left off the chart rather than skewing it. The modal reclaims its full width on mobile. (Thanks @WMP. #961, #965)

Categories & Payees

Default categories that match your country

New installs now get a country-aware set of default categories, picked at import time and localized into every supported language — so a French or German install starts with sensible names instead of English ones. (#969)

One Maintenance menu for payee bulk actions

The Payees screen's bulk actions are grouped behind a single Maintenance menu, clearing the clutter from the toolbar. (Thanks @WMP. #967)

Interface

  • The AI panel can be repositioned with the same grip handle used by the guided-tour card. (Thanks @WMP. #959)
  • Dashboard widgets pick up the same hover edge highlight as Top Movers, so the whole dashboard reacts consistently. (#965)
  • The Combobox "create" option is truncated like every other row instead of stretching its menu.

Under the Hood

  • A multi-phase Row-Level Security (RLS) foundation lands in an inert state (default off): an RLS_MODE flag, per-tenant database roles, a tenantTx helper and request-context plumbing, and a CI ratchet that stops new direct-repository/QueryRunner database access from creeping in. This release also adds the database half — fail-closed identity helper functions, a GUC-aware updated_at trigger, and row-level policies for every table (direct, indirect, and special ownership). Nothing is enabled: the policies are created but not switched on, and the trigger behaves exactly as its predecessor did. Behavior is unchanged until RLS is turned on in a later release. (#945, #979)
  • New database migrations: 100 (account foreign-transaction fee), 101 (transaction original currency), 102 (drop the unused split fx-fee flag), 103–105 (loan monthly-budget scenario columns), 106 (What's New tracking), 107 (guided-tour progress), 108 (cascading user foreign keys), 109 (transaction attachments), 110 (drop the legacy is_cleared / is_reconciled transaction columns, long since superseded by the status field), and 111–114 (the inert RLS helpers, trigger, and policies described above).
  • Storage folders are now configured with an explicit container/host split: ATTACHMENT_CONTAINER_DIR / ATTACHMENT_HOST_DIR and BACKUP_CONTAINER_DIR / BACKUP_HOST_DIR, with the host bind-mount defaults nested under ./monize. The old ATTACHMENT_LOCAL_DIR still works but logs a deprecation warning at startup. BACKUP_RESTORE_LIMIT caps the size of an uploaded backup on restore. (#973, #975)
  • Deleting a user no longer fails on non-cascading foreign keys, and a Settings data purge now drops the cached lists that referenced the purged rows.
  • Local attachment storage validates keys against path traversal, and the Bearer scan's CWE-22 hits on that code are triaged as false positives. Attachment checksums are compared in constant time.
  • The AI streaming endpoints now escape markup in every server-sent event before it reaches the socket, so no raw <, >, &, or line-separator characters exist in the response body. Clients parse the original text back unchanged; this is defence in depth on top of the nosniff header already sent. (#981)
  • Security and dependency maintenance: Next.js, sharp, dompurify, js-yaml (GHSA-pm4m-ph32-ghv5), brace-expansion, and fast-uri bumped to clear advisories, plus TypeORM/Hono and other Dependabot updates. CI now blocks on advisories in shipped dependencies and only reports dev-only ones.
  • Translation hygiene: 35 orphaned keys dropped from every locale, and Portuguese strings that had leaked into the Ukrainian catalog fixed.

All Changes

  • Add foreign-currency transaction entry with exchange rates by @kenlasko in #931
  • Add foreign-currency editing to split transactions by @kenlasko in #933
  • Add foreign currency transaction fees reporting by @kenlasko in #935
  • feat(loans): "total monthly payment" simulation type (fixed loan budget) by @WMP in #937
  • Show foreign-currency register for accounts without fees by @kenlasko in #949
  • Add "What's New" release-notes digest modal by @kenlasko in #951
  • Increase WhatsNewModal max width from 2xl to 4xl by @kenlasko in #952
  • RLS foundation, CI ratchet, and inert context wrapping by @kenlasko in #945
  • Interactive guided tours, prominent demo banner, and this release's mini-tours by @kenlasko in #955
  • Foreign-currency guided tour by @kenlasko in #956
  • fix(tours): 1.13 beta tour review by @WMP in #958
  • feat(ui): move the AI panel with the tour card's grip handle by @WMP in #959
  • feat(dashboard): open a Top Movers price history, chart it, and mark buys and sells by @WMP in #961
  • Widget hover highlight, price-history paging, and What's New at login by @kenlasko in #965
  • feat(payees): group the bulk actions behind one Maintenance menu by @WMP in #967
  • Country-aware, localized default categories by @kenlasko in #969
  • Don't open the What's New digest on a first login by @kenlasko in #970
  • Transaction attachments: attach files, count column, and filter by @kenlasko in #971
  • Attachment storage providers: database, local filesystem, and S3 by @kenlasko in #972
  • Drop legacy transactions.is_cleared / is_reconciled columns by @kenlasko in #973
  • perf(attachments): shard local storage into id-prefixed subdirectories by @WMP in #974
  • Backup directory env vars and container/host storage split by @kenlasko in #975
  • Add attachment support to manage_transactions (AI Assistant + MCP) by @kenlasko in #977
  • feat(tours): guided tour for bringing your data in (QIF/CSV import) by @WMP in #960
  • feat(auth): explicit language selector on login/register, per-visitor in demo by @WMP in #976
  • RLS M1/M2: identity helpers, trigger, and policies (inert) by @kenlasko in #979
  • Pre-fill the first-run language/currency step, and show it after an SSO first login by @kenlasko in #978
  • Remove import tour and move wiki links to upload step by @kenlasko in #980
  • Escape markup in SSE streams to prevent XSS (CWE-79) by @kenlasko in #981

Full Changelog: v1.12.1...v1.13.0