Changelog
What we ship, when. Updated on every release.
v0.24.42
- Clearer, accurate descriptions of what's available today: the FIRE calculator page cites the simulator's real 10,000-path run and no longer quotes an unsourced guardrail figure; the bank coverage page and welcome emails describe manual entry and statement, SMS and email import, with automated bank feeds shown as a Q1 2027 roadmap item.
- Gulf currencies selectable for accounts and base currency: Qatari riyal, Kuwaiti dinar, Bahraini dinar and Omani rial, plus the Singapore dollar and Swiss franc, can now be picked for accounts, base currency and reporting currency.
v0.24.41
- The currency exposure summary shared with connected AI assistants now lists the Jordanian dinar, Qatari riyal, Bahraini dinar, Omani rial and Kuwaiti dinar under their own names instead of "Other", with a risk level that reflects whether each is pegged to the US dollar.
- The AI advisor report PDF is now named with your local date. It used the UTC date, so a report saved shortly after midnight in the UAE carried the previous day.
v0.24.40
- A referral can't be sent twice after a network hiccup. If a connection timed out while a referral to a will partner was going out, retrying could send it again; now it shows a reference and asks you not to resend.
- Every referral attempt now has a recorded outcome, including ones held back by the one-minute wait between referrals to the same partner.
- Will jurisdiction labels and the Sharia one-third rule message now describe the situation instead of telling you what to do.
v0.24.39
- Clearer messages if account deletion is interrupted. If a paid plan was set to end before the problem, the message now says it ends at the close of the billing period, which parts of the deletion finished, and what is still to do.
- A subscription payment left unfinished for over an hour no longer blocks starting a new checkout for up to a day.
- The confirmation page after payment now waits up to about 20 seconds for your plan to show as active, and says only that payment was received until it does.
- Prices shown from one source: the home, pricing and press pages and the comparison pages now read the plan prices from the same table the checkout prices are set up from.
v0.24.38
- Every kind of record is checked the same way before saving. Accounts, debts, income, budgets, insurance premiums, goals and holdings now get the same checks as transactions (amount within range, a valid currency code, a readable date). A record that fails is not saved, and you are told why. A Financial Planner import skips only the rows that fail and imports the rest.
- Splits can't bring back the original. After you split a transaction, syncing or importing the same bank row again no longer adds the original next to its parts, and a recurring income or expense is not generated again for that month.
- Recovery keeps every readable row. The background copy of your data to the cloud database no longer stops at one entry it cannot read: every readable entry is copied, and the rest stay unchanged on this device. When restored data includes entries this version cannot show, the notice now offers to remove them. Removal only happens after you confirm it.
- Bank sync no longer skips transactions it could not save while saving was paused. They are delivered again on the next sync.
v0.24.37
- Cloud sync stays live when you switch tabs or a background tab is paused. One tab listens for changes from your other devices; when that tab is hidden, paused by the browser, or loses its connection, another open tab now takes over instead of every tab waiting for a reload.
- Fewer reads at startup: a tab opened while another K25x tab is already syncing uses that tab's data instead of downloading everything again.
- A rule, alert threshold or net-worth history edit made in one tab is no longer lost when another tab or device saves at the same moment, even when both changed the same rule.
- Turning cloud sync off now stops it in every open tab straight away, not only after a reload. Turning it back on in a tab that was syncing resumes live updates straight away too.
- If re-encrypting your cloud copy does not fully finish when you turn on encryption, other devices are not yet required to encrypt, so their sync is not blocked while unencrypted data is still in the cloud.
v0.24.36
- Paid plans now get their full AI report length. The monthly report and the AI advisor report were sized for the Free plan for everyone, so Pro and Family reports could be cut short.
- Monthly report figures now come from K25x's own calculations, not the AI. Every number in the AI recap must match one K25x calculated from your data; a recap with any other figure is replaced by the calculated report. The recap only says market movements drove a change in net worth when they were the largest part of it.
- The AI advisor and the monthly recap now describe what your numbers show instead of telling you what to do; prose that reads as an instruction is rewritten or replaced.
- Monthly report: a recap held back by the content filter now shows the calculated report and the disclaimer instead of an empty notice; a goal with a zero target no longer shows "Infinity%"; the PDF prints the disclaimer once and uses your currency for the cash-flow bars.
- Story submissions: if a story cannot be saved, the form now says so instead of confirming a submission that was not stored.
v0.24.35
- Cloud sync: a download that fails part-way (for example when browser storage is full) can no longer cause the next upload to delete your cloud copies. The same holds when this device has no local copy of your financial data.
- "Sync now" says "Pushed N items" only when everything was uploaded. Otherwise it says how many items were not uploaded. "Last synced" is no longer updated after a sync that did not finish.
- Cloud sync uses fewer reads per change: a change made on another device is downloaded on its own instead of re-reading all your data, only one open tab listens for changes, and a change is uploaded once rather than once per open tab.
- Turning cloud sync off, or turning on Local-only mode, now stops uploads from every open tab straight away. Backup copies the app keeps of data it could not read stay on this device.
v0.24.34
- Arabic site, groundwork only: nothing here is visible yet. The Arabic site is still switched off and stays off until a native Arabic speaker has reviewed the wording. When it is switched on, each main English marketing page will have an Arabic counterpart (pages not yet translated show a short Arabic notice linking to the English original), so links on the Arabic pages never lead to a missing page. The calculators under Tools and the sign-in pages stay English-only.
- Ready for when the Arabic site is switched on: icons, spacing, table alignment and arrows follow right-to-left reading order, a language switch links to the same page in the other language, and figures keep Western digits with currency codes in Latin letters (for example AED).
- Ready for when the Arabic site is switched on: if you open the app after reading the Arabic pages, a one-time notice will say the app itself is in English only for now.
v0.24.33
- Your data survives app updates intact: details added by a newer version of the app, or by another of your devices, are kept when this version saves, edits or restores your data.
- Exports while saving is paused are truthful: the file is your saved data exactly as stored on this device, labelled as a raw backup, or nothing at all if there is none. It is never an empty backup. The daily net-worth snapshot is not recorded while saving is paused.
- Every save tells you if it was refused. Forms, imports and tool pages stay open with what you entered instead of showing success, a PDF import credit is used only when transactions were added, and if this device cannot open its secure storage the app says changes are not being saved.
- Duplicate detection on import recognises the same statement row whatever time zone your device is in, and no longer treats two different transactions with long, similar descriptions as one. Currency codes typed in lower case are stored in upper case and counted in your totals.
- Donations and remittances recorded from now on, and retirement contributions on the tax-advantaged page (updated the next time you open it), count in their own currency instead of your base currency.
v0.24.32
- Estate partner referral: clearer limits, truthful status, and tighter privacy on failures. Only a referral that is actually sent counts toward the daily limit; a retried request is not sent twice; the confirmation screen says whether your confirmation email went out; an unverified email address is flagged before you start; and a failed send shows a reference number instead of the email provider's error text.
- Estate: the jurisdiction notes now describe what each country's will process involves rather than reading as a to-do list, and the Estate page describes the partner-match flow as it works today.
v0.24.31
- Billing: account deletion now also finds a subscription whose billing record was not saved yet and sets it to end at the close of the paid period, and stops (so you can try again) if the billing record cannot be read. If a deletion fails after your plan was set to end, the message now says so.
- Safer handling of plan changes: a second or old subscription can no longer overwrite your active plan, a plan on an unrecognised price keeps its tier, and the payment page says "active" only once the plan is confirmed.
- Signing out or switching accounts on a shared device no longer leaves the previous person's billing details in the app.
v0.24.30
- Added regression tests around subscription and entitlement checks, saved AI-provider keys, report and CSV exports, and the monthly report and advice narration. Nothing you see changes; these tests make future changes to those calculations safer.
v0.24.29
- Email sign-in codes are now stored with a keyed hash.
v0.24.28
- Error reporting keeps its strict privacy settings after a major library upgrade: no cookies, request bodies, user details or database query contents are sent with an error report, and sensitive values are still redacted before a report is sent.
- Routine updates to sign-in, rate-limiting, forms, analytics and the test tooling.
v0.24.27
- The SMS, email and CSV/Excel import screens now say in their own message how many rows were skipped and why, next to the number imported and the number of duplicates. Before, a general notice replaced their message, so the duplicate count disappeared. If saving is paused, these screens no longer show "Imported" for a save that did not happen, and the rows stay on screen.
- Receipt scanning: if a scanned receipt cannot be saved, the dialog stays open with the receipt so you can correct it, instead of showing "Saved" and closing.
v0.24.26
- AI PDF statement import is now part of the Pro and Family plans. On the free plan, the PDF statement option shows a short note saying so, with a link to CSV, Excel and on-device PDF import, which stay available within the same 12-document allowance. An import that is refused no longer counts toward the daily AI allowance this device keeps track of. Before, a free account could start an AI PDF import and then be stopped by the daily AI allowance partway through.
- Arabic pricing page: cloud sync was listed as included on the free plan. It is part of Pro and Family, as the English page says. The Arabic comparison table also gains the reporting currency and FX board row, and two Arabic free-plan lines no longer mention linking a bank, which is not available yet.
v0.24.25
- Qatari riyal, Bahraini dinar, Omani rial and Kuwaiti dinar balances now convert while live exchange rates are loading or unavailable, instead of showing "—". The Qatari riyal, Bahraini dinar and Omani rial are treated as pegged to the US dollar. The Kuwaiti dinar uses an approximate rate, because it is linked to a basket of currencies rather than to the dollar. Their daily rates are now kept for the FX page history.
v0.24.24
- PDF statement import (AI): long statements are read in smaller sections, so a section is no longer cut off part-way; if part of a statement still could not be read, the review says so and about how many lines are missing, instead of showing a shorter list as if it were complete. A row with no date on the statement is no longer dated 1 January; it waits in the review until you give it a date. Each row shows the line as read from the statement. A row whose amount, date or direction (money in or out) does not match that line, or whose date is more than two years from today, is held until you confirm it.
- PDF statement import (AI): the review has a Statement currency picker listing every currency, filled in when the statement names its currency (for example "KD" or "Kuwaiti Dinar") and otherwise left empty until you choose one. The currency you pick is the one saved on the rows, except a row that prints its own currency beside the amount, which keeps it. Amounts are labelled, not converted. Rows in currencies such as KWD or PHP import normally; the review notes that they are converted with live exchange rates and are left out of totals while no rates are available. Where the statement prints totals or opening and closing balances, the review compares them with the rows being imported and shows both figures when they differ.
- SMS import: a message with no currency is no longer saved as AED. It is labelled with your base currency and the review says so; the review has a currency column you can change per row. Only a currency printed beside the amount counts, so an available-limit figure in another currency does not relabel the purchase. A date with no year (for example 30/12 read on 2 January) is placed in the most recent matching year, not the future. Declined or failed transactions, reversals, pre-authorisations, and rows whose amount or date does not match the message start unticked with the reason shown.
- SMS and email import review: dates showed one day early in the UAE and other timezones ahead of UTC. They now show the day that is saved. An email transaction with no date is no longer dated today; it waits in the review until you give it a date.
- Receipt scan on your device: the total is taken from the grand total or amount due line, or the last total line, so "Total savings" is no longer picked up. Whole-number totals are read, and cash handed over is no longer used as the total. The total stays editable before you save.
v0.24.23
- Importing a CSV or Excel statement: dates are now read in one order for the whole file. Before, 25/03/2026 was read as 25 March and 03/04/2026 in the same file as 4 March, and dates written with dots (03.04.2026) were always read month-first. The import screens now show a Date order setting, pre-set from the file where the file settles it. Where it does not, a suggestion is shown and the import waits until you choose.
- Importing a statement: amounts marked DR or CR are now stored as expenses and income. Before, "1,250.00 DR" was stored as income. A new Amount signs setting says how signs are read: minus as money out (bank-style), minus as money in (card-style), or the Type column. When a file has a Type column and any negative amounts, the setting is pre-filled only when at least 10 rows clearly point one way; otherwise the import waits until you choose. The screen shows how often the Type and the sign agree, how many rows have a Type the app does not recognise, what the selected option would do, and the rows it reads differently from their Type. Workbook sheets that would need different settings are imported one at a time. When the Type column decides, rows whose Type is not recognised are skipped by default, or imported as money out or money in if you choose that under "Rows whose type isn’t recognised".
- Importing a statement: the import screens now ask which currency the statement is in, instead of assuming your base currency. Rows keep the amounts as written and are labelled with that currency; nothing is converted on import. A currency cell the importer cannot read (for example "Rupees") is listed as an error instead of being stored under your base currency. Any currency code can be chosen as the statement currency. For a currency with no built-in fallback rate (for example Kuwaiti dinar), the import screen notes that totals use live exchange rates and leave those rows out until rates have loaded on the device.
- Importing a PDF statement on your device: the running balance is no longer taken as the amount. Before, a 250.00 purchase on a statement with a balance column could be stored as income of 12,345.67, and the opening balance was imported as a transaction. Lines where the amount or its direction cannot be worked out from the PDF, including every line of a statement with no column header and card statements whose only marks are minus signs, are now listed for you to review and are not imported.
- Both import screens now show each row as it will be stored (date with the month spelled out, income or expense, amount, currency) before you import, and list every row that will be left out with the reason.
- Importing a statement: amounts written with Arabic-Indic digits are now read. Amounts that use a comma as the decimal point, such as 0,500, are read correctly when the file shows that format or you choose it under Decimal separator.
- Importing an Excel workbook: you tick which sheets to import. Only the first matching sheet is ticked to start with. Before, every sheet was merged, so a summary sheet’s total could be imported as a transaction.
- Importing a CSV: files larger than 5 MB are now refused with a message before they are read, instead of freezing the page.
v0.24.22
- Importing: a single row with an amount below 0.01 or above 1,000,000,000 could make all of your saved data fail to load the next time you opened K25x, and stop new changes from saving. Every row is now checked before it is stored. Rows that cannot be stored are left out, the rest are imported, and you are told how many were skipped and why.
- Opening K25x: if some saved entries cannot be shown by this version of the app, everything else now loads as normal instead of nothing. Those entries are kept exactly as they are, on this device and in cloud sync, and a newer version of the app shows them. A bar at the top of the page says how many there are, and offers to remove them if you choose; removing them deletes them from all your devices.
- If an earlier version set your data aside after the problem above, K25x restores it by itself the next time it opens, as long as you have not added newer data since, cloud sync is off, and this browser belongs to your account. With cloud sync on, your cloud copy is used instead. The bar at the top says how many entries were restored.
- The message shown when saved data cannot be read pointed to a recovery screen in Settings that does not exist. It now says what is true: nothing is shown, changes are not being saved, and a backup file can be loaded in Settings.
- Importing a file with two identical rows (same day, amount, description and currency) now keeps both. Before, the second was dropped and reported as already in your data. Importing the same file again later still adds nothing.
- Importing: a transaction saved without a currency now counts as your main currency when checking for duplicates, so importing the same statement again no longer adds it twice. Entries this version cannot show are also counted, both in that check and before sample data replaces your workspace.
- Restoring a backup: a file holding some entries this version cannot show was refused whole. Those entries are now restored and kept unchanged. The restore checklist says how many there are, asks you to confirm, and says plainly that restoring replaces those categories on this device and on every device that syncs with it. A backup made from Settings also includes such entries.
- Restoring an old full backup: transactions saved without a currency are now given the currency the backup was made in, when the file records one. Before, they were read in whatever your main currency is today.
- Quick add, editing a transaction and applying rules: a change that cannot be saved now says so and keeps what you typed. Apply rules counts only the transactions it actually changed, and "save as a rule" is only offered when the edit was saved.
- Recurring income and expenses: if a generated entry cannot be saved (for example an amount under 0.01), K25x now says so once instead of dropping it silently. That entry is not added; once the amount is fixed, new entries are added as normal.
- If another open K25x tab, or cloud sync, delivers data this version of the app cannot read, saving now pauses until you reload, and a bar at the top says so with a Reload button. Nothing is saved over the newer data, and changes you try to make meanwhile say they were not saved instead of disappearing.
- Bank sync: a bank correction that cannot be saved (for example an amount of 0) is now counted in the sync message instead of being dropped without a word.
- Financial Planner import: a row with an amount above 1,000,000,000 is now listed as skipped instead of being saved.
v0.24.21
- Invest: Boglehead Scores change. The concentration part of the score now looks only at single names, meaning individual stocks and crypto coins. Index funds and other ETFs count as diversified, so a portfolio held entirely in one global index fund is no longer marked down as concentrated. A portfolio that is 90% in an index fund and 10% in one stock reads that stock at 10%. A narrow or single-sector fund also counts as diversified.
- Invest and Portfolio: without a policy of your own, the illustrative mix the score compares against is now 70% equity and 30% bonds, with no crypto or REIT share. Crypto holdings are compared against a 0% target in that case, and REIT holdings count as equity, the same as a REIT fund saved as an ETF. If you have set your own policy, your targets are used as before; REIT holdings count as equity there too unless your policy sets a REIT target.
v0.24.20
- The expert-team panel on the Advisor page is now an analyst panel. The tax, investment and planning analysts explain what your numbers show and the trade-offs involved, and the summary brings their views together. It no longer ends with a list of steps to take.
- Plan and the advisor report: the "Next 3 moves" and "Action checklist" sections are now "What moves your plan most", three observations about your numbers ranked by their modelled impact, for example how far a higher savings rate moves your independence date in the model.
- Wording on the methodology page, a member story, the PopaDex comparison (English and Arabic) and the UK pension guide now describes rather than tells you what to do. The UK pension guide now cites the FCA rule on defined benefit transfers directly.
v0.24.19
- Home: the recent-transactions and goal widgets show only the amount in its own currency to keep the page compact, but the converted figure in your reporting currency is now available on tap or hover.
- The currency-risk tool now recognises Egyptian pound (EGP) holdings as their own currency instead of grouping them under "other".
v0.24.18
- Gold funds (for example GLD, IAU, SGLN, IGLN) now show as their own Gold slice in your allocation instead of counting as equity ETFs.
- T-bill and money-market funds (for example SGOV, BIL, SHV) now show as Cash instead of Bond.
- Some Boglehead alignment numbers change. Index funds and single stocks are now measured together as equity, so a portfolio of index funds no longer scores lower than the same portfolio with a single stock swapped in. Gold and cash-like funds have no target, so they no longer move the number either way; they are listed separately as not scored. The allocation drift card on Portfolio reads the same way.
- The AI advisor, chat, Quick Insights and the year-end tax summary now see each holding’s corrected class, so a bond fund you saved as an ETF is treated as a bond.
v0.24.17
- Quick Insights on the Home page: after you add, remove or edit an investment holding, the card no longer shows insights worked out for your previous holdings. Before, it could reuse them for up to a day.
- Removing your data from this device: a K25x tab you had left open elsewhere could set up a new, empty encrypted store on this browser after the removal. It now leaves the browser empty until someone signs in again.
v0.24.16
- Wording: the health score tips, the emergency fund card, the Plan tab watch list, the standard roadmap steps, the advisor report (on screen and in the PDF), glossary definitions in English and Arabic, the mega-backdoor note, the will checks and the leaving-the-UAE checklist now state what your numbers show instead of telling you what to do with your money. The figures, thresholds and colours are unchanged.
v0.24.15
- AI narratives: the FIRE journey paragraph, Quick Insights, the monthly report, the year-end tax summary and the advisor report were often replaced by the standard summary, or failed to load, after our AI provider changed the model behind its default name. The model version is now fixed, and each feature sets how much the model reasons before it writes, so the written answer is no longer cut short.
- AI chat and advisor: ordinary questions could be refused with "The AI assistant is temporarily unavailable" because the safety check ran too slowly. It now runs on a faster model and, if one model is slow or unavailable, tries the next one. The whole check now finishes within 15 seconds. A question that cannot be checked in time is still refused.
- AI usage: some AI answers now set aside extra room for the model to reason, so while an answer is being written it can count for more of your daily AI allowance than before.
v0.24.14
- Automatic transaction categorisation no longer miscategorises a merchant name just because it contains a short keyword as a fragment of a longer word — for example a charity donation naming "Crescent" was being labelled a utility bill because it contains "sce".
v0.24.13
- Invest, Portfolio and Roadmap: BIV, BSV, BLV, IGLT, SHV and BIL saved as an ETF are now counted as bonds. They were counted with equity funds, so the Boglehead alignment score, the allocation drift and the bond share on Roadmap understated your bond holdings.
v0.24.12
- The Smart Insights card on Home now states facts only, such as your savings rate, how many months of expenses your emergency fund covers, and the share of your net worth in invested assets. It no longer suggests what to do with your money or grades your figures.
v0.24.11
- Properties, mortgages, rental income, cash and debt accounts, insurance policies, donations and joint goals now show each amount in its own currency with the converted figure underneath, the way Accounts, Net Worth, Goals and Portfolio already did. The converted figure shows the exchange rate used and its date.
- Crypto: the total value is now stated in your base currency instead of always in US dollars, and each wallet shows its US-dollar value with the converted figure underneath.
- Invest: an investment account saved without a currency is now labelled in your base currency, matching how it was already converted. It was labelled in US dollars.
- Advisor PDF: the scenario and projection charts are labelled in your base currency when the report has no monthly-contribution figure. They were labelled in US dollars.
v0.24.10
- The Smart Insights card on Home now works out "share of your net worth in invested assets" and "liabilities as a share of your total assets" from the same net worth every other screen shows. It previously left your portfolio holdings out and counted a stocks or crypto balance that your holdings already replace, so both percentages could differ from the rest of the app.
v0.24.9
- Cloud sync now follows your plan’s billing period. When a plan ends, syncing from a device stops within the same grace period the rest of the app uses, even if that device has not been reopened since. Your data stays on the device and in the cloud, and you can still download or delete it.
- A renewed plan whose renewal notice was delayed now restores cloud sync the next time the app opens, instead of waiting for the notice.
- The year-end tax summary and AI usage tracking now use the same plan check as the rest of the app, so a paused or ended plan is treated as the free plan there too.
v0.24.8
- A browser holding K25x data from before one-account-per-browser no longer asks “Is the data in this browser yours?” when this browser’s own records show it has only ever been used by the account signing in. The question still appears whenever any record points to a different account, or when nothing on the device says whose the data is.
v0.24.7
- Shared browsers: K25x now keeps one account per browser. If you sign in where another account’s data is saved, nothing opens until you remove that data from this device or sign out, and that data is never synced into your account.
- A browser holding K25x data from before this change, which K25x cannot match to an account, now asks whether the data is yours before opening it, instead of assuming. Nothing syncs until you answer.
- New “Log out and remove data from this device” option next to Log out, and a “Remove data from this device” control in Settings → Data Rights. Both ask first, remove everything K25x keeps in this browser and sign you out; your account and any cloud copy stay.
- Logging out, or being signed out when a session ends, now also clears the biometric unlock and locks the password vault, so the next person on the browser does not inherit an unlocked session. Your saved data stays for your return.
- The privacy page now describes the data-removal controls that exist, instead of a one-click wipe that did not.
v0.24.6
- Cloud sync: every synced item now has a size limit on the server, not just the settings blobs. One oversized record can no longer use up the shared daily database allowance that everyone’s sync depends on.
- Cloud sync: an item too large to sync is now left on your device and flagged as not synced, instead of blocking the rest of your data or retrying in the background indefinitely.
- Cloud sync: when the server refuses an upload, the app stops retrying on a timer and tries again on your next edit or the next time the app opens.
v0.24.5
- Plans: when a paid plan is past its renewal date, K25x now checks the plan status with the payment provider before continuing paid features, so an ended plan can no longer stay active by mistake. A renewed plan carries on without interruption, and a brief provider outage does not interrupt a current plan.
v0.24.4
- Bring-your-own-key: the Anthropic model list now offers Claude Opus 5.5 and Claude Sonnet 5 (the new default), and drops Claude Opus 4, which Anthropic retired in June and which would have failed every request. Anyone who had it selected is moved to the default automatically.
- Bring-your-own-key: requests to current Claude models no longer send a sampling setting those models reject, so they cannot fail on that.
v0.24.3
- Deleting your account now ends a paid plan properly: it is set to finish at the close of the period you have already paid for, so you are never charged again after deleting, and your Stripe profile is redacted once that period ends. Previously the plan could keep renewing.
- If K25x cannot reach Stripe to end your plan, the deletion is held and you are asked to try again, rather than deleting the account with the plan still open.
v0.24.2
- A brief hiccup fetching your subscription status no longer makes the app show the free plan: it keeps what it last knew and quietly retries.
- Internal: a successful payment whose Stripe event cannot be matched to a subscription is retried by Stripe instead of being marked as handled, and any billing event K25x cannot attribute now raises a Sentry alert instead of retrying silently for days.
v0.24.0
- Cloud Sync can no longer be jammed by a single record with a malformed id, and a corrupted rules, alerts or history record arriving from another device is rejected instead of applied.
- Internal: nine device-only settings (idle lock, browser unlock record, cloud-encryption opt-in, local-only mode and the privacy opt-outs) are now refused by the Firestore rules as well as by the app, and the test that mirrors the two lists can see all of them.
v0.23.99
- Internal: the pre-deploy checklist's Journey figure is updated to match how the app has sized the FIRE number since the September fix (on recorded expenses, with the stated target as the fallback), and that figure is now pinned by a test.
v0.23.98
- Sending your details to a will partner now asks you to confirm it is you (passkey or email code) first, so a stolen login session alone cannot send them.
- Partner referrals are limited to five a day per account, and K25x now keeps a record of exactly what you acknowledged on the consent screen, stored as a keyed hash of your typed name rather than the name itself.
v0.23.96
- If you already have an active plan, starting a new checkout is refused with a pointer to the billing portal instead of creating a second subscription and charging you twice.
- Starting a checkout can no longer overwrite a payment that landed moments earlier: the customer link is written on its own, and the check reads the live record rather than a cached copy.
- Internal: Stripe's webhook deliveries get their own generous rate-limit bucket at the edge so a renewal batch is never throttled ahead of signature verification.
v0.23.95
- Our automated browser tests now skip a set of recordings that were only ever used to make marketing videos, and reuse work from the previous build step instead of starting over. Checks on accessibility, sign-in and offline support are unchanged — the same things are still tested, just with less waiting.
v0.23.94
- Faster test runs in CI.
v0.23.93
- Will partner referrals now require a verified email address before anything is sent, so an account created with someone else's address cannot cause them to receive a referral email or be listed as the reply contact.
- A referral is only sent once a permanent record of the attempt has been written; if that record cannot be written, the referral is held and you are asked to try again rather than sent without a trace.
- The note you can add for the partner can no longer be formatted to look like part of the K25x cover message, and the confirmation email you receive now lists the asset and profile summary that was shared alongside your wizard answers.
- The partner note is capped at 200 characters everywhere, matching what the consent screen shows in full, and the currency field only accepts a three-letter currency code.
v0.23.92
- Uploaded receipts, bank statements and insurance policies are now handed to the AI clearly marked as your document rather than as instructions, the same way pasted text already was. If a document contains text trying to steer the extraction, the AI is asked to report it in its output instead of following it.
v0.23.91
- Internal: the automated test suite no longer re-runs on every merge to production, only on each pull request and once a week for the coverage report. Nothing about the checks that gate a release changes; this only stops paying for the same tests a second time.
v0.23.90
- Every server action now checks the shape of what it was sent before it does anything with it. A malformed request is turned away with a readable message instead of a minified React error, and it no longer spends part of your daily AI allowance or uses up the free plan's one-off advisor report on the way to being rejected.
- A build check now fails if a new server action is added without that check, so the protection cannot quietly lapse.
v0.23.89
- Push notifications (runway warnings, FX moves, the day-183 tax watch) could silently stop arriving after reloading the app, because the notification handler and the offline-caching worker were fighting over the same registration and only one could win. They are now one worker, so both always work together.
v0.23.88
- AI document uploads (bank/card statement PDF import, insurance-policy parsing) are now metered per page instead of a flat per-file estimate. A long statement now counts proportionally toward your daily AI limit rather than being under-priced the same as a single receipt photo.
v0.23.87
- A failed AI request no longer refunds its whole token reservation. It is now charged for the model calls it actually made, including calls that timed out, so repeating a failing import can no longer get around the daily AI limit.
- Every AI action now has a per-minute rate limit. Before this, only the /api routes had one. SMS and email imports also reserve tokens based on the size of what you send, so several large imports started at the same moment can no longer go over the daily limit together.
v0.23.86
- Auto-categorisation now only accepts a category from your own list. Anything else the AI returns is treated as "Other" and never remembered, and remembered categories are no longer shared between accounts.
- Text inside an imported SMS, e-mail or transaction description can no longer break out of the section the AI is told to treat as data.
v0.23.85
- Closed a CSV formula-injection gap (CWE-1236) in the VAT Tracker export, the Reports export, and the Settings → Audit Log export: a transaction description or category starting with =, +, -, or @ (e.g. from an imported bank statement, SMS, or email) could open in Excel/Sheets as a live, executable formula instead of plain text. All three now route through the same guarded CSV helper already used by the Transactions and Giving exports.
v0.23.84
- Added Firebase App Check (reCAPTCHA Enterprise) as defense-in-depth against scripted traffic hitting Firestore directly from the browser — inert until an env var is set. This is prep work only: merging it changes nothing in production. Turning it on is a separate founder action (docs/APP_CHECK_ROLLOUT.md).
v0.23.83
- When a bank sync was refused for being on its four-hour cooldown, the screen showed the raw error code sync_cooldown instead of an explanation. It now shows a plain sentence telling you when you can sync again, for both Plaid and Lean connections.
v0.23.82
- Security audit records now have a daily limit per account. Every signed-in account previously could write enough audit records in a day to use up most of the shared database allowance, which would have stopped cloud sync for everyone. Past the limit the request still works and the record is kept in the server logs instead. Account deletion, sign-out-everywhere, passkey changes and successful identity checks have a small reserved allowance of their own.
v0.23.81
- Bank sync (Plaid) now holds to one sync per account every four hours when a sync fails because the connection needs attention, such as a bank asking you to log in again. Reconnecting the bank still lets you sync straight away. A sync that fails on the Plaid or bank side can still be retried right away, up to twice per four hours.
v0.23.80
- Bank sync (Lean) now holds to one sync per account every four hours even when a sync fails. Previously a failed sync gave its slot back, and a request built to fail on purpose (an impossible date range or an unknown account) could repeat all day. Date ranges are now checked up front, failures caused by the request keep the four-hour wait, a bank-side outage still allows a couple of quick retries, and each user has a daily ceiling on sync attempts.
v0.23.79
- Fixed two MCP data-read bugs in the financial advisor's Claude Desktop integration. The user's profile (age, retirement age, jurisdiction) was read from a Firestore key nothing ever wrote to, so it was silently always empty. Separately, an item with end-to-end cloud encryption enabled was read as a zero-value item instead of being excluded, which could understate a reported total; encrypted items are now left out of every total and reported as an explicit count so the assistant can tell the user the figures are incomplete.
v0.23.78
- Hardened the unauthenticated login audit endpoint. It accepted a user id from the request body, which both chose its own rate-limit bucket (so rotating the id restored the allowance) and could steer where the row was written. Total unauthenticated audit writes are now capped per day, with anything past the cap logged instead of stored, and rows written this way are permanently marked as client-reported so they can never be mistaken for server-verified ones.
v0.23.77
- Security: an emailed verification code is no longer accepted for account deletion or bank connect when the address on the account is unverified — so a code sent to an address that was just swapped in cannot stand in for the check.
v0.23.76
- Settings › Active Sessions: a new "sign out everywhere and remove all credentials" action for when you think someone else has access. Signing out other sessions never removed credentials — an attacker's added passkey or MCP access token kept working afterwards. The new action deletes every passkey and revokes every MCP token as well, behind a separate confirmation that names exactly what will be destroyed and a second verification step.
v0.23.75
- Settings → Credentials: one list of every passkey and MCP token on your account, with created/last-used dates, a "Never used" / "New" flag, and a revoke button for each.
v0.23.74
- Adding or removing a passkey, creating an MCP desktop token, and saving or changing an AI provider key now ask you to confirm it is you (passkey or emailed code). No passkey yet? The emailed code works.
v0.23.73
- Two-factor sign-in: after a wrong email code, a 'Send a new code' button now sits right next to the error — no more backing out and re-requesting on the Touch ID / Face ID fallback screen.
v0.23.72
- Benchmarks: the net worth, income and home-ownership references are now labelled as US surveys, with the citation saying why (no UAE equivalent is published). A new card places your monthly income in the UAE's official wage bands.
v0.23.71
- One savings rate. Benchmarks, the advisor review and its health score, and the assistant now use the same savings rate the dashboard shows, with its basis named (typical month, or this month so far).
- Month-specific figures say which month: the monthly summary and the AI monthly report label their savings rate by month; the couples page labels its household rate.
v0.23.70
- Goals can be marked "Spent at the deadline". The roadmap and the scenario planner then take that money out of the projected pot in the deadline year, and financial independence is declared only once everything still planned to leave has been allowed for.
- Scenario planner: each scenario has its own list of one-offs, seeded from your spend goals and editable, so "what if we skip the car" is one row removed in scenario B.
- The roadmap chart and its years-to-FI figure are now one calculation, so the line and the headline cannot disagree; a one-off shows as a dip with its own tooltip.
v0.23.69
- Faster, cheaper responses for term lookups, statement and email import, and the simulator query box, with no change to what they produce.
v0.23.68
- If deleting your account cannot remove your cloud copy, you now stay signed in so you can try again. Previously the sign-in was removed first, which made the retry impossible.
v0.23.67
- Each monthly snapshot of your independence journey now records how your holdings were valued, and the journey report shows it. Where two snapshots were valued differently, the net-worth and years-to-independence changes are left blank rather than showing a difference that comes from the change in valuation.
v0.23.66
- Setting a password vault now asks for at least 12 characters with mixed case, or a digit and a symbol. Vaults you already created keep working with their current password.
v0.23.65
- AI assistant connections: a tool result that mentioned a fund or broker name returned an error instead of the result. It now returns normally with the name removed.
v0.23.64
- Every change to connected-bank tokens, AI provider keys, MCP access tokens and notification preferences now leaves an entry in your account audit trail.
- The service health probe now checks the rate-limiting cache with a live round-trip instead of trusting that it is configured.
v0.23.63
- Sample-data mode is now fully isolated from cloud sync: exploring the demo no longer pushes fabricated rows into a synced account, and leaving the demo clears it everywhere, on every device.
- Deleting your account now also revokes bank access at the provider, clears passkey index records, and anonymises feedback you submitted — erasure reaches the places the old sweep missed.
- Encrypted device-bound data (advisor memory, bank credentials) no longer syncs between devices, where it could not be decrypted and could overwrite good data.
- The roadmap, FIRE journey and diversification figures now price holdings the same way the Home net worth does, so the numbers agree across screens.
- Email hardening: all templates escape interpolated text, unsubscribe requires a confirmation click (mail scanners can no longer trigger it), and marketing emails carry one-click unsubscribe headers.
- The will partner-match consent screen now shows the exact account email that is shared and lists your typed name among the shared fields.
v0.23.62
- The India pension triage now checks whether your non-resident status is confirmed before producing a pathway — if you’re not certain, it points you at the official Income Tax Department source instead of guessing.
- The couples survivor-runway no longer counts joint-account money as immediately available — access after a death varies by bank, so joint funds show as unverified rather than spendable until confirmed.
v0.23.61
- US contribution limits shown in the tax-regime reference now come from a single verified source, so the retirement-account caps can no longer disagree between screens.
v0.23.60
- The Home screen now fits its whole summary — net worth, the day’s change, and your currency breakdown — on one screen without scrolling, and the redundant "Dashboard" title above it is gone.
v0.23.59
- Closed a gap where an AI assistant connected through the MCP interface could be handed back the exact provider names the regulatory filter had just removed.
v0.23.58
- When you ask the AI about your net worth, holdings quoted in another currency are now converted before being added up — previously a US-listed holding could be counted at a fraction of its value in an AED or GBP account.
v0.23.57
- A FIRE plan that reaches its target in exactly 100 years now shows the year instead of reporting the goal as unreachable.
- Hardened admin-page access checks and added a send limit to the welcome email endpoint.
- AI usage costs can no longer display as "NaN" for an unrecognised model name, and shorter Google AI keys are now scrubbed from error reports.
v0.23.56
- Hardened subscription billing updates: if a payment webhook is interrupted mid-processing, it is now retried and applied instead of being silently dropped.
- A subscription status update now reflects live billing state rather than a possibly-outdated snapshot, so a renewal that already succeeded cannot be reverted by a late-arriving notification.
v0.23.55
- Deleting a categorisation rule on one device now stays deleted everywhere — it could previously reappear after another device synced.
- Signing in on a device that was offline no longer discards items you added while offline; local and cloud entries are merged item by item.
- Fixed a first-sync case, for accounts whose data lived only in the cloud, where the next sync could empty the local copy.
v0.23.54
- The free-plan limit of one linked bank is now enforced on the server as well as in the app — closing a loophole that also protected us from per-connection provider fees.
- Currency-rate fetches on the server now time out and race both providers, so one hung provider can no longer stall money-math requests.
- Error reports now scrub credential-bearing web addresses (api_key, token and similar parameters) regardless of what the value looks like.
- The AI advisor now discloses how many of your holdings could not be priced (a missing exchange rate) instead of silently presenting an understated net worth as complete.
- The FIRE projection no longer says "never" when your savings rate is temporarily zero but your existing investments would compound to the target on their own.
- The public runway check now uses the exact UAE statutory gratuity formula (21 days per year for the first five years) instead of a rougher approximation that could overstate your safety margin.
- Hardened the brand-name redaction in AI answers against invisible-character and lookalike-letter evasions, including mid-stream.
v0.23.53
- The Setup Progress checklist now actually appears on the dashboard. It was hidden behind a customization toggle nobody had turned on — if you prefer it gone, hide it in dashboard customization and that choice sticks.
- Following the questionnaire invitation now scrolls Settings to the questionnaire card instead of leaving you at the top of the page.
v0.23.52
- Setup Progress now invites you to the optional behavioural questionnaire — twenty quick statements that shape how the AI advisor reads you. Until you answer, the advisor uses a neutral default persona; nothing is assumed on your behalf.
- The "finish setting up" prompt on AI screens now opens the snapshot wizard directly instead of dropping you on the dashboard to find it yourself.
v0.23.51
- Settings → Report an issue: download a diagnostic file — app version, the page you were on, and your recent in-app activity — built on your device and sent nowhere until you choose to share it. A clearly-labelled checkbox (off by default) can include your financial data so the exact numbers involved can be reproduced.
- For users who consent to analytics, usage events are now tied to a pseudonymous account id (and testers are tagged as testers), so a reported problem can be traced back through the exact screens that led to it. No amounts, no email, no personal data — the same rules as before.
v0.23.50
- While exploring sample data there is now one slim notice bar instead of two stacked ones — on a phone your net worth starts 88 pixels higher. “Make it mine” lives on that bar, and both ways out of the sample workspace now show the same what-will-be-cleared confirmation.
- Finishing the quick setup and choosing “Add your first account” now closes the setup dialog as you land on Accounts — it used to stay open on top of the page.
v0.23.49
- The guided tour’s popups now carry a small arrow pointing at the thing each step is talking about, so the highlighted element and the explanation read as one — not a floating box near a glowing ring.
v0.23.48
- Getting started is one clear path: the four-question setup leads, and “look around with sample data” or “import a statement” step back to quiet links underneath. Your result screen now links to the public methodology page — every number is one you can verify — and offers one obvious next step: add your first account.
v0.23.47
- The landing page now leads with what makes K25x different for UAE expats — end-of-service gratuity, UCITS vs US-domiciled funds, Zakat, 183-day residency and multi-currency net worth are named right under the headline, with a link to the public methodology page. Previously these lived below the comparison table.
v0.23.46
- The quick-setup wizard no longer fills in answers you never gave. The twenty behavioural questions stay empty until you answer them yourself, and the retirement age it estimates is now labelled as an estimate — in Settings and on the AI consent screen — until you set your own, at which point the label disappears everywhere.
- The AI consent screen is more precise about the questionnaire: if you have not answered it, it now says nothing is sent for it at all, rather than describing placeholder values.
v0.23.45
- Browsing the Assets and Money tabs no longer springs the full “More” navigation tree open in the sidebar. Those pages belong to their hub at the top of the screen; the long tail of routes now stays tucked away unless you open it — or arrive on a page that truly lives only there.
- The “exploring sample data” banner is now a single slim row on phones instead of stacking to two, so the first thing you see is your net worth, not the chrome above it.
v0.23.44
- Deleting your account now also removes the recovery copies the app keeps when stored data fails to load. Previously, if your profile had ever been set aside into such a recovery copy, its contents — age, retirement age, investment preference, tax rate and questionnaire answers — could remain on the device after a deletion the app reported as complete.
v0.23.43
- The Retirement Lab no longer freezes your portfolio value at the exchange rates it saw in the first instant of loading. Live rates usually arrive a moment later, and the Lab kept the earlier snapshot — permanently, across sessions — which could leave it tens of thousands apart from the Roadmap on the same accounts. Seeded values now follow the current rates; anything you typed yourself is never touched.
- The Lab’s assumptions note claimed your car was excluded from the seeded portfolio. It never was — only your home (and its mortgage) is excluded — and the note now says exactly that.
v0.23.42
- The behavioural questionnaire can now actually be answered — Settings → Behavioural questionnaire, twenty statements rated from strongly disagree to strongly agree. Your answers shape the AI advisor’s investor persona, which until now was always derived from neutral placeholder values.
- The AI consent screen now tells you which case you are in: if you have answered the questionnaire it says the scores are your ratings; if not, it still says plainly that placeholders are sent — and now points you to where the real questions live.
v0.23.41
- The Retirement Lab and scenario-planning now start from your recorded expenses, like the Roadmap — so all your planning tools open on the same number. Your stated spending target is still used when you have no expenses recorded yet, and the note under the figure says which one it was.
v0.23.40
- Import failures now say what actually went wrong. A statement too large for the AI tells you it is too large (and suggests fewer pages or CSV import), a rate limit says to wait a minute, a network problem says to check your connection. All of these previously collapsed into one generic "something went wrong" — the part of the app that could tell them apart could never see the real error.
- A statement that is too large no longer switches AI features off for five minutes — that pause is reserved for genuine service problems, since the fix for a too-large statement is simply to retry with a smaller one.
v0.23.39
- When an AI feature hits your daily usage limit, you are now told so. Previously that message never reached anyone — on any AI screen — and several screens showed an internal error code instead of an explanation. Affected the dictionary, chat, the advisor, the roadmap, receipt and statement imports, SMS and email imports, the year-end tax summary and the retirement simulator.
- The roadmap could not tell a usage limit apart from a network problem or a billing issue, so it always showed the same generic message. It now names the reason when it knows it.
v0.23.38
- Your mortgage and your automatic investment transfers are no longer counted as subscriptions. They recur every month, so the detector picked them up — which meant the roadmap could tell you to review your recurring charges to free up cash while counting your home loan and your investing in that total.
- Years to Financial Independence is shown as a whole number instead of one decimal place. The projection works in whole years, so the decimal was always ".0" — it implied a precision the calculation does not have.
v0.23.37
- The AI consent screen said the 20 behavioural scores it sends were ones you answered during setup. They were not — the app never asks those questions anywhere, and all twenty are set to a neutral middle value. The screen now says so plainly, and says the investor persona derived from them is a placeholder rather than a reading of you. It also now tells you when the retirement age being sent is an estimate the four-question setup worked out, rather than a target you chose. Because what you are consenting to has changed, you will be asked to confirm consent once more.
- The daily founder digest now reports whether the email actually went out as its own field, instead of leaving it to be inferred from whether an error was attached. A run that finishes but fails to deliver can no longer read as a fully successful one.
v0.23.36
- The AI dictionary showed a raw error code instead of a definition. Looking up any term now returns either the definition or a plain sentence explaining what went wrong, and an unavailable lookup is no longer remembered as though it were an answer.
- The Retirement Lab now says which spending figure it started from — your recorded expenses or your spending target. It can still differ from the figure on your roadmap, but you can now see why rather than being left with two numbers and no explanation. The note disappears once you type your own amount.
- The sample dataset counted the same salary, rent and bills twice — once as a recurring item and again as a transaction — which inflated the monthly savings and retirement figures shown to anyone exploring the app with demo data. Your own data was never affected.
v0.23.35
- The guided tour no longer opens itself on the wrong page, and moving through it no longer fills up your back button.
- The retirement wizard’s summary now comes from the same calculator as the rest of the app, so the number it shows matches the one on your plan.
- Percentages in multi-currency views are calculated against the converted amounts, and a price banner no longer appears when there is no price change to report.
v0.23.34
- The daily residency-tracking job now reads users in parallel and pages through them, so it finishes well inside its time limit as more people use the feature. Previously it could be cut off partway and would restart from the beginning the next day, meaning the same people at the end of the list were never reached.
- A temporary database error while checking your notification settings can no longer delete your 183-day tracking. It is now skipped and retried on the next run.
- Guide emails are sent several at a time rather than strictly one after another, so a large batch completes instead of being cut short partway through.
v0.23.33
- If an AI provider stalls, thirteen more features now give up and fall back instead of hanging until the server kills the request — including receipt scanning, PDF statement import, insurance-policy parsing and chat. Previously only five had that protection, so the rest could leave you on an error page with no explanation.
- Editing on two devices no longer loses one device’s work. If you added a categorisation rule on your phone and a different one on your laptop before either synced, whichever synced second replaced the other’s entire list. Both are now kept.
- Requests to outside services — price feeds, banks, email, AI providers — now give up after a set time instead of hanging. A single slow provider could previously tie up capacity for everyone.
- Your portfolio breakdown percentages now always add up to 100. An evenly split portfolio could show 33% / 33% / 33%, which reads as though something is missing when nothing is.
v0.23.32
- Your Financial Independence number now says which figure it was built from — your recorded expenses, or the yearly spending target you set. The roadmap already said this; the dashboard did not, so two screens could show different numbers with nothing explaining why.
v0.23.31
- Chat can no longer state a tax figure without a source. It was told to cite or decline, but nothing checked the answer before it reached you — the AI advisor has had that check for months and Chat had not. An uncited tax number is now replaced with a note to verify it, before any of it appears on screen.
v0.23.30
- Importing a Google Sheet now pulls it across in Excel format instead of CSV. Google’s CSV conversion quietly rounds numbers off after about eleven digits — in testing, 999,999.999999 came through as exactly 1,000,000 — and nothing in the file shows it happened. Everyday amounts with two decimal places were never affected, but the rounding is now impossible rather than merely unlikely.
v0.23.29
- Every email K25x sends about a guide now has a working unsubscribe link. The link had been included in those emails all along but pointed at a page that did not exist, so anyone who clicked it got an error and stayed subscribed. It works now, in one click, and cannot be triggered by anyone other than the recipient.
- Asking for a K25x guide now sends one email asking you to confirm your address, and nothing further until you do. Previously anyone could type any address into the form and that person would start receiving a multi-day series they never asked for. If the address is not yours, ignoring that one email is the end of it.
- The guide sign-up form no longer reveals whether an address is already on the list — every submission gets the same reply.
v0.23.28
- Rotating the key that protects your stored AI provider keys now genuinely rotates it. The old code accepted several key formats but only ever used the first 32 characters of them, so a rotation that changed anything after that point produced the identical protection key — the rotation looked successful while old data stayed readable under the old key. Only one unambiguous format is accepted now, and anything else is refused at startup with an explicit message rather than quietly reinterpreted.
v0.23.27
- A bank sync no longer loses its place when the balance lookup at the end fails. K25x pays per page of transactions it fetches, and the marker recording how far it got was only saved after that final lookup succeeded — so one hiccup meant the next sync re-fetched, and re-paid for, everything it had just downloaded. Balances are now optional to the sync; your place is always saved.
- When you bring your own AI key, the note saying which provider handled a request is now taken from the same decision that actually routed it. It was worked out twice independently, so in rare cases it could tell you your own key was used when the request had actually run on ours.
v0.23.26
- The assistant’s read-only view of your data was looking in the wrong place in the cloud and always coming up empty, so it quietly fell back to an older saved copy — which could be out of date, or missing entirely if you started using K25x recently. It now reads the same records everything else does.
v0.23.25
- Signing in with a passkey now reports a clear, specific reason if something behind the scenes fails after your fingerprint or face is accepted — previously any such hiccup surfaced as an unexplained error on the sign-in screen. And if the anti-cloning counter can’t be saved, sign-in is refused rather than completed, because that counter is the protection.
- Two records — your 183-day residency sync and the notification that fires when you approach the threshold — are now written before the request finishes instead of in the background, so they can’t be lost when the server shuts the request down.
- The email-capture form on public pages no longer shows an error when a background lookup briefly fails; your address is captured either way.
v0.23.24
- The built-in glossary no longer answers a question you didn’t ask. Asking about “fire insurance” returned the definition of FIRE (financial independence), and a single letter matched whatever term happened to contain it. It now answers only genuine variations of a term it knows — spelling, spacing, plurals — and otherwise hands the question to the assistant, which can ask what you meant.
- If you bring your own AI key, failed provider calls are now recorded in your audit log alongside successful ones, and the record is written before the response is returned rather than in the background. Previously a refused or failed call left no entry at all, so “nothing in the log” could mean either “nothing happened” or “something happened and wasn’t recorded”.
- Signing out your other devices now reads the device list after the server confirms, so a device that checked in while the request was in flight is reflected correctly. This only ever affected the list you see — the sign-out itself was always applied on the server.
- The daily founder digest no longer fails outright when one of the figures behind it can’t be read. It now sends anyway, marked “partial”, naming exactly which section is missing — and a section it couldn’t read is shown as unavailable rather than as a zero, so a failed read can never be mistaken for a quiet day.
- Crypto wallet addresses are now checked against the shape of the chain you picked before K25x calls the block explorer, so a typo or a mismatched address is caught immediately with a clear message instead of an unexplained lookup failure.
- Imported transactions get their internal identifiers from a cryptographic random source, removing any chance of two rows in a large import colliding on the same second.
v0.23.23
- If the AI provider stops responding mid-request, the year-end tax summary and the roadmap now give up after 18 seconds and fall back to the figures K25x calculates itself. Previously the request simply waited until the server killed it, so you got an empty error page instead of the summary — even though the fallback that would have answered you was sitting right there.
- Fixed the year-end tax summary being cut short for Pro and Family members. Its length allowance is meant to scale with your plan, but the plan was never reaching the step that sets it, so every member got the Free allowance — enough to truncate a long summary back to the basic version with no indication anything had been dropped.
v0.23.22
- The three-specialist advisor no longer shows a percentage next to each specialist. That number was the model rating its own confidence — not a measure of how right it is — and when a specialist’s reply came back unreadable the app filled in a stand-in “60%” that looked exactly like a real one. You now see a plainly-labelled self-rated band, and nothing at all when the specialist didn’t state one.
- If you bring your own Google AI key, it is now sent in a request header instead of in the web address. Addresses are the part of a request that gets written to error-tracking and server logs by default; headers are not. Your key never changes and nothing about the feature changes — it simply stops travelling somewhere it could be recorded.
v0.23.21
- Closed a gap in the bank-sync cost limit. K25x allows one sync per connected account every four hours because each one is billed by the bank-data provider — but the check and the timestamp that enforces it were separated by the sync itself, so two requests arriving at the same moment could both pass the check and both run. The limit is now claimed up front in a single atomic step, and handed straight back if the sync fails, so a failed attempt still doesn’t cost you the four-hour window.
v0.23.20
- Connecting a bank can no longer leave a half-finished connection behind. After your bank approved the link, K25x fetched your account names and institution details — and if that follow-up step failed (a dropped connection, a bad response), the whole link was thrown away even though the connection had already been created on the bank side. You had to start over. Now the connection is saved regardless, with the names filled in on the next sync.
v0.23.19
- The advisor no longer states retirement-contribution figures it cannot know. It was estimating how much you had contributed to a 401(k) this year by dividing your balance by ten — and reporting the result, plus an “unused room” total built on it, as fact. Your account balance simply doesn’t say what you contributed, so those figures now read as unknown; the published annual limits are still shown.
- Fixed a slow memory leak in the safety check that runs before every AI request — its cache had no size limit and never dropped expired entries, so a long-running server accumulated one entry per unique question indefinitely.
- Hardened three places where text that can come from your own data was passed to the AI without being clearly marked as data. Roadmap gap descriptions are now checked by the regulatory firewall and fenced (previously they skipped the check entirely and went into the prompt raw), the multi-agent advisor fences the specialists’ opinions before its final synthesis step, and a goal name containing a line break can no longer forge an extra “fact” line in the on-device assistant’s prompt. Regulatory-block audit entries are now attributed to the right account instead of “anonymous”.
v0.23.18
- The advisor no longer blanks out perfectly good sentences. Its tax-claim check matched keywords as substrings, so words like “conservative” (contains “vat”), “advisable” (“isa”) or “aspirational” (“ira”) tripped it and the whole paragraph was replaced with “I don’t have a verified source.” It now matches whole words, and also correctly catches tax thresholds written without commas (e.g. “£12570”) so those still get a citation check.
- Security hardening: the step-up security-token secret now recognises a production deploy even if one environment flag is misconfigured, closing a latent path where a fallback development secret could have been used in production. Plus CI supply-chain pins (the security scanners are pinned to fixed versions instead of a floating branch/latest).
v0.23.17
- The advisor report’s “required monthly savings” figure now uses the same net worth the rest of the report shows. It was computed from a raw assets-minus-liabilities total that left out your investment holdings, so for anyone with a portfolio it disagreed with the net worth printed a few lines up. Now both use the one canonical figure — portfolio value included, superseded lump removed.
v0.23.16
- Every figure on the year-end tax summary is now computed by the app, never by the AI. Previously only the headline deductible total was app-computed while the per-line amounts were written by the model — on a page you might carry into a filing. Now the AI can only write the wording; all the numbers come from your own transactions, so a wrong estimate (or a manipulated prompt) can no longer put a fabricated figure in front of you.
- On-device AI mode now keeps your data on-device for the year-end tax summary too. Previously, choosing on-device (“device”) AI and generating this summary still sent your full transaction list, donation recipients and holdings to the cloud — while the page promised the opposite. Now the summary is built entirely on your device from your own numbers; the cloud is used only if you pick cloud AI.
v0.23.15
- Turning Local-only mode off now puts your AI mode back where it was (F-91). The preset switches AI to Local when it engages; it now undoes that one change when it disengages — so on the hosted app you’re not left stranded in a mode with no model behind it. A mode you picked yourself while Local-only was on is kept, and the privacy opt-outs (analytics, bank connections, cloud sync) still stay off until you re-enable each one, exactly as promised.
v0.23.14
- Account deletion’s identity check works again with a passkey (F-92). The security challenge before deletion now names your own enrolled passkeys instead of asking the device to guess — the old challenge could come back empty-handed and the check could never succeed, which made deletion unreachable. An account with no passkey enrolled is now told so plainly and pointed to the email-code option, instead of being launched into a check that must fail.
- When our email delivery is failing, the deletion flow says so honestly — “retrying won’t help” — and points to the factor that works and to support, instead of stranding you mid-deletion. The root cause of the failures themselves (the sending domain was never verified with our email provider — the same cause behind every silently missing K25x email to date) is a provider-side setup being completed separately; this entry will be corrected if that account is wrong.
v0.23.13
- The educational explainer blocks — “what is FIRE”, “how the cashflow engine works”, “how the AI advisor works”, and the rest across some twenty screens — now introduce themselves once and then get out of the way. The first time you visit a screen its explainer shows in full, exactly as before; from then on it folds to a one-line “What is this?” you can reopen any time. Rewritten explainer copy counts as new and shows itself once more. Regulatory notices are untouched — they are required to stay visible, and do.
v0.23.12
- The AI-quota message no longer tells you to “switch to Local AI mode” — on the hosted app that mode has no model behind it and the suggestion dead-ended in an error page. The message now says the true thing: upgrade for a higher limit, and Local mode is unmetered when you run K25x on your own machine. The settings caption got the same correction.
- Correction to the v0.23.2 entry (a dated correction, never a silent edit): the “not financial advice” notices were genuinely added to the Arabic pages in the codebase, but those pages are not publicly reachable — the Arabic locale is deliberately deferred for launch, and every /ar address currently redirects to its English equivalent (a temporary, reversible redirect). The notices are in place for the day Arabic ships; until then the claim can’t be seen live, and this entry says so.
- The floating + button rides a little higher on phones — clear of the home-indicator area and of the last content row, which it touched on narrow screens (seen on Plan at 400px). Pages gained matching bottom breathing room so everything can scroll fully past it. Desktop position unchanged.
v0.23.11
- Turning off biometric unlock can no longer lock you out of your account. If the biometric you’re removing was also your two-factor method, two-factor is retired with it — and the app says so — instead of leaving sign-in demanding a credential that no longer exists, with a saved recovery code as the only way back in. An enrollment belonging to a different account on the same browser is never touched; you’re warned that that account will need a recovery code or an emailed code.
- Disabling two-factor no longer looks like a mystery sign-out. Removing a sign-in factor makes Firebase revoke your session for security — the app now expects that, records the real reason in your security history instead of “session lost”, and tells you up front that you may need to sign in again.
- The Touch ID / Face ID sign-in check now offers “Email me a code instead” — so a broken or missing biometric no longer leaves saved recovery codes as your only way in. The emailed code is verified server-side, exactly like the email two-factor method.
v0.23.10
- The quick bar is now Home · Plan · Money · Assets · Advisor — your plan one click from anywhere, and the three hubs entered at their first tab. The keyboard chords follow: g h, g p, g m, g a, g v.
- Money is one place: Transactions, Budget, Subscriptions, Rules, Alerts, and FX share a tab strip, the same way Assets does. FX left the quick bar and lives as a Money tab; its page is unchanged.
- One AI surface. Advisor and Chat sit behind a single Advisor entry with a two-tab strip — no more guessing which door is which. Chat is unchanged and its address still works.
- The three couple-shaped pages — Couples, the “if one of us dies” diagnostic, and Family & college — are one “Couples & family” entry with three tabs. Every page keeps its own address.
v0.23.9
- Your assets are one place now. Accounts, Net worth, Portfolio, Invest, Properties, and Crypto share a tab strip at the top of each page, so moving between views of “what do I own?” is one click instead of a trip through the menu. Every page keeps its own address — bookmarks and deep links all still work — and /assets is the hub’s front door, opening on Accounts.
v0.23.8
- The exit hub’s gratuity calculator now pre-fills your monthly salary from the AED salary stream you already recorded, labeled as pre-filled and fully editable — gratuity is computed from your basic salary, so if your recorded figure includes allowances, correct it in place. A value you typed yourself always wins, and the calculator never converts a foreign-currency stream or guesses from other income: no AED salary recorded means the field simply stays empty.
- Leaving the UAE now states its destination instead of implying it. A UK-nationality profile sees “Destination: United Kingdom — matched from the nationality on your profile”; any other profile is told plainly that the arrival checklists are UK-specific, that the UK is the only destination with a full checklist in this version, and that more destinations are on the roadmap — with their own home country named so it’s clear the page read the profile.
v0.23.7
- Recurring streams now materialise themselves. Generation runs automatically when the app loads AND the moment you add or edit a stream — the “Run recurring” button is gone because the job it did no longer exists. For months that were left empty before this existed, the cash-flow chart now says exactly why they show zero (“your recurring streams were never generated for those months — not because the data was lost”) and offers a one-click “Generate for this period” that fills them from your streams. Generating twice never duplicates a row.
- The transactions toolbar is two actions instead of eight: Add Transaction, and an Import menu holding guided import, CSV with column mapping, PDF statements, the Financial Planner workbook, and receipt scanning. Apply rules moved to the ⋯ menu. Every path lands in the same dialog it always did, with the same plan gating — the change is prominence, not capability.
- The roadmap now opens onto the tools that answer “what if?”: Test your assumptions (Retirement Lab), Run the full simulation (Monte Carlo), and Update your inputs (the four-question snapshot). Each of those tools carries a “Back to your roadmap” link, so the plan and the instruments form one path instead of four silos.
- The Budget page now says it plainly when this month’s spend is entirely your recurring streams — in that state every difference reads 0.00 by construction, which is arithmetic, not a verdict, and the page now explains that and points you at logging one-off spending. Creating a recurring stream with a name you already use now asks what you meant: merge the amounts into the existing stream (offered only when currency and frequency match) or keep both — previously the second stream was accepted silently and “Typical” quietly summed the pair.
v0.23.6
- The unlock record’s freshness stamp now moves with every unlock and activity update, and is removed with the record. It had been frozen since the record was (correctly) excluded from cloud sync, which let any device still running an older cached version of the app overwrite this browser’s unlock — the reload re-lock QA reproduced. This build’s own start-up check reads freshness from inside the record and never from the stamp. The idle lock is confirmed opt-in: off for new accounts until enabled in Settings, and enrolling biometrics does not switch it on; anyone who enabled it keeps it.
- The financial-snapshot wizard’s answer options are selectable again on accounts with existing data (question 2 could not be selected at all). The option rows now activate the control they contain rather than looking one up by id — a transient duplicate of the dialog in the page could give that id two owners, sending every click to an invisible copy. Stored answers now come pre-selected and stay changeable; saving still only fills in what you never answered elsewhere, so Settings-made choices survive re-running the wizard.
- General questions to the assistant (“What is the 4% rule?”) no longer fail after a long wait while account questions succeed. The assistant now answers definitional questions directly instead of searching your data for them, and if a reply dies before its first word the server makes one more attempt without data tools before giving up. Failures are no longer invisible: every reply carries a request id, and failed ones report a cause — so support can find exactly what went wrong.
v0.23.5
- Published the measured accessibility result for the AI Advisor form: every visible control on it has a proper name for screen readers. Three controls elsewhere that genuinely lacked one were fixed in the previous release.
v0.23.4
- Chart value labels no longer get cut off. Six money charts — refinance break-even, cash-flow forecast, debt payoff, scenario planning, the RMD tool and the advisor report — were formatting their vertical axis at full precision ("$1,500,000.00") in a space only wide enough for about seven characters, so the labels clipped to fragments like "000.00". They now read as "$600K" and fit.
v0.23.3
- New accounts now default to UCITS (Irish-domiciled) funds rather than US-domiciled ones. For a non-US person — which most UAE residents are — US-domiciled funds carry 30% dividend withholding and US estate-tax exposure, which is what the domicile guide has always explained; the default now matches that guidance. You can still choose US-domiciled or Sharia-compliant in Settings, and a choice you have already made is never changed.
- The AI advisor now writes in your actual base currency. It previously guessed the currency from your fund preference, which could describe a Dubai household’s finances in pounds.
v0.23.2
- Reviewed every public page and corrected wording that read as personal financial advice rather than information. The runway calculator no longer names particular bank accounts or tells you what to hold; the worked examples now describe what the numbers modelled rather than money "saved"; and the guides describe trade-offs instead of ranking products for you.
- Corrected several factual claims on the public pages: what is actually encrypted (your two-factor secret and AI advisor memory, not the whole book), which AI providers can process a request, that bank connections are not live yet, and the current default model names.
- Added the "not financial advice" notice to the calculators, glossary and comparison pages that only carried it in the site footer — including the Arabic versions, which had none — and a test that keeps every money-related public page covered.
v0.23.1
- The Independence journey now has an "Update this month’s snapshot" action. Your monthly points are normally recorded once per calendar month, so a change to what a snapshot captures only shows up when the month rolls over — this lets you bring the current month’s point onto your latest figures straight away. Earlier months are never altered, and your next automatic snapshot is unaffected.
v0.23.0
- Your biometric unlock now stays on your device. The record that keeps you unlocked for a browser session was being synced to the cloud along with your data — which both sent it off the device and let a record from another session overwrite it, locking you out again for no visible reason. It is now treated as device-only security state, exactly like your biometric credential already was.
- Unlocking in one tab now unlocks the tabs you already had open, instead of only tabs opened afterwards.
- A month you spent away from the app can no longer be permanently skipped when your recurring income and expenses are generated. The marker recording how far each device had got was shared between devices, so one device could skip past months another had never filled in.
- The estate checklist now flags the US medical-records release (HIPAA) as probably not applying to you if you are not a US person — the same treatment the other US-specific tools already give.
- Your monthly independence snapshots now record whether your primary residence was counted toward the assets your plan draws from, so a snapshot can be read back later without guessing which basis produced it. The Roadmap also now states whether its FIRE number came from your recorded expenses or your stated spending target.
- Three form controls that screen readers could not announce — a commitment checkbox, the expert-team question box, and the consent name field — now have proper labels.
v0.22.3
- A chat reply can no longer fail in silence. If the AI service returns nothing at all, you now get a plain message saying so instead of your question sitting there with nothing after it — and the same is true when a reply fails for any other reason.
- A natural-language question that cannot be answered now says so in the panel, next to the question you asked, instead of quietly returning you to the suggestion list — which looked like the answer had been thrown away.
- The estate page for couples now picks up the partner name you recorded in household mode. The previous fix read a different store, so a recorded name still showed as “your partner”.
v0.22.2
- Every planning screen now reads the same "monthly savings" figure, computed one way: your recurring streams plus last month’s genuine one-offs — and, for a brand-new account whose only data is the current month, that month’s actual transactions, clearly labelled "This month so far". Previously the dashboard tile, the Roadmap, and the Retirement Lab each computed this independently: a new user who had just entered real income and expenses could see “0.0%” on one card, 66.7% on the next, a $1,500 placeholder in the Lab, and a Roadmap declaring “Not on track” — all at once.
- When there is no income to measure against, savings-rate figures now show a dash instead of a misleading “0.0%”.
v0.22.1
- Restoring a backup now always ends sample-data mode, and "Clear sample data" asks for confirmation first — listing exactly what is currently loaded. Previously, restoring while the sample workspace was open could leave the sample banner over your real restored data, and its clear button removed that data on a single click with no warning.
- Adding an asset or liability without picking an owner no longer fails with a technical error message — "no owner picked" is a valid state, as the Couples pages have always treated it.
- The financial-snapshot wizard no longer overwrites answers you have already given elsewhere. A retirement age you set in Settings, your investment preference, and your saved assumptions all survive re-running it; the wizard only fills in what you have never answered.
v0.22.0
- The FX view now splits every holding’s gain into two legs: what the asset did in its own currency, and what the currency itself did against your base. A position can be up in dollars and down in dirhams — now you can see which effect is which.
- Two-factor authentication and the biometric lock now belong to the account that set them up. Signing in with a different account on the same browser previously inherited the first account’s security prompts — including a biometric check that could never succeed for the second account. A different account now gets a plain explanation and a sign-out path instead.
- The setup checklist’s "Complete your profile" step and the Roadmap’s unlock message now open the financial-snapshot wizard directly. Both previously pointed back at the dashboard — the page you were already on.
- The "Watch the 45-second tour" button no longer appears when no tour video is available — clicking it used to open an empty player. The product tour also returns you to the dashboard before starting (its steps describe dashboard widgets), and its closing step no longer claims you are looking at sample numbers when you aren’t.
- New accounts no longer start with every past release marked unread in "What’s new" — only releases from after you arrive are news. The two-factor settings card now correctly describes 2FA as optional and recommended, and one remaining unlabeled field in the AI Advisor form is now announced properly to screen readers.
v0.21.1
- Chat and the quick financial answers (natural-language questions, categorisation) now automatically retry on a second AI provider when the first one is briefly overloaded or unavailable, instead of failing the whole request. Longer streamed replies also no longer get cut off by a server time limit.
- Exchange rates now genuinely refresh during a long session. The hourly refresh added previously was being answered from a cache that outlived it, so the "as of" time could stay stuck for hours; the cache now expires before each refresh.
- The Retirement Lab’s shared assumptions now reach the journey headline on the same page. Editing the portfolio value or spending in the assumptions card previously updated the charts but not the verdict underneath them, which could keep declaring financial independence reached against numbers you had already changed.
- The suggestion chips under a natural-language question now show their answer instead of discarding it, and asking a second question no longer clears the previous result without rendering the new one.
- The estate page for couples now proposes your recorded partner’s name automatically instead of a blank label; a name you typed yourself still wins.
- The Retirement Lab and Envelope Budget captions now state exactly what was computed — including whether your primary residence is excluded, and how many months of data an average is actually based on.
v0.21.0
- Every screen that models your financial independence — the Independence journey, the Roadmap, the Retirement Lab, and the dashboard — now computes "the assets your plan draws from" the same way: your net worth minus the equity in any home marked Primary Residence (rental and investment properties still count). Previously each screen had its own version of this rule, and they could disagree by millions on the same data. The Accounts banner and the methodology page state the one rule.
- The Retirement Lab’s stress-test tab could tell you that you had already reached your FIRE number when you were still slightly short of it — it treated "every modelled path gets there within about half a year" as "you are there today". It now compares today’s portfolio against the same target the simulation actually runs with.
- If the AI Advisor form had a problem — for example a required field that was hidden inside a collapsed section — pressing the generate button previously did nothing at all, with no message. It now tells you exactly which fields need attention, opens the sections containing them, and takes you to the first one.
- Long Chat replies used to stop abruptly mid-sentence with no indication anything was cut. Replies now have far more room, and on the rare occasion one is still cut short, it says so and invites you to ask for the rest. Chat also renders formatting properly (bold, lists) instead of showing raw asterisks, and tax figures are now framed to the current date with the same cite-or-refuse standard the Advisor uses.
- Importing a planner file now flags any row whose name matches something you already have — even when the amounts differ — showing both amounts so you can decide. Previously a row with the same name but a different balance could slip through and quietly double-count an account or an income stream.
- The Zakat calculator’s reserve metal prices (used when a live price is unavailable) had fallen far behind the market, which understated the Nisab threshold by roughly half. They now reflect verified current prices, and the calculator states when it is using a reserve price rather than a live one.
- The Benchmarks page now shows the survey it cites: net-worth brackets are the Federal Reserve’s 2022 Survey of Consumer Finances and income brackets are 2023 Census data, each labelled with its own vintage. FX rates also refresh themselves during long sessions instead of only at sign-in.
- Security housekeeping: all high-severity advisories in the app’s production dependencies have been resolved, and the biometric lock now records diagnostic detail whenever it locks unexpectedly, so a re-lock that shouldn’t have happened can be traced.
v0.20.0
- If you had recorded beneficiaries on the Estate page and then generated the lawyer-facing estate summary, it could show “None recorded” for beneficiaries — even though you had entered them. Two separate places were tracking beneficiary designations without either one knowing about the other. There is now one record, and anything you had already entered has been carried across automatically.
- The sample dataset used to explore the app with realistic numbers now fills in every section — including Insurance, Beneficiaries, Giving, Family, Pensions, Alerts, and Rules — across six currencies. Previously several sections had no sample data, so there was no way to see what they looked like before entering your own.
v0.19.0
- The Invest page now shows a balance for investment accounts that don’t have individual holdings recorded, instead of “No holdings yet” — which it previously showed even when the account held real money.
- VAT treatment can now be set per category — standard rate, zero-rated, or exempt — for your own expenses, rather than one flat rate applied to everything. Every category still defaults to the standard rate until you change it, so nothing in your existing totals changes unless you set it yourself.
- Biometric unlock now stays unlocked across tabs and after reopening the app, for as long as your idle-timeout window allows. Previously it reset the moment you opened a new tab, so switching tabs meant unlocking all over again. It still locks after your device has been idle, and after the browser fully restarts.
- Signed-in sessions older than 30 days are now retired automatically (previously 90), and you can remove a single session yourself from the list instead of only revoking every session at once.
v0.18.0
- The VAT export is now labelled “VAT estimate” rather than “VAT return” — it was never a submission-ready return, and the old name could be read as one.
v0.17.0
- Adding an asset or liability from inside the AI Advisor no longer crashes the page.
- When the shared price service can’t refresh, the app now says so instead of quietly reporting success — previously a failed price refresh looked identical to “not fetched yet,” and gain/loss figures could get stuck reading zero.
- Chat and the AI Advisor now say plainly when on-device AI mode can’t run inside the hosted app, instead of reporting it as “not reachable at localhost” — wording that read like a fault on your own device rather than a mode this app can’t offer online.
- The Estate page’s beneficiary checklist now correctly recognises the account types this app’s users actually hold — pensions, GIAs, and similar accounts. It previously matched only against US-style account types and could show no eligible accounts even when several existed.
- Beneficiary guidance now names the account types and institutions relevant outside the US, rather than 401(k)/IRA-style examples, and the claim that naming a beneficiary “overrides your will” has been softened to reflect that this depends on your jurisdiction.
- An ISIN (the code identifying a specific investment) is now checked for a valid format when entered, rather than accepted as any 12-character string.
- The list of countries you can record as “where you’ve worked” for pensions no longer reuses the will-drafting jurisdiction list — it’s now a plain, worldwide country list.
- Accounts — including ones brought in through a planner import — can now be edited and deleted directly from the Accounts page. Previously the only place to fix or remove one was the Net Worth page.
v0.16.0
- Cloud sync was silently rejecting part of your profile — including every FIRE planning assumption — so it never reached your cloud copy, even though sync otherwise looked like it was working normally. If you were relying on cloud sync as a backup, your profile was not among the data actually being backed up until this was fixed. The underlying sync rules are now deployed and checked automatically as part of every release, so a gap like this can’t go unnoticed again.
- Anyone whose investment preference was set to UCITS or Sharia-compliant could not save Settings at all — every attempt failed with no indication of what was wrong. This is fixed for both options.
- Net worth benchmarks previously compared your net worth, converted into your base currency, directly against wealth brackets stated in US dollars — inflating or deflating your percentile for anyone not on a US-dollar base. The comparison is now currency-consistent.
- The FIRE target behind your Roadmap number previously came from a fixed figure set once during onboarding, with no way to edit it afterward. It now tracks your actual monthly expenses, the same figure used everywhere else in the app.
- Saving in twelve places across the app — including Insurance, Alerts, Remittance, Family, Giving, Couples, and Estate — now tells you which field needs attention when a save doesn’t go through. Previously nothing happened and no message appeared, so a failed save looked identical to a successful one.
- Insurance, Giving, Family, joint Couples goals, and Estate digital assets and emergency contacts can now be edited in place. Previously the only way to correct one of these was to delete it and re-enter it from scratch.
v0.15.0
- Google sign-in on mobile is fixed. Three separate issues were compounding: the sign-in page could fail to load at all, a saved passkey could be rejected even when it was the correct one, and a signed-in user landing back on the login page saw it loop instead of continuing through. All three are corrected — sign-in should now be a single tap that lands you on your dashboard and keeps you there.
- The “A new version is ready” banner’s Refresh button now actually reloads the app. It previously did nothing when clicked.
- Gross rental yield is now calculated using only the value of property that actually produces rental income, rather than dividing by the value of all property you hold — which understated the yield by roughly half for anyone with a mix of rental and non-rental property.
v0.14.0
- Importing a PDF statement now shows a review step before anything is saved — the extracted transactions appear for you to check, edit, or remove, matching the CSV guided import. Cancelling adds nothing to your data.
- Large multi-page PDF statements that were too big to parse in one pass now import reliably — the statement is split on line boundaries and parsed in pieces.
- Monthly reports render formatted on screen instead of showing raw markdown characters.
- The AI advisor’s memory no longer accumulates duplicate or stale facts — near-identical facts are collapsed into one, and a superseded volatile figure (such as an out-of-date savings rate) is dropped rather than left to contradict the current one.
- Recent transactions on the dashboard show each amount in its own currency instead of relabelling it as your base currency — a £100 charge no longer reads as “$100”.
- Exporting VAT no longer crashes when a transaction has no category.
- The net-worth composition donut no longer blanks out when a holding is in a currency without an available rate.
- The dashboard’s anomaly and cashflow cards now show a clear “unavailable” state when their data cannot load, instead of a false “all caught up” or an endless loading skeleton.
- On-device AI (the fully in-browser WebGPU mode) now labels itself as on-device instead of showing the cloud provider’s name — the privacy signal matches what actually runs.
- A render error on one screen now shows a recoverable message with a retry inside the app, instead of dropping you out of the whole app. Error screens no longer surface raw internal error text.
- When the shared AI model is rate-limited or busy, AI insights and the advisor no longer wait out a provider backoff of roughly 30 seconds inside the request — they stop within a bounded timeout and show a clear “unavailable — try again” state.
v0.13.0
- A redesigned Home: net worth in your reporting currency with a 30-day change and one factual attribution line, a five-chip KPI strip (period change, FX impact, market impact, cash and invested share), and a composition-by-currency board that expands to item level. On a 1440×900 desktop the primary view fits without scrolling. The FX-versus-market split and per-currency sparklines build from snapshots recorded from today forward, showing “—” until enough history exists.
- The primary navigation is now five destinations: Home, Accounts, Budget, Invest, FX. Everything else moved under “More” — nothing was removed, and every page keeps its address.
- New Accounts destination: a dense, sortable table of your assets and liabilities — account, type, currency, native amount, ≈ reporting conversion, 30-day change, and trend; two-line cards on mobile. Per-account change and trend accrue from today forward and show “—” until at least two data points exist.
- New FX destination: every currency you hold, paired against your reporting currency — the current cross-rate, recent change, a sparkline, your held exposure, and a factual line on how currency moves changed your net worth. Rate history accrues one point per day of app use, forward-only: change figures and sparklines appear once at least two days are recorded, and are never backfilled. Pegged pairs (AED and SAR to USD) carry a quiet “pegged” badge.
- Budget is now a neutral current-month grid: Category, Spent, Typical, and a signed difference. “Typical” is the set budget converted to a monthly figure where one exists, otherwise the median of the last three months with data — never fabricated, “—” until enough months exist. Over or under is stated as a plain fact, not colored as an alarm.
- New Invest destination: a display-only read of the holdings managed in Portfolio, with a “Boglehead alignment” figure (0–100) — a measurement of how the current mix compares to an illustrative target allocation, with a full “How is this computed?” disclosure. Allocation drift is shown neutrally, there are no trade or rebalance controls, and the page carries a persistent informational disclaimer.
- Reporting currency: a display currency independent of your base. Every money surface shows the native amount with its ≈ conversion alongside, and a tooltip states the rate used and when it was fetched. Egyptian pound (EGP) joins the currency list, and onboarding now asks for a base currency up front.
- Desktop power layer: Cmd/Ctrl+K opens the command palette (five destinations, reporting currency, jump to an account); “g” then h / a / b / i / f jumps between destinations; right-clicking an amount offers copy and view-history actions; hovering an FX figure shows the rate and its as-of time — an indicative fallback rate is never presented as live. Mobile is unchanged.
- One net worth everywhere. Dashboard, milestones, couples, benchmarks, projections, and the AI advisor all read the same canonical figure — portfolio market value included, superseded lump entries excluded. Six surfaces previously computed it independently and could disagree. The dense-view tile that excludes home equity is now labeled “Liquid net worth”.
- Bond ETFs count as bonds. Funds recorded under the ETF type (AGGG, BND, SGOV, VAGE, the SPDR Portfolio bond series, and more, including exchange-suffixed listings) now land in the bond allocation of the diversification measurement instead of reading as 0% bonds.
- The advisor’s Monte Carlo projection starts from the same canonical net worth its report states — portfolio value included, superseded entries no longer double-counted. The projection remains a set of probabilistic ranges, not a prediction.
- Chart honesty: the net-worth trend axis uses compact labels that no longer clip, and its legend reads “Total assets” / “Net worth” instead of raw data keys. FX change labels state the true span when daily data is sparse (“+0.42% (5d)”) rather than implying a 24-hour move.
- Product analytics on the new surfaces record only a route name, a keyboard chord, or a three-letter currency code — never amounts, balances, or personal data — and only when analytics consent is on.
- All new motion completes within 400ms and is disabled when the system reduced-motion preference is set.
v0.12.0
- Net worth no longer double-counts crypto that was recorded both as a manual asset and as a portfolio holding — the two now reconcile to one figure, the way stocks and ETFs already did. If you tracked crypto both ways, your total corrects to the accurate, non-duplicated amount.
- Amounts now follow each currency’s own convention: zero-decimal currencies like Japanese yen show as whole numbers (¥1,000, not ¥1,000.00), and three-decimal Gulf currencies (BHD, KWD, OMR) show their full precision.
- The net-worth breakdown (“what drove your change”) no longer invents a gain or loss after you switch base currency. Snapshots recorded in a different currency are set aside instead of subtracted as if they matched the new one.
- VAT tracker reads descriptions like “incl VAT 5%” and “20% off, incl VAT” correctly — a rate is no longer captured as a fixed amount, and a non-VAT discount is no longer treated as the VAT rate.
- When a device copies your data up to cloud sync for the first time, a change you made on another device at the same moment is no longer at risk of being overwritten — the upload now defers to whichever copy is newer at the instant it writes.
- Turning off cloud sync now truly keeps new data on your device. An edit still waiting to upload when you switch sync off is no longer sent, and a leftover upload queue from an earlier session won’t sync on your next sign-in while sync stays off.
- Deleting your account is now sealed across every open tab, so a second tab can’t re-save data after the wipe. If the server-side deletion doesn’t confirm, the app returns to normal use instead of staying half-locked.
- A mistyped birthdate at the under-18 age check now signs you out rather than clearing your local data.
- Category rules and alert thresholds no longer re-stamp their edit time on every page load, so a real change made on one device isn’t overwritten by simply opening the app on another.
- When the password vault auto-locks after 30 minutes idle, its encryption key is now fully cleared — closing a gap where the vault’s own data could still be decrypted in the background until the page was reloaded.
- Retirement-simulator endpoints now require sign-in, are rate-limited, and bound their inputs, closing an anonymous compute-abuse path.
- Further security hardening: links in account emails are always built from the app’s own address rather than a request header, and the feedback endpoints are rate-limited per account.
- Restored the visual-regression and premium-tool test gates so pre-merge checks reliably catch marketing-page and gated-feature regressions again.
v0.11.0
- Two-factor authentication (TOTP) is available on every account — optional and strongly recommended. Compatible with any authenticator app; enable it anytime from Settings.
- Major security pass: closed 5 of 7 Critical, 4 of 9 High, and 14 additional findings from a hostile self-audit. Full status in SECURITY_AUDIT.md.
- Server-side token verification now checks revocation immediately — “Revoke other sessions” takes effect at the next request, not 1 hour later.
- Stripe checkout binds customers by verified user id only; eliminates billing-portal-by-email-collision risk.
- /api/subscribe rate-limited at 5/min/IP to prevent provider-cost abuse.
- Production builds fail fast if Firebase env vars are missing — no more silent dev-mode fallthroughs.
- 1136 unit tests passing (was 856 due to a pre-existing localStorage shim bug — fixed); 26/26 authenticated E2E green.
- VAT tracker stayed on the previous quarter past midnight on quarter boundaries.
- Stale dev-mode bypass could leak into production builds in two non-auth code paths — both now hard-gated.
v0.10.0
- AI Privacy Mode: Cloud (Gemini), Local (Ollama), or Local-only — server-enforced.
- Optional password-protected vault with PBKDF2 + 30-min auto-lock.
- AI usage analytics dashboard in Settings.
- 7-post blog at /blog covering FIRE, Sharia-compliant investing, expat finance.
- Comparison pages: vs Mint, vs YNAB, vs Personal Capital.
- Free Zakat calculator + UAE tax guide landing pages.
- CSV / PDF data export from Settings → Data Rights.
- Code-split dashboard widgets and AI advisor — ~30-40% smaller initial bundle.
- AI flow cache + transaction summarizer — estimated 60-80% token reduction.
- Sentry/PostHog scrub layer; AI input sanitization against prompt injection.
- TypeScript at maximum strictness; 260 unit tests passing.
v0.9.0
- Reliability: error boundaries, status page, feedback widget.
- Observability: Sentry + PostHog with DNT-respecting, PII-scrubbing capture.
- Feature flag system with localStorage overrides.
- Changelog popover with unread badge.
v0.8.0
- AI Advisor powered by Claude for personalized guidance.
- Voice input across quick-add flows.
- Command palette and global search upgrades.
v0.7.0
- Bank-connection framework scaffolded (Plaid + Lean) — automated account feeds targeted for early 2027; manual and statement import available today.
- Background price updates for tracked holdings.
v0.6.0
- Zakat calculator with Nisab thresholds and multi-asset support.
- Expat mode: multi-currency net worth, tax-residency guidance.
- FX rate caching and freshness indicator in header.
v0.5.0
- FIRE variants: Lean, Fat, Coast, Barista projections.
- Retirement and RMD simulators, Monte Carlo scenario planning.
- Tax-loss harvesting and year-end tax tool.
v0.4.0
- Estate, insurance, and family modules.
- Couples mode for shared financial planning.
- Giving + Goals tracking.
v0.3.0
- Portfolio, crypto, and property tracking.
- Debt and cash management with payoff calculators.
- Benchmarks and performance reports.
v0.2.0
- Dashboard, net worth, income/expenses.
- Budget envelopes and alerts.
- PWA install, offline shell.
v0.1.0
- Initial release: Firebase auth, settings, onboarding tour.