Commit Graph

4902 Commits

Author SHA1 Message Date
Matiss Janis Aboltins
dee3c22002 Update tech-support.yml
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>
2026-05-01 18:36:27 +01:00
Matiss Janis Aboltins
8335e76d45 Update issues-close-tech-support.yml
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>
2026-05-01 18:36:16 +01:00
Cursor Agent
fb699c960b [AI] Fix formatting in workflow file
Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com>
2026-04-30 17:16:03 +00:00
Matiss Janis Aboltins
b95b889da5 Update 7670.md 2026-04-30 18:11:58 +01:00
Cursor Agent
ff2e1d5eff [AI] Replace create-or-update-comment action with gh CLI
The peter-evans/create-or-update-comment action is unnecessary since GitHub's gh CLI (pre-installed on all GitHub-hosted runners) provides the same functionality natively via 'gh issue comment' and 'gh issue close' commands. This change addresses the zizmor security scanner warning about using an action when the functionality is already included by the runner.

Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com>
2026-04-30 17:08:28 +00:00
github-actions[bot]
17d94f41bc Add release notes for PR #7670 2026-04-30 18:05:42 +01:00
Claude
85f8f50ed8 [AI] Replace Support contact link with auto-closing tech-support issue template
Convert the external Discord "Support" contact link into a proper GitHub issue
form so users who skip the redirect still land somewhere useful. The new form
has a single "Describe your problem" field and a prominent notice that tech
support tickets are auto-closed and Discord is the place to get help. A new
workflow watches for the `tech-support` label, posts a friendly Discord pointer
and closes the issue, mirroring the existing feature-request auto-close flow.
2026-04-30 08:10:53 +00:00
Julian Dominguez-Schatz
24279264da Fix shared worker resumption after tab suspend (#7656)
* [AI] Fix SharedWorker tab resume recovery

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* [AI] Fix SharedWorker reload readiness

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add release notes

* Update packages/desktop-client/src/shared-browser-server-core.ts

Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>
2026-04-30 07:37:02 +00:00
Matiss Janis Aboltins
4a5ee9c2dc [AI] Make TypeScript work in test files across packages (#7642)
* [AI] Make TypeScript work in test files across packages

Match the CRDT package's tsconfig pattern in loot-core, desktop-client,
api, and desktop-electron so test files participate in the project graph
(IDE intellisense, project-wide typecheck) while production builds still
emit clean declaration files.

- Remove test-file exclusions from each package's main tsconfig
- Add tsconfig.build.json for loot-core and api with test exclusions,
  used by the build scripts
- Add e2e/tsconfig.json for desktop-client and desktop-electron with
  Playwright types
- Fix latent type errors in test files now caught by typecheck
- Disable typescript/unbound-method for test files (mock matcher pattern)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Release notes

* [AI] Address review feedback on test type fixes

- goal-template.test.ts: extract amounts to typed locals so single-value
  assertions no longer compare against unknown
- category-template-context.test.ts: replace `as unknown as DbCategory`
  double-cast with a fully-typed object using `satisfies DbCategory`
  (the previous mock had `is_income: true` which doesn't match the
  `1 | 0` shape the cast was hiding)
- api/tsconfig.build.json: broaden test exclude pattern to `**/*.test.ts`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Widen toMatchThemeScreenshots matcher to accept Page

The matcher's runtime impl already handled both Page and Locator
(via `typeof locator.page === 'function'` branch), but the type only
declared Locator. Call sites pass a Page (`expect(page).toMatchThemeScreenshots()`),
which now compiles cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Type window.Actual in e2e fixtures and refactor matcher

- Pull loot-core/typings/window.ts into the e2e tsconfig include so
  the ambient `window.Actual` augmentation is visible.
- Refactor toMatchThemeScreenshots to derive a Page once via
  `'page' in target`, then call evaluate on the page consistently.
  The previous union-typed access (locator.evaluate, locator.page)
  didn't typecheck on Locator | Page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Drop tsconfig.build.json for loot-core and api

The build-config indirection was incomplete protection: typecheck
(`tsgo -b` against the main tsconfig, which now includes test files)
already emits `*.test.d.ts` into `@types/`, and the build step does
not clean before re-emitting. The same is observable in crdt's
`dist/`, which currently contains test declarations on disk.

What actually keeps test declarations out of the npm tarball is the
`files` field in package.json — and loot-core already uses that
mechanism for source files (`\!src/**/*.test.ts`). Extending the same
pattern to `@types/` is more direct than maintaining a duplicate
tsconfig that doesn't reliably do its job.

- Delete loot-core/tsconfig.build.json; revert build to `tsgo -b`;
  add `\!@types/**/*.test.d.ts*`, `\!@types/**/__tests__/**`,
  `\!@types/**/__mocks__/**` to `files`.
- Delete api/tsconfig.build.json; revert build to
  `vite build && tsgo --emitDeclarationOnly`; add
  `\!@types/**/*.test.d.ts*` to `files`.

Verified: `yarn pack --dry-run` excludes all test declarations from
both packages while production declarations still pack (428 .d.ts
files for loot-core, methods.d.ts for api).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Standardise crdt to drop tsconfig.build.json

Apply the same simplification as loot-core and api: a single tsconfig
per package, with `files`-field negations preventing test
declarations from being published.

Note: this also fixes a pre-existing issue where crdt was shipping
`crdt/timestamp.test.d.ts` and `crdt/merkle.test.d.ts` to npm. The
old `tsconfig.build.json` excluded test files from declaration emit,
but the `typecheck` script (`tsgo -b` via the main tsconfig) had
already emitted them into `dist/` and the build did not clean
first, so they were packed via `"files": ["dist"]`.

After this change, `yarn pack --dry-run` packs only production
declarations (10 .d.ts files) and excludes the test ones.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:06:58 +00:00
arjunrawal1
a8eb204ce7 Fix release notes link in PR template (#7655)
* Fix release notes link in PR template

* Add release note
2026-04-29 16:39:10 +00:00
rboadu
f68e4fbb2a Updated API Documentation for Splitting Transactions (#7593)
* Updated API Documentation for Splitting Transactions

* Update check-spelling metadata

* Updated category name in example

* Update packages/docs/docs/api/reference.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Fixed documentation to CodeRabbits feedback

* Update packages/docs/docs/api/reference.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Updated wording of reference document

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: youngcw <calebyoung94@gmail.com>
2026-04-29 16:28:14 +00:00
Matiss Janis Aboltins
dd3b1144d1 [AI] Mobile: iconography, placeholders, and dropdown chevrons for transaction form (#7639)
* [AI] Add iconography, placeholders, and dropdown chevrons to mobile transaction form

Brings the mobile new-transaction screen in line with the design mockup so
each field shows a leading icon, dropdown affordances surface on the right,
and empty pickers display a placeholder hint.

- Extend TapField with optional icon/placeholder props (placeholder uses
  formInputTextPlaceholder when value is empty).
- Extend InputField with an optional icon prop that wraps the input in a
  bordered row when present.
- Wire SvgUser/SvgTag/SvgWallet/SvgCalendar/SvgNotesPaper into Payee,
  Category, Account, Date, and Notes for both the main form and split
  child rows; add a SvgCheveronDown rightContent on Category and Account.

* Add release notes for PR #7639

* [AI] Forward consumer style to inner Input in icon path of InputField

CodeRabbit flagged that consumer-supplied `style` was being applied to the
wrapper View in the icon branch, so input-targeted properties like
`appearance: 'none'` and `minWidth: '150px'` on the Date field never reached
the underlying `<input type="date">`. Move the style spread onto the inner
Input so those styles take effect.

* [AI] Add dropdown chevron to mobile Payee field

Show the chevron on the Payee TapField in both the main form (as the
fallback when neither the Save-location nor Nearby-payee button applies)
and in split child rows, matching Category and Account.

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7639

* [AI] Hide native date picker icon on mobile transaction form

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7639

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-29 07:56:05 +00:00
Matiss Janis Aboltins
ff0f5bdb35 [AI] lage - move browser build to using lage (#7602)
* Simplify desktop client browser build

* [AI] Move browser build orchestration into vite config and lage

Moves loot-core worker build, public/ staging (migrations, default-db,
sql-wasm, data-file-index), and build-stats wiring from the deleted
packages/desktop-client/bin/build-browser shell script into a
lootCoreBackend vite plugin in packages/desktop-client/vite.config.mts.

Adds a build:browser target to lage.config.js so bin/package-browser
runs as a single `lage build:browser --to=@actual-app/web` call, with
crdt + loot-core built via lage's ^build dependency before the
desktop-client build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Refactor e2e-test workflow and update desktop-client configurations

* [AI] Move plugins-service staging into desktop-client vite config

Declares plugins-service as a workspace devDependency of @actual-app/web
so lage's ^build edge picks it up automatically in the build:browser
pipeline, and moves the cross-package file staging (production copy +
dev serving) into vite.config.mts, mirroring the lootCoreBackend
pattern. Drops the plugins-service shell wrapper script and simplifies
its package.json scripts to invoke vite build directly. Updates root
start:browser to run plugins-service watch in parallel with the dev
server instead of pre-building once.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Sync tsconfig project references for plugins-service edge

Follow-up to the plugins-service workspace edge: adds the
../plugins-service project reference in packages/desktop-client/tsconfig.json
via yarn sync:tsconfig-references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Release notes

* [AI] Ignore .venv/ so lage's git hasher skips Electron CI's Python venv

Electron CI provisions a Python virtualenv at the repo root for
setuptools. With browser builds now routed through lage, lage's
git hash-object pass walks untracked-not-ignored files and fails on
the venv's broken lib64 symlink ("fatal: Unable to hash .../.venv/lib64").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Bake Weblate translations back into VRT/e2e bundle

build-web set download-translations: false and relied on bin/package-browser's
ad-hoc git clone + git pull. That path is fragile inside the playwright
container, so vite's import.meta.glob('/locale/*.json') frequently produced an
empty languages map and the bundle shipped with no en.json. VRTs then rendered
source-code English and diffed against snapshots authored from Weblate strings.

Route translation provisioning back through actions/checkout (download-translations: true)
in build-web and vrt-update-generate, and add --skip-translations to bin/package-browser
(mirroring bin/package-electron) so the in-script git pull is bypassed when CI
has already staged the locale dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Skip translation cloning in build-web bundle for VRT determinism

bin/package-browser used to unconditionally clone actualbudget/translations
before vite ran, baking Weblate en.json into the build artifact. With the
e2e-test pipeline now serving that artifact via serve-build.mjs, VRT
screenshots ended up rendering Weblate strings — drifting from the snapshots,
which were authored against source-code English (master VRTs ran on vite dev
without a locale dir).

Pass --skip-translations to bin/package-browser from build-web so the bundle
ships with no locale chunks. download-translations stays 'false' across the
e2e-test and vrt-update-generate workflows, matching the prior behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 20:20:13 +00:00
Rudra Sarker
11ce29e7fd fix: disable Inter font contextual alternates to prevent x→× substitution (#7375)
* fix: disable contextual alternates in Inter font to prevent unwanted character substitution

Fixes #6351

The Inter font calt feature replaces x between digits with a
multiplication sign. Disable it while preserving ss01 and ss04.

* [autofix.ci] apply automated fixes

* Add release notes for PR #7375

* [autofix.ci] apply automated fixes

* Fix release notes category casing

* Add authors field to release notes

* Update upcoming-release-notes/7375.md

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>
2026-04-28 10:56:20 +00:00
Trevin Chow
d58c9a9a07 fix(transactions): show 'Date is a required field' error when adding without date (#7511)
* fix: show consistent 'Date is a required field' error in add transaction

When adding a new transaction with a missing date, the UI surfaced the
generic 'Something internally went wrong' error instead of a specific
message, while missing account showed 'Account is a required field'.
Add an analogous date validation mirroring the existing account check,
so both required-field errors are consistent.

Fixes #7424

* fix: prevent empty date from reaching server when clearing date input

When adding a transaction, clearing the date field and clicking Add
caused DateSelect's blur handler to save an empty string as the date
via onSelect(''). The server rejected '' as an invalid date, emitting
a generic "Something internally went wrong" error.

The previous fix (adding a date check in the shouldAdd guard) didn't
work because the cell save fires on blur BEFORE shouldAdd runs — by
the time shouldAdd checks the date, it's either already sent to the
server or reverted by DateSelect's clearOnBlur logic.

Fix: change DateSelect's empty-input blur path to restore the previous
valid date instead of propagating ''. This prevents the invalid value
from ever reaching the cell save handler or the server.

Verified locally: clear date → click Add → date restores to previous
value and transaction saves normally. No generic error.

Fixes #7424
2026-04-28 10:50:54 +00:00
Matiss Janis Aboltins
598e3ec9d8 [AI] Keep mobile transaction amount field at a consistent height when empty (#7638)
* [AI] Keep mobile transaction amount field at a consistent height when empty

When the user backspaced every digit while editing the amount on the
mobile transaction form, the inner <Text> span had no content and
collapsed the pill to zero height. Fall back to a non-breaking space so
the line box keeps its natural font-driven height even when the input
is momentarily empty.

* Add release notes for PR #7638

* [AI] Use amountToCurrency(0) instead of nbsp when amount input is empty

Mirrors the unfocused-zero display rather than rendering a blank pill,
and respects the user's hideFraction pref and locale separators
through amountToCurrency.

* Simplify description of mobile transaction field height

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-28 07:31:57 +00:00
Matt Fiddaman
c2987af64f fix lint (#7643) 2026-04-27 21:24:16 +00:00
Matt Fiddaman
c7d39961cf fix cherrypicked commits not being respected and lint race in release note generation workflow (#7640)
* fix cherrypicked commits not being respected and lint race

* note

* coderabbit suggestions

* fix lint

* make double restore possibility safe
2026-04-27 20:52:07 +00:00
Matt Fiddaman
a42b7c5777 fix release note generation script (#7635)
* fix release note generation script

* note
2026-04-27 19:32:24 +00:00
Emil Tveden Bjerglund
33af9bf906 Fix Sankey income bug, when payee it not set (#7632)
* Ensure income categories are shown correct, even if payee is not set

* Add release note
2026-04-26 19:23:07 +00:00
Matt Fiddaman
46687da7a8 fix infinite loop when remainder is impossible to solve (#7623)
* fix infinite loop when remainder is impossible to solve

* note
2026-04-26 04:20:49 +00:00
Matt Fiddaman
3928d5b2a8 increase test coverage for budget templates (#7620)
* [AI] cover existing template engine logic with regression tests

Adds tests for goal template behavior that predates this PR so the
suite can be cherry-picked onto master to confirm no regressions. No
production code changes.

Covers:
- init() validation: schedule names, by/schedule priority match, past
  by-target with and without annual/repeat, percentage source not
  found, special source aliases, duplicate limit/spend/goal
  directives, weekly limit missing start date, invalid limit period,
  unrecognized periodic period
- runRemainder cap clamping and hideDecimal fraction removal
- Income-category branch in runTemplatesForPriority
- getLimitExcess against an aggregate weekly cap
- Past by-target rolling forward via the annual period
- runSchedule full=true (no sinking accumulation), percent and fixed
  adjustments, completed-schedule filtering, past-date error for
  non-repeating schedules, monthly/weekly/daily sinking contribution
  branches when interval exceeds the pay-month-of cap, surplus
  absorption when last-month balance exceeds the target, and
  tracking-budget mode forcing all schedules pay-month-of
- applyMultipleCategoryTemplates orchestration: per-category writes,
  cross-category priority clamping when funds run out, error
  notification path
- applyTemplate force=false skipping already-budgeted categories

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* note

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 23:35:32 +00:00
Matt Fiddaman
8b29ee40a7 show all blog posts on docs site (#7622) 2026-04-25 23:20:40 +00:00
Matiss Janis Aboltins
9acbd6388b [AI] Cache the CLI's local budget between invocations (#7539)
* [AI] Cache the CLI's local budget between invocations

Every `actual <cmd>` call currently delta-syncs the budget with the
sync server via `api.downloadBudget`, which hits the server's
500-req/min rate limit on scripted workflows. Actual is local-first:
once the budget is on disk, most read commands do not need fresh
server data.

Introduce a CLI-only cache layer inside `withConnection` that
decides per invocation whether to skip, sync, or re-download:

- Cache state lives at `{dataDir}/.actual-cli/{syncId}/state.json`,
  keyed by `syncId` to avoid the chicken-and-egg of not knowing the
  on-disk `budgetId` before the first download. The on-disk id is
  resolved via `api.getBudgets()` and persisted after first download.
- Read commands (list, balance, query run, …) skip the `/sync`
  call while `now - lastSyncedAt < cacheTtl`. Write commands
  (create, update, delete, set-*, etc.) sync before and after the
  operation to keep server state consistent.
- Encrypted budgets force a sync per call since `api/load-budget`
  does not re-verify the password.
- New `proper-lockfile`-backed shared/exclusive lock serializes
  writes while allowing parallel reads. Reader markers live in
  `{meta}/readers/`; writers sweep stale markers by PID.

New `actual sync` command with three modes: default (sync now),
`--status` (print cache age, TTL, stale flag), `--clear` (delete
cache, holding the exclusive lock to avoid racing writers).

New config surface, following the existing flag → env → config file
→ default precedence chain:

- `--cache-ttl <s>` / `ACTUAL_CACHE_TTL` / `cacheTtl` (default 60)
- `--refresh` / `--no-cache`
- `--lock-timeout <s>` / `ACTUAL_LOCK_TIMEOUT` / `lockTimeout` (10)
- `--no-lock` / `ACTUAL_NO_LOCK` / `noLock`

Every `withConnection` call site now passes an explicit
`{ mutates: boolean, skipBudget?: boolean }` so read/write intent is
visible at the edge.

The old `budgets sync` subcommand is removed — it silently diverged
from the new top-level `actual sync`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Simplify CLI cache/lock internals

Use a discriminated SyncDecision union so connection.ts no longer needs
non-null assertions on the cached state. Thread the resolved CliConfig
through withConnection's callback to drop duplicate resolveConfig calls
in the sync and budgets commands. Extract an errorCode helper and
replace the existsSync+readdirSync TOCTOU pattern in the reader-wait
polling loop with a single readdir that tolerates ENOENT.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Address PR #7539 review comments

- cache.ts: use a unique per-writer tmp filename so concurrent shared-
  lock writers (encrypted budgets, --refresh, stale TTL) don't clobber
  each other's publish and silently drop state updates.

- index.ts/config.ts: fix --no-cache and --no-lock flags. Commander
  stores --no-foo under the positive key (cache/lock) and an explicit
  false default makes the flag a no-op; the previous code also read
  the wrong keys (noCache/noLock) so the flags had no effect at all.
  Derive refresh/noLock from the correct keys.

- budgets.ts: invert encryption password precedence so the subcommand
  flag (--encryption-password) wins over env/config-file values.

- sync.ts: report stale=true in --status when lastSyncedAt is in the
  future, matching decideSyncAction's clock-skew handling.

- connection.ts: drop unnecessary `as` cast on api.getBudgets() now
  that the return type is Promise<APIFileEntity[]>.

- utils.ts: parseBoolEnv throws on unrecognized values instead of
  silently returning undefined so typos like ACTUAL_NO_LOCK=yes fail
  loudly.

- Shorten 7539 release note to a single user-facing sentence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:58:18 +00:00
Alec Bakholdin
77f0a3e58b Update documentation for transaction import behavior based (#7614)
* Update documentation for transaction import behavior

Updated docs per the change in #7610

* [autofix.ci] apply automated fixes

* release notes

* removed patch notes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-25 21:44:38 +00:00
Matt Fiddaman
eb922fd191 sankey card should follow report settings (#7619)
* sankey card should follow report rules

* note
2026-04-25 16:17:45 +00:00
Julian Dominguez-Schatz
2b584e1ad0 Make double ctrl-f trigger browser-native search (#7605)
* Make double Ctrl-f trigger browser find

* Add release notes

* Invert condition

* Rename release note
2026-04-25 00:53:25 +00:00
dependabot[bot]
4f1bc3fcdd Bump postcss from 8.5.8 to 8.5.10 (#7613)
* Bump postcss from 8.5.8 to 8.5.10

Bumps [postcss](https://github.com/postcss/postcss) from 8.5.8 to 8.5.10.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.8...8.5.10)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.10
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Add release notes for postcss version bump

Updated postcss version for maintenance.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>
2026-04-25 00:23:54 +00:00
Julian Dominguez-Schatz
ea50db524b Enable stricter electron build options (#7609)
* Enable stricter electron build options

* Add release notes

* Fix build signatures when no signing credentials are provided

* Attempt fix again
2026-04-24 23:59:28 +00:00
Julian Dominguez-Schatz
da1d0a94b9 Migrate file service to TypeScript (#7606)
* Migrate file service to TypeScript

* Add release notes

* Rabbit

* Stricter types
2026-04-24 22:50:43 +00:00
Alec Bakholdin
daab7f737e Import Transactions - Persist and set reimport deleted transactions config to true (#7610)
* fix: restored default functionality from v26.3.0 for reimport deleted transactions. import-reimport-deleted is now a synced pref that persists between imports

* release notes

* release note update

---------

Co-authored-by: Alec Bakholdin <alecbakholdin.com>
2026-04-24 18:21:45 +00:00
Emil Tveden Bjerglund
686f10247d Enhance Sankey chart datamodel, show income and allow layer filtering (#7582)
* Refactor to use directed, weighted graph as datamodel

* Fix percentage labels

* Reimplement sorting and topN handling

* Fix typing. Show toBudget on graph.

* Implement better DAG model

* Fix Other-grouping with new datamodel

* Add global sorting

* Reorder spreadsheet code for clarity

* Add percentageLabels back

* Fix all sorting modes

* Better color handling

* Handle if overbudgeted

* Fix filtering issue related to hidden nodes for Spent report

* Implement enums for special names

* Linting and typechecking

* Add layer selectors

* Trim SankeyCard

* Fix issue with empty nodes making the graph unreadable

* Add release note

* Update release note

* Reorder code

* Address coderabbit comments

* Ensure that layer-from and layer-to cannot be equal

* Update layer selectors to match selected view mode

* Fix wrong graph object reference

* Cap regex length

* Fixed wrong layer assignment for budget income categories

* Make translation not optional in createSpreadsheet

* Use predefined suffix for 'Other'

* Avoid invalid layer selection for Budgeted

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7582

* Import translation in spreadsheet, instead of passing as argument

* Remove all non-null assertions and handle safely

* Fix most uses of 'as'

* Fix issues hiding Other categories and giving wrong toBudget value

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-24 18:20:15 +00:00
Julian Dominguez-Schatz
227c995155 Disallow reconfiguring OpenID after initialization (#7608)
* Disallow reconfiguring OpenID after initialization

* Add release notes
2026-04-24 15:12:01 +00:00
dependabot[bot]
c8224d24be Bump @xmldom/xmldom from 0.8.12 to 0.8.13 (#7596)
Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.12 to 0.8.13.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.12...0.8.13)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-version: 0.8.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 20:06:30 +00:00
Dakyne
29a06b23ea Add Gruvbox Light and Dark themes to custom theme catalog (#7571)
* Add Gruvbox Light and Dark custom themes to catalog

* Add release note for PR #7571

* [autofix.ci] apply automated fixes

* Update packages/desktop-client/src/data/customThemeCatalog.json

Co-authored-by: Joel Jeremy Marquez <joeljeremy.marquez@gmail.com>

---------

Co-authored-by: Dakyne <fawn_salable_73@icloud.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Joel Jeremy Marquez <joeljeremy.marquez@gmail.com>
2026-04-23 14:25:05 +00:00
Matiss Janis Aboltins
aeb28d3b87 Add Discord notification for nightly theme catalog scan failures (#7595)
* [AI] Notify Discord when nightly theme catalog scan fails

Adds an if: failure() step to the validate-theme-catalog job that posts a
minimal alert to the DISCORD_WEBHOOK_URL webhook with a link back to the
failing workflow run. Fires on both theme validation failures (script exits
1) and earlier step failures (checkout/setup), so infrastructure breakage
is also surfaced. nofail: true keeps a Discord outage from cascading into
a red job.

* [AI] Drop setup comment from Discord notify step

* [AI] Move Discord notify to its own job gated by an environment

Splits the notify step into a separate notify-failure job that depends on
validate-theme-catalog and runs only on failure. The new job binds to the
nightly-alerts GitHub Environment so the DISCORD_WEBHOOK_URL secret is
scoped to a dedicated environment rather than inherited at the repo level
(zizmor secrets-without-environment).

* [AI] Add release notes for 7595

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-23 06:58:21 +00:00
dependabot[bot]
bd1da27404 Bump dompurify from 3.3.2 to 3.4.1 (#7591)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.3.2 to 3.4.1.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.3.2...3.4.1)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv>
2026-04-22 20:51:12 +00:00
Matiss Janis Aboltins
7501674613 [AI] Fix Docker build for workspace:* dependencies (#7564)
* [AI] Fix Docker build for workspace:* dependencies

Since @actual-app/crdt became a workspace:* dep, `yarn workspaces focus
--production` creates relative symlinks in node_modules that dangle when
only node_modules is copied into the prod image, breaking local Docker
builds with ERR_MODULE_NOT_FOUND: @actual-app/crdt.

Dereference yarn's workspace symlinks in the builder stage with `cp -RL`
so the prod stage can copy a self-contained node_modules without needing
to enumerate which workspace:* deps exist. Adding a new workspace:* dep
now requires zero Dockerfile changes.

Also move the sync-server .dockerignore to the repo root (and drop stray
local node_modules / .git / .yarn caches from the build context), since
docker builds use the repo root as context — the old sync-server-level
file was no longer being applied.

Fixes #7561.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Strip dev-only dirs from dereferenced workspace packages

The generic `cp -RL` step copies full workspace package trees into the
image (src/, e2e/, tests, build-stats, etc.). Remove them after the
dereference — they're not needed at runtime, and skipping them recovers
~67MB from the final image on both alpine and ubuntu variants.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Rephrase 7564 release note to be user-facing

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 19:20:51 +00:00
Jaime R Calzada
c3717e7036 [AI] Add per-schedule custom upcoming length override (#7434)
* [AI] Add per-schedule custom upcoming length override

* [AI] Add release notes for PR #7434

* [AI] Add custom length option to per-schedule upcoming length selector

* [AI] Deduplicate preset values and guard against malformed custom upcoming length

* [autofix.ci] apply automated fixes

* [AI] Retrigger CI (flaky accounts E2E test)

* [AI] Improve schedule editor layout for upcoming length field

Restructure the custom upcoming length from a checkbox + conditional
dropdown into a proper FormField with a single Select that includes
"Use global default" as the null option. Place it in a responsive
side-by-side row with the auto-post checkbox, consistent with the
form's existing layout patterns.

* [AI] Address CodeRabbit review feedback

Tighten custom upcoming length validation with a proper regex
instead of a loose hyphen check. Replace fixed height with minHeight
on the auto-post checkbox row to avoid clipping translated labels.

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #7434

* [AI] Fix custom_upcoming_length not persisting on mobile

The mobile schedule save handler was missing the custom_upcoming_length
field from the payload sent to schedule/create and schedule/update.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: youngcw <calebyoung94@gmail.com>
2026-04-22 16:33:21 +00:00
Matt Fiddaman
9d91da77ec move from tsgo dev preview to beta (#7587)
* move from tsgo dev preview to beta

* note
2026-04-22 15:22:14 +00:00
Copilot
1c97388654 [AI] Consolidate npm release and nightly publishing into one workflow (#7583)
* [AI] Unify npm release and nightly publish workflows

Agent-Logs-Url: https://github.com/actualbudget/actual/sessions/3f8de051-a9a7-4527-88d8-5c44bc06a562

Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com>

* [AI] Harden unified npm publish workflow conditionals

Agent-Logs-Url: https://github.com/actualbudget/actual/sessions/3f8de051-a9a7-4527-88d8-5c44bc06a562

Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com>

* [AI] Clarify nightly install step and add concise release note

Agent-Logs-Url: https://github.com/actualbudget/actual/sessions/af3d68aa-d217-47be-addb-1b40b08f533b

Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com>

* [AI] Revert release note edit and make npm publish workflow ACT-compatible (#7584)

* Initial plan

* [AI] Revert release note edit and validate workflow with act

Agent-Logs-Url: https://github.com/actualbudget/actual/sessions/df98a192-197a-4df4-a804-80b69116f742

Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com>
2026-04-22 15:18:29 +00:00
Julian Dominguez-Schatz
8323a7d27c Reduce permissions in stale workflow (#7555)
* Restrict permissions on stale workflow

* Add release notes for reducing permissions in stale workflow
2026-04-22 15:17:35 +00:00
Matiss Janis Aboltins
7d4e28041c [AI] Export API models as separate entry point (#7581)
* [AI] Expose API entity types via @actual-app/api/models

Adds a new `./models` subpath export on `@actual-app/api` that re-exports
the public API entity types (`APIAccountEntity`, `APICategoryEntity`,
`APICategoryGroupEntity`, `APIFileEntity`, `APIPayeeEntity`,
`APIScheduleEntity`, `APITagEntity`, `AmountOPType`) from
`@actual-app/core/server/api-models`. Consumers can now import these types
from a stable public entry point instead of reaching into core internals:

    import type {
      APICategoryEntity,
      APICategoryGroupEntity,
    } from '@actual-app/api/models';

Uses `export type *` so the compiled `dist/models.js` is empty and no
runtime code is added. The Vite lib config is expanded to a multi-entry
map (`index`, `models`) so both bundles are produced, and tsgo already
emits `@types/models.d.ts` via the existing `declarationDir` setup.

* Add release notes for PR #7581

* Modify release notes for API model exports

Updated category from 'Features' to 'Enhancements' and added API export details.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-22 10:45:54 +00:00
Matiss Janis Aboltins
3c77b3d0d5 [AI] Add enforce-boundaries ESLint rule for architectural boundaries (#7467)
* [AI] Add enforce-boundaries ESLint rule for architectural boundaries

Disallow tsconfig compilerOptions.paths, Vite resolve.alias, and
backtracked imports (../../) to enforce the use of package.json
subpath imports (#path) as the canonical aliasing mechanism.

The rule is enabled globally as an error without autofixes.

https://claude.ai/code/session_01T7VCnq5Kid7co9vBDPHWmR

* [AI] Fix enforce-boundaries lint violations

Replace backtracked imports (../../) with subpath imports (#path):
- migrations.ts: use #migrations/* mapping
- Formula.tsx: use #components/* mapping
- TransactionsTable.test.tsx: use #mocks/* mapping

Suppress unavoidable violations with oxlint-disable comments:
- preview.tsx: cross-package theme imports (pre-existing TODO)
- vite.desktop.config.ts: handlebars resolve.alias (types require root entry)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [AI] Clean up enforce-boundaries rule: remove redundant comments, optimize Property visitor, add edge-case tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add release notes for PR #7467

* Update category for release notes

Changed category from Enhancements to Maintenance.

* [AI] Fix JSON syntax error after merge

Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com>

* [AI] Merge master and fix lint errors in enforce-boundaries rule

Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com>
2026-04-21 21:18:42 +00:00
Matiss Janis Aboltins
846b6a6b7a [AI] Add nightly CI scan for custom theme catalog (#7566)
* [AI] Add nightly CI scan for custom theme catalog

Adds a scheduled GitHub Actions workflow that fetches `actual.css` from
every repo in `customThemeCatalog.json` and runs it through the same
`embedThemeFonts` + `validateThemeCss` pipeline the app uses at install
time. Failing themes fail the job so maintainers get an alert when a
third-party repo introduces a regression.

The scan treats fetched CSS as opaque text: never executed, never
injected into a DOM, size-capped at 512 KB per file, 15s per fetch,
restricted to raw.githubusercontent.com with redirects disabled, and
run with `contents: read` permissions only. Each catalog `repo` is
schema-checked against `owner/repo` before being interpolated into
the URL.

* [AI] Simplify theme catalog scan

- Reuse `CatalogTheme` type from customThemes instead of duplicating as
  `CatalogEntry` in the script.
- Hoist `appendFileSync` to the static `node:fs` import; drop the dynamic
  import inside `writeStepSummary`.
- Drop the narrative header docstring and the trailing `// ...` comments
  that just restated constant names.
- Drop the redundant URL-prefix re-check inside the CSS fetch helper;
  the single call site constructs the URL from a pinned literal.
- Drop the 250 ms inter-request delay (GitHub Raw rate limits are not
  relevant for 21 requests, and the trailing delay was idle wall-clock
  against the 10-min job budget).
- Give each font fetch inside `embedThemeFonts` its own 15 s timeout
  via `AbortSignal.any`, instead of sharing one signal across every
  font in a theme. Drop the now-unnecessary caller-supplied signal
  from the CI call site.

* [AI] Fix lint on theme catalog scan imports
2026-04-21 21:18:21 +00:00
Julian Dominguez-Schatz
07c71154c9 Enable trusted publishing for releases (#7579)
* Enable trusted publishing for releases

* Add release notes for PR #7579

* Update 7579.md

* [autofix.ci] apply automated fixes

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-21 18:34:38 +00:00
Matt Fiddaman
2f49c5c400 add repository details to package.json files (#7578)
* add package URLs

* note
2026-04-21 17:40:11 +00:00
Matt Fiddaman
4b28a8146e fix error when clearing the payee field of a transaction (#7532)
* treat undefined values as missing in updates

* note
2026-04-21 17:30:45 +00:00
Matiss Janis Aboltins
362d8d60e4 [AI] Optimize CI e2e tests with pre-built bundle serving (#7503)
* [AI] Speed up and stabilize Playwright e2e tests

- Serve the prebuilt browser bundle via bin/serve-build.mjs in CI to
  skip per-shard Vite startup; 3-shard matrix with 4 workers each.
- Disable CSS animations in non-VRT runs via a fixture-level init
  script; bump expect timeout to 10s for AutoSizer-bound assertions.
- Use page.evaluate() for React Aria button clicks and a native value
  setter + single input event for controlled-input fills to eliminate
  React Aria re-render races in createAccount and Payee/Category
  autocompletes.
- Click the matching option directly (instead of Enter on a not-yet-
  highlighted list) in mobile transaction and schedule autocompletes.
- FocusableAmountInput.applyText reads the DOM input value so the
  typed amount survives a blur that fires before React flushes the
  onChange state update under CPU contention.
- MobileTransactionEntryPage.fillAmount waits for the outer display
  button (reads parent props.value) so async rules-run completes
  before the next fillField snapshots the transaction.
- MobileNavigation dispatches nav link clicks through evaluate() to
  bypass Playwright's viewport-stability check against the navbar's
  react-spring transforms.
- MobileBudgetPage summary-button lookups use locator.or().waitFor()
  instead of an isVisible() cascade.
- ConfigurationPage.startFresh/createTestFile wait for the account
  header / budget table to mount before returning.
- Workflow hardening: persist-credentials=false on all actions/checkout
  and top-level permissions: contents: read (zizmor findings).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Apply animation-disable init script to browser.newPage pages

The previous implementation extended the test-scoped `page` fixture,
but every test creates its own page via `browser.newPage()` and never
uses the fixture-provided page — so the init script was a no-op in
every test.

Move the wrap to the worker-scoped `browser` fixture: intercept
`browser.newPage` so each page created that way has `addInitScript`
applied before the caller can navigate to it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:03:56 +00:00
Julian Dominguez-Schatz
664cfdf244 Force node version 24 for trusted publishing (#7577)
* Force node version 24 for trusted publishing

* Add release notes for PR #7577

* Enable check-latest for npm setup action

* Update nightly package publishing workflow to Node.js 24

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-21 16:44:03 +00:00