Skip to main content
Budget Tool
← All guides

Budget Tool — Release Notes

Newest first. Written for the people using and running Budget Tool, not from the commit log.

Anything marked Action needed requires somebody to do something; everything else takes effect on upgrade.


1.20 - 5 September 2026

Added

  • Two-factor authentication for platform administrators. /platform/account can now set up, disable and regenerate recovery codes for two-factor authentication, the same flow an organisation's own Settings page offers. It was previously not possible at all for this role.
  • The one-click demo sign-in is now rate limited, the same as every other unauthenticated endpoint that signs somebody in or sends mail on our behalf - 20 attempts per 15 minutes, per IP address, since there is no account yet to key the limit on.
  • The demo accounts can no longer write anything. They previously carried their role's genuine permissions with nothing stopping them from actually using them - a demo visitor picking Administrator or Finance user could really delete a budget or change settings. Every write is now refused centrally with a message, by HTTP method rather than a list of routes to remember per feature; reads and signing out both still work exactly as before.
  • app:demo:publish locks the seeded demo accounts' passwords. A demo exposed publicly needs this in addition to demo mode being on: without it, the same seeded password every local developer's copy uses also works at the ordinary sign-in form, bypassing the read-only enforcement above entirely. Action needed: if a demo instance is already live, run php bin/console app:demo:publish on it now, and add it to whatever schedule already reloads its fixtures - a reset reseeds the known password.

Changed

  • Two-factor authentication is now required, not optional, for the Administrator and Platform Administrator roles. Every other page redirects back to Settings (or, for a platform administrator, My account) until it is enabled, with a banner explaining why. Every other role can still choose to enable it, but is never required to.
  • The sign-in, registration, invitation and password screens now put only the form itself inside the elevated white card. The demo notice, the Microsoft sign-in option and every "go elsewhere" link (Create one, Sign in, Back to sign in) sit on the plain canvas around it instead, which is how the rest of this app's family builds an auth page.

Notes for administrators

  • This applies from the moment an account is promoted to Administrator, or from first sign-in for a freshly provisioned platform administrator - there is no grace period, and MFA reset behaves the same way for an existing Administrator who has just had it cleared.
  • The demo Administrator account is deliberately exempt. It is a shared, periodically reset fixture with a published password, and real enrolment on it would dead-end every visitor at a 2FA challenge nobody can pass. This has no bearing on a real administrator's own account.

1.19 - 3 September 2026

Added

  • A supported way to create the platform administrator of a new installation. php bin/console app:platform:provision-admin [email protected] creates the account and emails a one-time password. It is safe to run on every deployment — it does nothing if the installation already has one.

Changed

  • A password somebody else set for you now works exactly once. Signing in with it goes straight to a form to choose your own, and nothing else is reachable until you have. This applies to the provisioned platform administrator and to any account whose password an administrator sets or resets on their behalf.

Notes for administrators

  • Setting a user's password for them now forces them to change it at next sign-in. Tell them to expect it; the page they land on explains why.
  • The provisioning command deliberately does not print the password. If the email does not arrive, check the mail configuration, then delete the account and run the command again — there is no way to recover the password afterwards, by design.

1.18 - 2 September 2026

Changed

  • Whoever creates a budget can no longer approve it. Segregation of duties — the separation between the person who prepares a set of figures and the people who sign them off — is what makes an approval chain evidence rather than a formality, and it is the first thing an auditor asks about. The creator no longer appears in the list of people you can add as an approver, and the application refuses the assignment even if the request is made directly.
  • The privacy notice and the accessibility statement now come from a single source. Each previously existed twice in the codebase, and the two copies had drifted apart. Nothing you read has changed materially; the accessibility statement now shows the two sections that had only ever been in the unpublished copy.

Notes for administrators

  • If a budget currently has its creator as an approver, that person will be refused when they try to act. Add a different approver, or remove and reassign the approval, before submitting it. Existing approvals already given are not reversed.
  • A one-person organisation cannot complete an approval at all, by design. Invite a colleague before submitting a budget for review.

1.17 - 2 September 2026

Fixed

  • Importing the same actuals file twice no longer doubles your spend. The importer had no duplicate check at all, so re-importing an export created every transaction a second time — and a doubled month does not look broken, it looks like overspend. The review step now says how many rows look like transactions already imported and skips them by default. If they really are separate transactions that happen to look alike, you can say so and import them anyway.
  • Closed a set of places where editing an id in a URL could have reached another organisation's data. Budget and approval pages, and the company, cost centre and budget year filters on reports, all resolved ids in a way that could bypass the check that keeps organisations apart. They no longer can, and there is a test that tries.

Notes for administrators

  • Existing transactions have been fingerprinted as part of the upgrade, so they take part in duplicate detection too — re-importing an old file will be recognised.
  • Every import records how many rows it skipped as already imported, in the audit log.

1.16 - 2 September 2026

Added

  • Export a budget, edit it, import it back. The budget importer now recognises the columns the budget export produces, so the round trip works. At the review step you choose whether to add the incoming lines or replace what is already there — choose Replace when the file came from exporting this budget, or every line appears twice.
  • An example budget import file, from the Import screen, alongside a direct link to export the budget you are importing into.

Fixed

  • The budget importer could not read our own export. It expected a column called "Jan Amount"; the export writes "Jan". All twelve monthly figures arrived unmapped, so you were asked to map twelve columns by hand on a file you had just downloaded from Budget Tool. It now also understands months spelled out in full.

Notes for administrators

  • Replace deletes the budget's existing lines before importing. It is never the default and has to be chosen. If nothing in the file can be imported, the replace is refused outright rather than leaving the budget empty.
  • Every import records which mode was used, and how many lines were replaced, in the audit log.

1.15 - 2 September 2026

Added

  • Fix an unmatched transaction without re-importing. The Actuals page now has a Match button next to every unmatched row. Set the nominal code and whichever of company, department, cost centre and supplier apply, and it is matched immediately. Previously the only route was to export the unmatched rows, correct them in a spreadsheet and import the file again.
  • An example import file, from Import Actuals → Download an example file. The columns this expects, with two rows filled in.

Changed

  • The importer recognises other accounting systems. It now knows the column headings Xero, Sage and QuickBooks actually export, so your columns are matched up for you instead of arriving as a screen of empty drop-downs. It tells you which system it recognised, and anything it cannot place is still yours to set by hand.
  • The import screens no longer say "Xero". The importer has always worked with any system that can export a spreadsheet; the wording said otherwise.

Notes for administrators

  • Imported figures cannot be edited from the Match screen — only the fields matching depends on. Date, amount, description and reference are what your accounting system says happened; correct those at the source and import again.
  • If a correction still does not match, the message says which nominal code and which year it looked for. The usual cause is no budget for that year containing that code.

1.14 - 2 September 2026

Added

  • A proper API reference, at Guides → API reference: every endpoint, what it does, its parameters, and a worked request and response with real figures rather than a schema.
  • A downloadable Postman collection. Import it, paste your token into one variable, and press Send. It works in Insomnia and Bruno too. Generated from the same contract as the reference page, so the two cannot disagree.

Fixed

  • The variance report could return another organisation's data. Asking for a budget year belonging to someone else returned their report instead of "not found". Now fixed, and covered by a test that deliberately asks for somebody else's data.
  • The variance report was missing from the API documentation entirely — it worked, but no caller could discover it without reading the source.

Notes for administrators

  • If you have built anything against /api/v1/reports/variance, no change is needed: it behaves the same for data you are entitled to see.

1.13 - 2 September 2026

Added

  • The guides are now in the application, at Guides in the footer of every page. The user guide, the administrator guide and these release notes — previously they only existed as files in the code repository, which is no use to anybody actually using Budget Tool.
  • An API reference, at Guides → API reference, with the machine-readable specification published at a URL so a developer can generate a client from it.
  • Contextual help on every master data screen. Companies, Departments, Cost Centres, Nominal Codes, Budget Categories and Suppliers each now explain what the thing is for and what changing it affects — including which changes break future imports, which is the one that costs time.

Changed

  • The sign-in screen is laid out properly: the logo sits at the top of the coloured panel, the text is centred in the middle of it, and the links sit at the bottom. Previously all three were bunched together in the middle.

1.12 - 1 September 2026

Added

  • A "Get help" page, at the bottom of every page and on every error page. Tell us what you were doing and what happened instead, and we will reply to the address you give. It works without signing in — if you are locked out, that is exactly when you need it.
  • Proper error pages. A page that cannot be found, one you do not have access to, and a fault at our end each now explain what happened in plain words and offer a way back, instead of a bare browser error.

Fixed

  • Menu items you cannot open are no longer shown. Anyone who was not an administrator could see Microsoft sign-in and Email delivery in Settings and got "access denied" on both. Being shown a link and then refused is worse than not being shown it — you cannot tell a permission you do not have from something that is broken.

Notes for administrators

  • Set SUPPORT_ADDRESS to wherever help requests should arrive. Messages are sent from the platform's own address with the person's address as Reply-To, so replying goes to them.
  • The support form is rate limited to five messages an hour per address, because an unauthenticated form that sends mail is otherwise a way to flood an inbox.
  • A "403" is usually not a fault. The page now says so, and points the person at the administrator who can change their role.

1.11 - 1 September 2026

Added

  • One-click demo sign-in. The sign-in page now has a View demo button that opens a short list — Administrator, Finance user or Viewer — and one click signs you in as that example. No password to copy, and each one shows the product as that kind of person actually sees it.
  • A read-only demo account, so the demo can show what somebody who may look but not change anything sees. Previously every demo account could edit.

Changed

  • The demo data is a fictional company. The sample organisation is now Meridian Care Group, and every seeded account is a made-up person on a reserved .test address. No real name, address or employer appears in the demo data — which matters because three of those accounts are shown by name on the sign-in page whenever demo mode is on.

Notes for administrators

  • Demo sign-in only exists where APP_DEMO_MODE=1. Everywhere else the route is not merely refused, it returns 404 — an endpoint that signs people in should not advertise that it exists. Do not switch it on for an instance holding real data.
  • The seeded sign-in details have changed. The demo administrator is now [email protected]; the password is still changeme. Reload fixtures (doctrine:fixtures:load) to pick this up — it purges and re-seeds, so never run it against a live instance.

1.10 - 1 September 2026

Changed

  • The menu works properly on a phone. Below tablet width the navigation was a strip you had to scroll sideways to reach half of, which almost nobody discovered. It is now a normal menu button in the top bar that slides the full navigation in, closes on Escape or by tapping away, and returns you to the button you opened it with. Nothing changes on a desktop.
  • The privacy and accessibility links have moved to a consistent place. Centred at the bottom of every page once you are signed in; on the sign-in and registration screens they sit at the foot of the dark panel on the left, and move into the form card on narrow screens where that panel is not shown.

Added

  • A "try it without signing up" panel above the sign-in form, listing the demo accounts. Off by default, including in production: it appears only where APP_DEMO_MODE=1 is set, so an instance holding real data cannot advertise credentials by accident.

Notes for administrators

  • Do not set APP_DEMO_MODE=1 on an instance with real data. It prints working sign-in details above the login form. It is meant for a demonstration system whose data is disposable and periodically reset.
  • The menu button appears below 992px wide. Above that the sidebar is unchanged.

1.9 - 31 August 2026

Added

  • You can close your own account. Settings now has a "Close your account" section. It asks for your password and signs you out immediately. This is reversible - an administrator at your organisation can restore you.
  • Removed users, and a way back. Administrators can remove somebody from the organisation rather than only deactivating them. Removal stops sign-in at once, including any session they already have open. Users -> Removed users lists everyone removed, who removed them and when, with a Restore button.
  • Permanent erasure, for when somebody asks for their data to be deleted. Separate from removal, restricted to administrators, and confirmed by typing the person's email address rather than clicking through a dialog.

Changed

  • The audit log now records the name and email of whoever acted, at the time they acted. Previously it only linked to the account, so a removed account left older entries showing nobody. Existing entries have been filled in.
  • Some buttons have changed colour. The outline warning, danger and success buttons used Bootstrap's own shades; the warning one was effectively unreadable against white.

Notes for administrators

  • Removing and erasing are not the same, and the interface keeps them apart. Removing is reversible and is the right choice for somebody leaving. Erasing cannot be undone and is for a data deletion request.
  • What erasure keeps, and why. Budgets, forecasts, imports and approvals stay and are shown against a removed user. They are your organisation's financial records rather than the individual's, and an approval with nobody attached is not an accurate one. The privacy notice explains this to the person asking.
  • What erasure removes. Name, email address, password, two-factor setup, every invitation ever sent to that address, and their name on every audit entry. The entries themselves survive - otherwise closing an account would be a way of erasing what was done with it.
  • The last administrator cannot be removed or erased. Appoint another one first. This is enforced on the server, not just hidden in the interface.
  • A removed person is signed out immediately, not at their next sign-in attempt.

1.8 - 31 August 2026

Added

  • Both published notices are now complete. The privacy notice and the accessibility statement name Michael Shreeves as the individual who runs Budget Tool and answers questions about it, give a contact address and a five-working-day response commitment, and set out a retention schedule for every kind of record the application holds. The only thing still outstanding is the hosting provider, which has not been chosen.
  • A security section in the privacy notice describing what the software actually does - hashed credentials, secrets encrypted at rest, per-organisation isolation enforced in the database layer, an audit trail, role-based access and optional two-factor. Hosting will be on infrastructure certified to ISO/IEC 27001; the notice is explicit that this is the host's certification and that Budget Tool itself is not certified.
  • An accessibility statement, published at /accessibility. It is reachable without signing in and linked from the bottom of every page. It says plainly what has been tested and what has not.
  • Charts on the dashboard now carry their figures as text. A chart drawn into a <canvas> is invisible to a screen reader, so each one now has a data table with the same numbers behind it.

Fixed

  • Colour contrast throughout. Status badges, muted text and links did not meet the contrast the standard requires - the worst measured 3.05:1 where 4.5:1 is needed. Some colours are now noticeably darker; this is deliberate.
  • The border around text boxes and drop-downs is darker, because at its old shade it was almost invisible against the page and it is the only thing showing where the control is.
  • Keyboard focus is now always visible. Drop-down filters and the current sidebar item previously gave no indication at all of where the keyboard was.
  • Wide tables can now be scrolled with the keyboard. They could only be scrolled by mouse or trackpad before.
  • The file upload on both importers now has a label, as do the twelve monthly amount boxes on the reforecast screen, which previously had no name at all for anyone using a screen reader.
  • The dashboard and the privacy notice no longer scroll sideways on a narrow screen or at high zoom.
  • Four forms returned an error page instead of a validation message when a drop-down was submitted with nothing chosen.

Notes for administrators

  • The accessibility statement no longer cites the 2018 public sector regulations as binding on this service. Budget Tool is run by a private individual, so those regulations do not apply to it; the Equality Act 2010 duty to make reasonable adjustments does. Where Budget Tool is supplied to a public sector or NHS organisation, that organisation's own duty reaches it through procurement, and the statement is written to be usable as evidence.
  • The retention periods in the privacy notice are a published commitment. Six years for financial and audit records, twelve months for sign-in records, 35 days for backups. Review them before the application holds real data.
  • The interface has changed colour in places. Several status colours and the input borders are darker than before. This is to meet WCAG 2.2 AA contrast and is not a fault.
  • It says the service is partially compliant, because it has not been tested with a screen reader. That is an honest position and a stronger one than an untested claim of full compliance. If you need a full conformance claim for procurement, an NVDA pass is the remaining work.

1.7 - 31 August 2026

Added

  • Send email from your own domain. An organisation can now point Budget Tool at its own mail provider, so invitations and password resets arrive from its address rather than the platform's. Set it up under Settings -> Email delivery. As with Microsoft sign-in, saving is not enabling: nothing changes until a test message has actually been delivered.
  • A settings area with sections. General settings, Microsoft sign-in and Email delivery now sit together rather than as separate items in the sidebar.
  • A platform administrator can change their own password, at /platform/account. Previously the only route was the database.

Fixed

  • Messages sent on the platform's behalf could go out with no sender. A check that was meant to fill in the default from-address never fired, so any message that did not set one explicitly would have failed to send.

Notes for administrators

  • Authenticate your sending domain (SPF, DKIM, DMARC) before relying on your own provider. A from-address that does not match the authenticated domain is the commonest cause of mail landing in spam.
  • If your provider stops working, Budget Tool will not fall back to its own address. That would send your mail from a domain that is not yours, through a provider you did not choose. The send fails and the reason is shown on your settings page.
  • Use a send-only key at your provider.
  • Two-factor authentication is not yet available for platform administrator accounts.

1.6 - 31 August 2026

Added

  • A platform console for whoever runs the installation, at /platform: every organisation with its people, budgets, pending invitations and Microsoft sign-in status, and the ability to suspend or reactivate one. Suspending signs out anyone already using it on their next request.
  • Audited "view as" support access. A platform administrator can view the application as one of an organisation's administrators, to reproduce a problem a customer reports. They see exactly what that person sees and nothing wider, a banner stays on screen throughout, and both starting and ending the session are written to that organisation's own audit log - so a customer asking "who looked at our data, and when" can be answered from their own records.

Changed

  • A platform administrator now lands on the console rather than the dashboard. They belong to no organisation, so the ordinary application would have shown every customer's figures added together.

Fixed

  • Application settings were global rather than per-organisation. The RAG thresholds and the Cost Centre label were keyed in a way that would have let the first organisation to save them block every other organisation from having its own. Nothing had broken yet because no organisation had saved one, but the second to try would have hit an error. Each organisation now has its own.

Notes for administrators

  • Only an organisation's administrators can be viewed as, only while the organisation is active, and never another platform administrator.
  • A platform administrator cannot yet change their own password in the interface.

1.5 — 31 August 2026

Added

  • Sign in with Microsoft (Entra ID). Off by default, set up per organisation under Admin → Microsoft Sign-in. You register an app in your own Azure tenant and paste its three values in, so no credential is shared with any other customer and you control access from your side. The settings page includes the Azure steps and the exact redirect URI to register.
  • A test sign-in that has to pass before anything goes live. Saving credentials does not enable Microsoft sign-in — a real sign-in through the configuration has to succeed first, and any later change to the credentials puts it back to unverified. A mistyped secret therefore cannot silently disable everyone's access.
  • An option to require Microsoft sign-in, turning off passwords for your organisation. It is deliberately ignored while Microsoft sign-in is not verified and working, so a broken setup cannot lock you out.

Notes for administrators

  • Microsoft sign-in does not create accounts. People must be invited first.
  • Their MFA is yours, not ours. People signing in this way are subject to whatever your Microsoft tenant enforces; Budget Tool's own two-factor does not apply to them.
  • Client secrets expire — Azure defaults to 6 or 24 months. When one does, Microsoft sign-in stops, the reason appears on the settings page, and everyone falls back to passwords. Set a rotation reminder.
  • Nothing fails silently: every failure is recorded with its reason on the settings page and returns the person to password sign-in.

Known limitation

The connection to Microsoft has been built and everything around it is tested, but the exchange itself has not yet been run against a real Azure tenant — there was not one available. The built-in test sign-in exists exactly for this: the first real configuration proves itself before anybody depends on it.


1.4 — 31 August 2026

Added

  • Staff invitations. Administrators can invite people by email with a role, from a new Invitations page. The person sets their own password from the link, and their account is created only when they use it — so an invitation nobody opens leaves no dormant account behind.
  • Bulk invite from a CSV. Upload a list and review exactly who would and would not be invited before anything is sent. Anyone who already has an account, or an invitation waiting, is skipped with the reason shown, and the skipped rows download as a CSV with a reason column so the list can be corrected and re-uploaded. Uploading the same file twice is safe.
  • Resend and revoke. Resending issues a fresh link and stops the previous one working immediately, which is how to cut off an invitation that went to the wrong address.

Fixed

  • Completing a password reset returned an error, after changing the password. The audit record written at the end of a reset could not be saved, because a reset happens while signed out and the record had no organisation to belong to. The password change itself had already gone through, so the account was usable — but the person saw a failure. The same fault affected confirming a registration and accepting an invitation.

Notes for administrators

  • Invitation links last 14 days and work once.
  • Invitation sending is limited to 30 an hour per organisation. Use the bulk invite for anything larger.
  • An address that already has a Budget Tool account anywhere cannot be invited: one person holds one account, in one organisation.

1.3 — 31 August 2026

Added

  • Self-service registration. Anyone can create an organisation at /register and becomes its administrator. The organisation and the account are both inert until the emailed confirmation link is opened, so a stranger cannot provision a usable tenant for an address they do not control.
  • Email confirmation, using a signed link that expires. There is no token to store or clean up, and changing the address invalidates any link already sent.
  • A privacy notice at /privacy, readable before registering. Action needed: the operator-specific sections — who the data controller is, where it is hosted, and how long records are kept — are marked and must be completed before the application is used with real people's data.
  • Proper HTML emails. Messages now use a shared branded layout with a plain text alternative, instead of the plain text previously assembled in code.

Changed

  • Security headers are now sent on every response — content type, framing, referrer, permissions, and a content security policy in production. The application previously sent none.
  • A production deploy now fails fast if APP_SECRET is missing or too short, or if the mailer is still null://. Both would previously have deployed silently: an empty secret makes every confirmation link, reset link and CSRF token forgeable, and a null mailer means registration can never complete. Action needed: make sure both are set in your production environment before the next deploy, or it will stop with a message telling you which.

Security

  • Registration is rate limited to five attempts an hour per connection — it is the only unauthenticated form that creates real records.
  • A registration attempt with an address that already exists behaves exactly like a new one, so the form cannot be used to discover who has an account.
  • Temporary and disposable email domains are refused.
  • The first administrator of an organisation needs a 12-character password, longer than elsewhere, because that account administers everything from the moment it is created.

1.2 — 31 August 2026

This release makes Budget Tool multi-tenant. It is the foundation for self-service registration and staff invitations, which follow in the next releases.

Added

  • Organisations. An organisation is now the boundary around everything: companies, budgets, actuals, master data, users, settings and the audit log all belong to one, and no organisation can see another's data by any route. An organisation sits above Company, so one customer can still hold several legal entities and get a Master Budget rollup per company.
  • Organisation status. Pending, Active or Suspended. Suspending blocks sign-in and signs out anyone already using the application on their next request, rather than waiting for their session to expire.
  • A platform administrator role, belonging to no organisation, for whoever runs the platform. It is deliberately given none of the ordinary budget permissions.
  • Two demo organisations in the development dataset, with deliberately separate data, so isolation can actually be demonstrated rather than assumed.

Changed

  • Names are now unique per organisation, not globally. Two organisations can each have a company called "Head Office", a department called "Finance", and a 2027 budget year. Email addresses remain globally unique: one person, one account, one organisation.
  • Existing data was migrated into a single "Default Organisation" on upgrade. Nothing was lost and nothing changed for an existing installation - it simply became an installation with one organisation in it.

Fixed

  • The Users and Audit Log pages listed every user on the installation, not only those in your own organisation. Found while adding tenancy scoping.
  • Adding an approver accepted any user id. Both the budget and master budget approver screens resolved whoever the id pointed at, so another organisation's staff could have been named as an approver on your budget. Ids are now resolved within your own organisation only.

Action needed

  • Nothing on upgrade - existing data is migrated automatically into a default organisation.
  • If you have API tokens issued, note they now belong to the issuing user's organisation. Existing tokens were migrated with everything else.

1.1 — 31 August 2026

Added

  • Recovery codes for two-factor authentication. Enrolling now produces ten single-use codes, shown once. Enter one in place of a code from your authenticator app if you lose the device. You can generate a fresh set from Settings, which immediately retires the old ones. Previously, a lost device meant asking an administrator to reset MFA.
  • A read-only API, so other applications can pull budgets, budget lines and master data out of Budget Tool. Administrators issue scoped, expiring tokens under Admin → API Tokens. The full contract is in docs/openapi.yaml.
  • Reforecast in the Variance Report. Reforecast figures now appear as their own column, and you can choose whether variance and RAG status are measured against the original budget or the reforecast. Both figures are always shown. Previously reforecast was entered per line but never reached the reports.
  • A user guide and an administrator guide (docs/User_Guide.md, docs/Administrator_Guide.md).
  • In-app help on every page. The ? panel previously covered 14 pages; it now covers all 50, including both import wizards, which had none.
  • php bin/console app:mail:test — sends a test message and reports which transport it used, so outbound mail can be verified without triggering a password reset.
  • A MAILER_FROM setting, so the From address is configurable rather than hardcoded. Action needed: set it in .env.local alongside MAILER_DSN.

Changed

  • The application works on tablets and phones. Below 992px the sidebar becomes a scrolling strip above the content, and wide tables scroll inside their own container instead of pushing the page sideways.
  • The sign-in, password-reset and two-factor screens now share one layout, with a proper heading on each and a brand mark.
  • Messages now appear on the sign-in and password-reset screens. See Fixed.
  • Logging out is now a button rather than a link, and is protected against cross-site requests.
  • Variance CSV exports name the comparison basis in the header row and in the filename, so an exported spreadsheet still says what it was measured against.
  • Password reset is now rate-limited — three attempts per address and ten per source address every fifteen minutes. The generic "if an account exists" message is unchanged.

Fixed

  • Password reset and sign-in messages were invisible. Those screens never displayed messages at all, so "If an account exists for that email, a password reset link has been sent" — and every error on those pages — was silently discarded. Anyone who has been told "nothing happens when I reset my password" was seeing this.
  • A reset link could be read out of the production log. The link contains a working credential and was being written to the log on every request. It is now only ever logged in development.
  • A failed password-reset email was silent. If the mail transport refused the message, the user was still told a link had been sent and nothing was recorded. Failures are now logged at error level.
  • Eleven actions failed silently when a request could not be verified — deactivating a company, deleting a budget line, resetting MFA and others. The page reloaded, nothing changed, and nothing explained why. They now say so.
  • Lines with no plan but real spend showed as Green. In the Variance Report, a line with nothing budgeted or reforecast against it but actual spend recorded produced a 0% variance and a Green status — reading as "on track" for spend that was never planned. Such lines now show — for the percentage and Red, labelled Unplanned spend.
  • Report filters could error under some inputs. A non-numeric value in a filter parameter is now ignored rather than treated as a filter.
  • A dead "Imports" link in the sidebar has been replaced with a working Import Actuals entry, shown only to people who can use it.
  • Active navigation is now announced to screen readers, not signalled by colour alone.

Security

  • Logging out no longer works over GET. It previously did, which let any third-party page sign a user out with an image tag.
  • The API cannot be authenticated by a browser session — it is token-only and stateless, so a cross-site request cannot speak for a signed-in user.
  • Deactivating a user immediately invalidates their API tokens. Action needed: if someone who owns an integration is leaving, reissue that token under an account that is staying, before deactivating theirs.
  • API errors no longer leak internal detail. A not-found response used to name the internal class and resolver involved.
  • Every page is now marked noindex, so nothing behind the login can reach a search index.

For developers

  • declare(strict_types=1) added to every PHP file, and classes made final except entities. This surfaced one real defect — see the filter fix above.
  • Test suite grown from 58 to 94 tests.

1.0

The initial release: authentication with two-factor, master data, budget years and budgets with multi-approver sign-off, master budgets, the budget and actuals import wizards, the dashboard, and the variance, trend and profit & loss reports.

Guides Get help Accessibility statement Privacy notice