[AI] Enforce file access authorization on sync API endpoints#7040
[AI] Enforce file access authorization on sync API endpoints#7040MatissJanis merged 12 commits intomasterfrom
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
✅ Deploy Preview for actualbudget ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a centralized file-access authorization helper used across sync-server routes, updates tests to validate admin vs non-owner access and simplified error payloads, introduces a migration to backfill NULL file owners, and adds release notes describing the bugfix. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client as Client
participant App as SyncServer (app-sync)
participant DB as Database
participant FS as FileStore
Client->>App: Request (route with fileId, token)
App->>DB: verifyFileExists(fileId)
DB-->>App: file
App->>DB: UserService.countUserAccess / requireFileAccess(file, userId)
alt access allowed (owner or admin or granted access)
App->>FS: read/write file as needed
FS-->>App: file data / ack
App-->>Client: 200 + payload
else access denied
App-->>Client: 403 "file-access-not-allowed"
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/sync-server/src/app-sync.ts (1)
278-291:⚠️ Potential issue | 🟡 MinorAuth check should precede
validateUploadedFileto prevent file-state disclosure.For an existing file,
validateUploadedFilecan return'file-has-reset'or'file-has-new-key'to the caller before the 403 is emitted. An attacker who knows a validfileIdcan probe these responses to learn that the file'sgroupIdorencryptKeyIdhas changed — metadata leakage without having access to the file. Moving the auth check above the validation call closes this.🛡️ Suggested re-ordering
- const errorMessage = validateUploadedFile(groupId, keyId, currentFile); - if (errorMessage) { - res.status(400).send(errorMessage); - return; - } - const fileAccessError = currentFile ? requireFileAccess(currentFile, res.locals.user_id) : null; if (fileAccessError) { res.status(403); res.send(fileAccessError); return; } + + const errorMessage = validateUploadedFile(groupId, keyId, currentFile); + if (errorMessage) { + res.status(400).send(errorMessage); + return; + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.ts` around lines 278 - 291, The validation call validateUploadedFile(currentFile, ...) is leaking file-state details before the authorization check—move the requireFileAccess(currentFile, res.locals.user_id) block to run before calling validateUploadedFile so that for existing files you first verify access and return 403 if unauthorized; only after requireFileAccess succeeds (and currentFile is confirmed accessible) call validateUploadedFile and then return 400 on its errors. Ensure you reference currentFile, requireFileAccess, validateUploadedFile, and res.locals.user_id when making the change.
🧹 Nitpick comments (2)
packages/sync-server/src/app-sync.ts (1)
488-501:/delete-user-fileduplicates therequireFileAccesspredicate instead of reusing it.The ownership+admin check logic on lines 491–494 is identical to what
requireFileAccessdoes. The error format differs (a JSON body vs the plain-text string), but the predicate can still delegate torequireFileAccess:♻️ Proposed refactor
- const { user_id: userId } = res.locals; - - const isOwner = file.owner === userId; - const isServerAdmin = isAdmin(userId); - - if (!isOwner && !isServerAdmin) { + if (requireFileAccess(file, res.locals.user_id)) { res.status(403).send({ status: 'error', reason: 'forbidden', details: 'file-delete-not-allowed', }); return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.ts` around lines 488 - 501, The file-delete handler duplicates the ownership/admin check; replace the inline isOwner/isServerAdmin logic with a call to the existing requireFileAccess predicate so we reuse authorization logic: invoke requireFileAccess (the same function/middleware used elsewhere) to validate access for the current user and file, and if it denies access return the same 403 JSON response currently used in this handler; remove the duplicated isOwner/isServerAdmin branch and any direct calls to isAdmin in this handler so authorization is centralized via requireFileAccess.packages/sync-server/src/app-sync.test.ts (1)
75-89: Missing admin-bypass coverage for the new access-controlled endpoints.All eight new 403 tests verify that a non-owner is rejected, but none verify the complement: that an admin can access files owned by someone else. The existing
/delete-user-filetest suite has this pattern (lines 917–941). Adding a matching admin-bypass test for at least one representative endpoint (e.g.,/user-get-keyor/sync) would close the coverage gap symmetrically.Also applies to: 114-133, 227-241, 455-489, 568-586, 638-652, 783-797, 1079-1099
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 75 - 89, Add a complementary admin-bypass test: generate a fileId and insert a files row via getAccountDb().mutate(...) with owner = OTHER_USER_ID (same as the failing test), then call request(app).post('/user-get-key') with header 'x-actual-token' set to 'valid-token-admin' (or whatever admin token is used in the suite) and the same body { fileId }; assert the response is allowed (status 200) and contains the expected encryption info (e.g., the encrypt_test/encrypt_keyid value you injected). This mirrors the non-owner 403 test but uses the admin token to verify admins can bypass ownership checks for the '/user-get-key' endpoint.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/sync-server/src/app-sync.ts`:
- Around line 278-291: The validation call validateUploadedFile(currentFile,
...) is leaking file-state details before the authorization check—move the
requireFileAccess(currentFile, res.locals.user_id) block to run before calling
validateUploadedFile so that for existing files you first verify access and
return 403 if unauthorized; only after requireFileAccess succeeds (and
currentFile is confirmed accessible) call validateUploadedFile and then return
400 on its errors. Ensure you reference currentFile, requireFileAccess,
validateUploadedFile, and res.locals.user_id when making the change.
---
Nitpick comments:
In `@packages/sync-server/src/app-sync.test.ts`:
- Around line 75-89: Add a complementary admin-bypass test: generate a fileId
and insert a files row via getAccountDb().mutate(...) with owner = OTHER_USER_ID
(same as the failing test), then call request(app).post('/user-get-key') with
header 'x-actual-token' set to 'valid-token-admin' (or whatever admin token is
used in the suite) and the same body { fileId }; assert the response is allowed
(status 200) and contains the expected encryption info (e.g., the
encrypt_test/encrypt_keyid value you injected). This mirrors the non-owner 403
test but uses the admin token to verify admins can bypass ownership checks for
the '/user-get-key' endpoint.
In `@packages/sync-server/src/app-sync.ts`:
- Around line 488-501: The file-delete handler duplicates the ownership/admin
check; replace the inline isOwner/isServerAdmin logic with a call to the
existing requireFileAccess predicate so we reuse authorization logic: invoke
requireFileAccess (the same function/middleware used elsewhere) to validate
access for the current user and file, and if it denies access return the same
403 JSON response currently used in this handler; remove the duplicated
isOwner/isServerAdmin branch and any direct calls to isAdmin in this handler so
authorization is centralized via requireFileAccess.
…iles for other users - Implemented a test for admin access to retrieve encryption keys for another user's file in the /user-get-key endpoint. - Added a test for admin users to sync another user's file in the /sync endpoint, ensuring proper response and headers. These changes enhance the authorization checks for admin actions on user files.
There was a problem hiding this comment.
🧹 Nitpick comments (5)
packages/sync-server/src/app-sync.test.ts (3)
1147-1159:groupIdparameter type should bestring | null
addMockFileis called withnullforgroupIdat line 1073. The@ts-strict-ignorebanner suppresses the diagnostic, but tightening the type makes the intent explicit and avoids silent bugs if strict mode is ever re-enabled.♻️ Proposed fix
function addMockFile( fileId: string, - groupId: string, + groupId: string | null, keyId: string, encryptMeta: string, syncVersion: number, owner: string = 'genericAdmin', ) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 1147 - 1159, The addMockFile helper currently types groupId as string but callers sometimes pass null; update the function signature for addMockFile to accept groupId: string | null and ensure the SQL bind uses that value directly (allowing null to be inserted) so callers no longer need `@ts-strict-ignore`; locate the addMockFile function and change its parameter type and any related test-call sites if necessary to match the new union type.
481-515: UseonTestFinishedto guarantee file cleanup on assertion failuresBoth new tests call
fs.unlinkSyncafter theexpectassertions. If any assertion throws, the temp file is left on disk and can pollute subsequent test runs.♻️ Proposed fix for both tests
it('returns 403 when non-owner overwrites another user file', async () => { const fileId = crypto.randomBytes(16).toString('hex'); // ... fs.writeFileSync(getPathForUserFile(fileId), 'existing content'); + onTestFinished(() => { + try { fs.unlinkSync(getPathForUserFile(fileId)); } catch { /* already removed */ } + }); // ... - fs.unlinkSync(getPathForUserFile(fileId)); });Apply the same pattern to the
'returns 403 when non-owner downloads another user file'test.Also applies to: 594-612
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 481 - 515, The tests 'returns 403 when non-owner overwrites another user file' and 'returns 403 when non-owner downloads another user file' currently call fs.unlinkSync(getPathForUserFile(fileId)) after assertions, which leaves temp files if an assertion fails; modify both tests to register cleanup with onTestFinished(() => fs.unlinkSync(getPathForUserFile(fileId))) immediately after creating the temp file (before any assertions) so the file is always removed, referencing the existing getPathForUserFile and fileId variables and removing the trailing direct fs.unlinkSync calls at the end of each test.
75-115: 403/admin coverage LGTM; consider adding admin-access tests for remaining endpointsAll new 403 tests correctly assert both the status code and the
'file-access-not-allowed'text body. Admin bypass tests exist for/user-get-keyand/sync, but are absent for/user-create-key,/reset-user-file,/upload-user-file,/download-user-file,/update-user-filename, and/get-user-file-info. Not a blocker, but parity would strengthen the test suite.Also applies to: 1101-1144
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 75 - 115, Add parity admin-access tests for the remaining endpoints listed in the review so admins can bypass file-owner restrictions: create tests in the same test suite that insert a file row (like the existing tests that set encrypt_salt/encrypt_keyid/encrypt_test and owner = OTHER_USER_ID) and then call each endpoint '/user-create-key', '/reset-user-file', '/upload-user-file', '/download-user-file', '/update-user-filename', and '/get-user-file-info' using the admin token header ('x-actual-token' = 'valid-token-admin'), asserting a 200 response (or the expected success payload) and confirming the returned data matches the inserted values; mirror the non-owner 403 tests by also keeping a non-admin request for each endpoint that asserts 403 and 'file-access-not-allowed' to ensure coverage of both branches.packages/sync-server/src/app-sync.ts (2)
178-178: Inconsistent error string:'file not found'vs'file-not-found'Both lines pass
'file not found'(human-readable, space-separated) toverifyFileExists, while every other call in this file uses kebab-case ('file-not-found'or a structured object). Standardizing to'file-not-found'would require updating the corresponding pre-existing test assertions at lines 137 and 634 of the test file, but the inconsistency is worth cleaning up.♻️ Proposed change (requires paired test updates)
- const file = verifyFileExists(fileId, filesService, res, 'file not found'); + const file = verifyFileExists(fileId, filesService, res, 'file-not-found');Also applies to: 387-387
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.ts` at line 178, The error string passed to verifyFileExists is inconsistent: replace the human-readable 'file not found' with the kebab-case 'file-not-found' wherever verifyFileExists(fileId, filesService, res, 'file not found') is used (e.g., the call in app-sync.ts that uses variables fileId, filesService, res and the other similar call), and update the corresponding test assertions that expect the old string so they assert 'file-not-found' instead; ensure you only change the string literals passed to verifyFileExists and keep the function signature and surrounding logic unchanged.
71-78: Operational concern: legacy files without anownerwill be inaccessible to non-admin users
file.owner === userIdevaluates tofalsewhenfile.ownerisnullor''(i.e., files created before owner-tracking was introduced). Such files will return403for any non-admin user, even the original uploader.Before deploying, confirm that all pre-existing rows in the
filestable have a populatedowner, or add a data migration to back-fill theownerfrom upload history. Admin users are unaffected.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.ts` around lines 71 - 78, requireFileAccess currently denies access when file.owner is null/empty causing legacy uploads to be inaccessible; fix this by either adding a data migration to backfill file.owner from upload history before deploying OR change requireFileAccess to treat missing owners specially: if file.owner is falsy, look up the original uploader (e.g., via the upload record or a field like file.uploaderId) and compare that uploaderId to userId, and only deny when neither the uploader nor isAdmin(userId) matches; update the requireFileAccess function and any call sites to use this lookup so pre-existing files are accessible to their original uploader.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/sync-server/src/app-sync.test.ts`:
- Around line 1147-1159: The addMockFile helper currently types groupId as
string but callers sometimes pass null; update the function signature for
addMockFile to accept groupId: string | null and ensure the SQL bind uses that
value directly (allowing null to be inserted) so callers no longer need
`@ts-strict-ignore`; locate the addMockFile function and change its parameter type
and any related test-call sites if necessary to match the new union type.
- Around line 481-515: The tests 'returns 403 when non-owner overwrites another
user file' and 'returns 403 when non-owner downloads another user file'
currently call fs.unlinkSync(getPathForUserFile(fileId)) after assertions, which
leaves temp files if an assertion fails; modify both tests to register cleanup
with onTestFinished(() => fs.unlinkSync(getPathForUserFile(fileId))) immediately
after creating the temp file (before any assertions) so the file is always
removed, referencing the existing getPathForUserFile and fileId variables and
removing the trailing direct fs.unlinkSync calls at the end of each test.
- Around line 75-115: Add parity admin-access tests for the remaining endpoints
listed in the review so admins can bypass file-owner restrictions: create tests
in the same test suite that insert a file row (like the existing tests that set
encrypt_salt/encrypt_keyid/encrypt_test and owner = OTHER_USER_ID) and then call
each endpoint '/user-create-key', '/reset-user-file', '/upload-user-file',
'/download-user-file', '/update-user-filename', and '/get-user-file-info' using
the admin token header ('x-actual-token' = 'valid-token-admin'), asserting a 200
response (or the expected success payload) and confirming the returned data
matches the inserted values; mirror the non-owner 403 tests by also keeping a
non-admin request for each endpoint that asserts 403 and
'file-access-not-allowed' to ensure coverage of both branches.
In `@packages/sync-server/src/app-sync.ts`:
- Line 178: The error string passed to verifyFileExists is inconsistent: replace
the human-readable 'file not found' with the kebab-case 'file-not-found'
wherever verifyFileExists(fileId, filesService, res, 'file not found') is used
(e.g., the call in app-sync.ts that uses variables fileId, filesService, res and
the other similar call), and update the corresponding test assertions that
expect the old string so they assert 'file-not-found' instead; ensure you only
change the string literals passed to verifyFileExists and keep the function
signature and surrounding logic unchanged.
- Around line 71-78: requireFileAccess currently denies access when file.owner
is null/empty causing legacy uploads to be inaccessible; fix this by either
adding a data migration to backfill file.owner from upload history before
deploying OR change requireFileAccess to treat missing owners specially: if
file.owner is falsy, look up the original uploader (e.g., via the upload record
or a field like file.uploaderId) and compare that uploaderId to userId, and only
deny when neither the uploader nor isAdmin(userId) matches; update the
requireFileAccess function and any call sites to use this lookup so pre-existing
files are accessible to their original uploader.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/sync-server/src/app-sync.test.ts`:
- Around line 75-115: The test suite never triggers the requireFileAccess branch
that grants access via UserService.countUserAccess because existing tests either
use the owner or an admin; add a new test in app-sync.test.ts that inserts a
files row with owner != TEST_USER and then inserts a user_access row for a
non-owner/non-admin user (not the file owner or admin) so that
UserService.countUserAccess > 0 is true, then call the /download-user-file
endpoint (or another endpoint that uses requireFileAccess) with that non-owner
user's token and assert a 200 response (not 403) and expected body, ensuring the
test references requireFileAccess and UserService.countUserAccess behavior
rather than owner/admin shortcuts.
This test verifies that users with appropriate access can download files owned by others, utilizing the requireFileAccess logic and UserService.countUserAccess. It ensures correct response headers and content delivery for shared files.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/sync-server/src/app-sync.test.ts (1)
415-419: MoveonTestFinishedcleanup to the top of each test, before any assertions.
onTestFinishedis only registered if execution reaches that line. When an assertion throws first, the cleanup is never scheduled and the temp file leaks. This same pattern is repeated at lines 487-491, 585-589, 635-639, 736-740, 761-765, and 798-802.♻️ Proposed fix (same pattern applies to all affected tests)
it('uploads a new file successfully', async () => { const fileId = crypto.randomBytes(16).toString('hex'); const filePath = getPathForUserFile(fileId); + onTestFinished(() => { + try { + fs.unlinkSync(filePath); + } catch {} + }); + // ... test body and assertions ... - - onTestFinished(() => { - try { - fs.unlinkSync(filePath); - } catch {} - }); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 415 - 419, The cleanup registration using onTestFinished(() => { try { fs.unlinkSync(filePath); } catch {} }) must be moved to the very start of each test (immediately after the temp file is created) so it is always registered even if an assertion throws; locate each test that currently registers onTestFinished right before/after assertions (look for onTestFinished, fs.unlinkSync and filePath in the test bodies) and hoist that registration to the top of the test block, preserving the try/catch and filePath reference so the temp file is reliably unlinked; apply the same change to all repeated occurrences found in the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/sync-server/src/app-sync.test.ts`:
- Around line 768-803: The review comment is a duplicate meta-tag
([duplicate_comment]) and not a code issue; no changes to the test are
required—leave the test "allows non-owner with user_access to download via
requireFileAccess (UserService.countUserAccess > 0)" as written, remove the
duplicate meta-tag from the review/PR comment, and mark the change approved.
---
Nitpick comments:
In `@packages/sync-server/src/app-sync.test.ts`:
- Around line 415-419: The cleanup registration using onTestFinished(() => { try
{ fs.unlinkSync(filePath); } catch {} }) must be moved to the very start of each
test (immediately after the temp file is created) so it is always registered
even if an assertion throws; locate each test that currently registers
onTestFinished right before/after assertions (look for onTestFinished,
fs.unlinkSync and filePath in the test bodies) and hoist that registration to
the top of the test block, preserving the try/catch and filePath reference so
the temp file is reliably unlinked; apply the same change to all repeated
occurrences found in the file.
…inished for improved error handling This update consolidates file cleanup logic in the test suite, ensuring that temporary files are removed after each test execution. The changes enhance the reliability of tests by consistently managing file state across various scenarios.
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
packages/sync-server/src/app-sync.ts (2)
72-82:isAdminis always eagerly evaluated, even when the user is already the file owner.Lines 73–74 compute both
isOwnerandisServerAdminup-front. SinceisAdminperforms a DB query (hasPermission), it fires on every access-checked request — including those from the file's owner — adding an unnecessary round-trip.⚡ Proposed fix (short-circuit evaluation)
function requireFileAccess(file: File, userId: string) { - const isOwner = file.owner === userId; - const isServerAdmin = isAdmin(userId); - if (isOwner || isServerAdmin) { + if (file.owner === userId || isAdmin(userId)) { return null; } if (UserService.countUserAccess(file.id, userId) > 0) { return null; } return 'file-access-not-allowed'; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.ts` around lines 72 - 82, The requireFileAccess function eagerly calls isAdmin even when the caller is the file owner; change it so isAdmin(userId) is only invoked if the ownership check fails: compute isOwner first, return null immediately if true, then call isAdmin(userId) and proceed with the existing logic (fall back to UserService.countUserAccess(file.id, userId) if not admin). This keeps the short-circuit behavior in requireFileAccess and avoids unnecessary DB calls inside isAdmin/hasPermission.
72-82:isAdminis always eagerly evaluated, even when the user is already the file owner.Both
isOwner(Line 73) andisServerAdmin(Line 74) are computed before theifcheck, soisAdmin(userId)— which hits the DB — fires on every request even whenfile.owner === userId.⚡ Proposed fix (lazy short-circuit)
function requireFileAccess(file: File, userId: string) { - const isOwner = file.owner === userId; - const isServerAdmin = isAdmin(userId); - if (isOwner || isServerAdmin) { + if (file.owner === userId || isAdmin(userId)) { return null; } if (UserService.countUserAccess(file.id, userId) > 0) { return null; } return 'file-access-not-allowed'; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.ts` around lines 72 - 82, In requireFileAccess, avoid eagerly calling isAdmin(userId): first check isOwner (file.owner === userId) and return null immediately if true, and only then call isAdmin(userId) to set isServerAdmin; keep the existing fallback to UserService.countUserAccess(file.id, userId) as before. If isAdmin is async, await it when called; otherwise call it synchronously — the key change is to compute isAdmin only when isOwner is false.packages/sync-server/src/app-sync.test.ts (2)
760-794: Missing DB-row cleanup for theuser_accessentry.
onTestFinishedat line 774 cleans up the on-disk file, but theuser_accessrow inserted at lines 770–773 is never deleted. SincefileIdis random there is no collision risk, but orphaned rows accumulate across test runs.🧹 Suggested fix
getAccountDb().mutate( 'INSERT INTO user_access (file_id, user_id) VALUES (?, ?)', [fileId, 'genericUser'], ); + onTestFinished(() => { + getAccountDb().mutate( + 'DELETE FROM user_access WHERE file_id = ?', + [fileId], + ); + }); onTestFinished(() => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 760 - 794, The test inserts a user_access row for fileId but never cleans it up; update the onTestFinished callback used for file cleanup to also delete the DB rows you created (at least the user_access row for that fileId, and optionally the files row) by calling getAccountDb().mutate('DELETE FROM user_access WHERE file_id = ?', [fileId]) (and/or getAccountDb().mutate('DELETE FROM files WHERE id = ?', [fileId])); place these deletes inside the existing onTestFinished block so all created state (disk file and DB rows) is removed after the test.
760-794: Missing DB cleanup for theuser_accessrow inserted in thecountUserAccesstest.The
onTestFinishedcallback at line 774 correctly removes the filesystem file, but theuser_accessrow at lines 770–773 is never removed. While the randomfileIdprevents primary-key collisions, orphaned rows accumulate across runs in shared test databases.🧹 Suggested cleanup addition
+ onTestFinished(() => { + getAccountDb().mutate( + 'DELETE FROM user_access WHERE file_id = ?', + [fileId], + ); + }); onTestFinished(() => { try { fs.unlinkSync(getPathForUserFile(fileId)); } catch {} });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sync-server/src/app-sync.test.ts` around lines 760 - 794, The test inserts a user_access row but never removes it; update the onTestFinished cleanup for the test that defines fileId to also delete the inserted user_access row by calling getAccountDb().mutate to delete from user_access where file_id = fileId (use the same fileId variable) so the test removes the DB row in addition to unlinking the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/sync-server/src/app-sync.test.ts`:
- Around line 760-794: The test inserts a user_access row for fileId but never
cleans it up; update the onTestFinished callback used for file cleanup to also
delete the DB rows you created (at least the user_access row for that fileId,
and optionally the files row) by calling getAccountDb().mutate('DELETE FROM
user_access WHERE file_id = ?', [fileId]) (and/or getAccountDb().mutate('DELETE
FROM files WHERE id = ?', [fileId])); place these deletes inside the existing
onTestFinished block so all created state (disk file and DB rows) is removed
after the test.
- Around line 760-794: The test inserts a user_access row but never removes it;
update the onTestFinished cleanup for the test that defines fileId to also
delete the inserted user_access row by calling getAccountDb().mutate to delete
from user_access where file_id = fileId (use the same fileId variable) so the
test removes the DB row in addition to unlinking the file.
In `@packages/sync-server/src/app-sync.ts`:
- Around line 72-82: The requireFileAccess function eagerly calls isAdmin even
when the caller is the file owner; change it so isAdmin(userId) is only invoked
if the ownership check fails: compute isOwner first, return null immediately if
true, then call isAdmin(userId) and proceed with the existing logic (fall back
to UserService.countUserAccess(file.id, userId) if not admin). This keeps the
short-circuit behavior in requireFileAccess and avoids unnecessary DB calls
inside isAdmin/hasPermission.
- Around line 72-82: In requireFileAccess, avoid eagerly calling
isAdmin(userId): first check isOwner (file.owner === userId) and return null
immediately if true, and only then call isAdmin(userId) to set isServerAdmin;
keep the existing fallback to UserService.countUserAccess(file.id, userId) as
before. If isAdmin is async, await it when called; otherwise call it
synchronously — the key change is to compute isAdmin only when isOwner is false.
* [AI] Enforce file access authorization on sync API endpoints Co-authored-by: Cursor <cursoragent@cursor.com> * Refactor file deletion authorization to return error message as text * Refactor file upload validation to improve error handling * Add tests to allow admin users to retrieve encryption keys and sync files for other users - Implemented a test for admin access to retrieve encryption keys for another user's file in the /user-get-key endpoint. - Added a test for admin users to sync another user's file in the /sync endpoint, ensuring proper response and headers. These changes enhance the authorization checks for admin actions on user files. * Refactor file cleanup in tests to use onTestFinished for better error handling * Enhance admin capabilities in file management tests * Add migration to backfill file owners with admin ID * Enhance file access authorization in sync API * Update migration to backfill file owners with admin ID to ensure consistent ordering in the query * Refactor access control tests for file downloads in sync API * Add test for non-owner file download access via user_access in sync API This test verifies that users with appropriate access can download files owned by others, utilizing the requireFileAccess logic and UserService.countUserAccess. It ensures correct response headers and content delivery for shared files. * Refactor file cleanup in upload and download tests to utilize onTestFinished for improved error handling This update consolidates file cleanup logic in the test suite, ensuring that temporary files are removed after each test execution. The changes enhance the reliability of tests by consistently managing file state across various scenarios. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…udget#7040) * [AI] Enforce file access authorization on sync API endpoints Co-authored-by: Cursor <cursoragent@cursor.com> * Refactor file deletion authorization to return error message as text * Refactor file upload validation to improve error handling * Add tests to allow admin users to retrieve encryption keys and sync files for other users - Implemented a test for admin access to retrieve encryption keys for another user's file in the /user-get-key endpoint. - Added a test for admin users to sync another user's file in the /sync endpoint, ensuring proper response and headers. These changes enhance the authorization checks for admin actions on user files. * Refactor file cleanup in tests to use onTestFinished for better error handling * Enhance admin capabilities in file management tests * Add migration to backfill file owners with admin ID * Enhance file access authorization in sync API * Update migration to backfill file owners with admin ID to ensure consistent ordering in the query * Refactor access control tests for file downloads in sync API * Add test for non-owner file download access via user_access in sync API This test verifies that users with appropriate access can download files owned by others, utilizing the requireFileAccess logic and UserService.countUserAccess. It ensures correct response headers and content delivery for shared files. * Refactor file cleanup in upload and download tests to utilize onTestFinished for improved error handling This update consolidates file cleanup logic in the test suite, ensuring that temporary files are removed after each test execution. The changes enhance the reliability of tests by consistently managing file state across various scenarios. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…#7040) * [AI] Enforce file access authorization on sync API endpoints Co-authored-by: Cursor <cursoragent@cursor.com> * Refactor file deletion authorization to return error message as text * Refactor file upload validation to improve error handling * Add tests to allow admin users to retrieve encryption keys and sync files for other users - Implemented a test for admin access to retrieve encryption keys for another user's file in the /user-get-key endpoint. - Added a test for admin users to sync another user's file in the /sync endpoint, ensuring proper response and headers. These changes enhance the authorization checks for admin actions on user files. * Refactor file cleanup in tests to use onTestFinished for better error handling * Enhance admin capabilities in file management tests * Add migration to backfill file owners with admin ID * Enhance file access authorization in sync API * Update migration to backfill file owners with admin ID to ensure consistent ordering in the query * Refactor access control tests for file downloads in sync API * Add test for non-owner file download access via user_access in sync API This test verifies that users with appropriate access can download files owned by others, utilizing the requireFileAccess logic and UserService.countUserAccess. It ensures correct response headers and content delivery for shared files. * Refactor file cleanup in upload and download tests to utilize onTestFinished for improved error handling This update consolidates file cleanup logic in the test suite, ensuring that temporary files are removed after each test execution. The changes enhance the reliability of tests by consistently managing file state across various scenarios. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
* Typescript: make arithmetic.ts strict (#6801) * Make arithmetic.ts strict TypeScript compliant - Add type definitions for ParserState, Operator, OperatorNode, and AstNode - Add explicit type annotations to all function parameters - Fix null/undefined handling in parsePrimary function - Remove type assertion in makeOperatorParser by using explicit Operator type - Handle null return from currencyToAmount function - All functions now have proper return type annotations * Add test for ignoring leftover characters in evalArithmetic function * Add oxlint rule against direct theme imports; fix Login OpenID button styles (#6796) Co-authored-by: Michael Clark <5285928+MikesGlitch@users.noreply.github.com> * Improve bug report template with better structure and requirements (#6784) * Improve bug report template with better structure and requirements * Fix: Remove empty value fields from textarea inputs in bug report template * Add release notes for PR #6784 * Update 6784.md * Update bug report template to request a screenshot of the import screen along with a redacted file version for better issue resolution. * Update bug report template for import issues Clarified instructions for reporting import issues. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix translation issue #6828 (#6845) * Fix translation issue #6828 * Add release note * [autofix.ci] apply automated fixes * update release number --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Avoid negative zero in budget summary amounts (#6843) * fix: report widget tooltip z-index (#6849) * Fix sync server migrations (#6346) * Fix sync-server migrations to use ESM loader * Add release notes * Apply CodeRabbit suggestions * [autofix.ci] apply automated fixes * Add file extension filter to sync-server migrations import * [autofix.ci] apply automated fixes * Ensure migrations occur synchronously * [autofix.ci] apply automated fixes * Minor cleanup --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv> Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> * fix(i18n): respect browser preferred languages when supported (#6812) * fix(i18n): respect browser preferred languages when supported Instead of relying on the first browser language, the application now iterates through navigator.languages and selects the first supported locale, with a fallback to English. * chore: add the release notes related file * fix(i18n): check region locales support before falling back to base locale * fix(i18n): make the unit test aligned with the region locales checking * switch to node alpine docker image (#6840) * switch to node alpine image * note * Include scheduled transactions in nYNAB imports (#6844) * Include scheduled transactions in nYNAB imports * Remove logs and restore schedule name from transaction memo * Simplify rule actions * Create schedules with unique names * Set the note rather than append * Update ynab5 demo budget and e2e test * Update findSortUp and findSortDown parameter to be more generic (#6861) * findSortUp and findSortDown is also used for CategoryEntity. Updating type to be more generic. * Generics * Add release notes for PR #6861 * Adjust category to Maintenance based on review feedback (#6865) * Initial plan * Change release notes category to Maintenance Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Use consistent color variables on Budget Page. (#6820) * Change color of budget table scrollbar. * Update budget sidebar to use budget colors. * Update fontWeight for 'Category' to match rest of table * Update to use budget background * Update ExpenseGroup to use budget color * Update IncomeGroup to use budget color * Update SidebarCategory colors Change drag/drop to buttonPrimaryBackground so it will always be visible in any custom theme. Background to budget color. * Update SidebarGroup background to budget color * Update EnvelopeBudgetComponents Add 'budgetNumberNeutral' to cheveronDown in budgeted field instead of using default bare button text incases where bare button is set to normal button text and normal button is inverted. remove mobile color variable for shadow * Update BudgetTotals.tsx Use tableHeaderText for header. * Update BudgetSummary.tsx Use budget colors * Update MonthPicker.tsx change selected months at top from tableBorderHover color to buttonPrimaryBackground. * [autofix.ci] apply automated fixes * Update EnvelopeBudgetComponents.tsx * Update BudgetTotals.tsx revert * Update SidebarCategory.tsx * Update TrackingBudgetComponents to use budget colors * [autofix.ci] apply automated fixes * Update BudgetSummary to use budget colors * Update BudgetTotal.tsx * Update ExpenseProgress.tsx * Update IncomeProgress.tsx * Update Saved.tsx * Use consistent color variables on budget pages. * Update IncomeProgress.tsx * Update ExpenseProgress.tsx * Update VRT screenshots Auto-generated by VRT workflow PR: #6820 * Update EnvelopeBudgetComponents Budget total header to follow current/other month style. * Update EnvelopeBudgetComponents.tsx * [autofix.ci] apply automated fixes * Update EnvelopeBudgetComponents.tsx * Update EnvelopeBudgetComponents.tsx * [autofix.ci] apply automated fixes * Update EnvelopeBudgetComponents.tsx * Revert EnvelopeBudgetComponents.tsx * [autofix.ci] apply automated fixes * Update EnvelopeBudgetComponents.tsx * Update EnvelopeBudgetComponents.tsx * Update EnvelopeBudgetComponents.tsx * Revert again :) EnvelopeBudgetComponents.tsx --------- 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> * fix: isConcise state handling for CashFlow report (#6765) * changes token expiry handling to be automatic sign out (#6798) * changes token expiry handling to be automatic sign out * add release notes --------- Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> * Remove comma from all instances of month-year strings (#6748) * Remove comma from all instances of month-year strings, e.g., "January 2026" rather than "January, 2026" * Update VRT screenshots Auto-generated by VRT workflow PR: #6748 * All updated calls now include `locale` as an argument * Update dependencies in `useEffect` to include `locale` * Reorganized new import * Remove double colon * Consistent trailing commas * Include locale in other dependency arrays * Reorder imports * Update VRT screenshots Auto-generated by VRT workflow PR: #6748 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> * Move redux state to react-query - category states (#5977) * Move redux state to react query - category states * Fix typecheck errors * Fix typecheck errors * Fix typecheck errors * Remove t argument * [autofix.ci] apply automated fixes * Coderabbot suggestion * Code review feedback * Fix type * Coderabbit * Delete useCategoryActions * Fix lint * Use categories from react query cache * Fix typecheck error * Update to use useDeleteCategoryGroupMutation * Coderabbit feedback * Break up useCategoryActions * [autofix.ci] apply automated fixes * Fix typecheck errors * Fix typecheck error * Fix typecheck error * await nested mutations * Await deleteCategory * Rename to sendThrow * Fix lint errors --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Fix react/exhaustive-deps in Modals (#6862) * Fix react/exhaustive-deps in Modals * Add release notes for PR #6862 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix react/exhaustive-deps in PayeeTable (#6863) * Fix react/exhaustive-deps in Modals * Fix react/exhaustive-deps in PayeeTable * Add release notes for PR #6863 * Change category and fix dependency management in PayeeTable Updated category from 'Enhancements' to 'Maintenance' and fixed dependency management in PayeeTable. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix react-hooks/exhaustive-deps in CustomReport (#6867) * Fix react-hooks/exhaustive-deps in CustomReport * Add release notes for PR #6867 * Fix typecheck errors * [autofix.ci] apply automated fixes * Change category to Maintenance and update description * [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> * Fix react-hooks/exhaustive-deps in ImportTransactionsModal (#6868) * Fix react-hooks/exhaustive-deps in ImportTransactionsModal * [autofix.ci] apply automated fixes * Add release notes for PR #6868 * Update category to Maintenance and fix warnings --------- 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> * Apply tag colors to YNAB flag tags (#6866) * Apply tag colors to match YNAB flags * Update tag colors to match YNAB, add description on import * Tighten types * Use custom colors * Use Actual palette equivalents for tag colors * Nitpick fixes * Fix nitpick 'fix' * Handle YNAB flag tag conflicts * Handle YNAB flag tag conflicts without creating separate color tags * Simplify * Reorganize * Fix date range calculation in BudgetAnalysisCard (#6875) * fix: corrected date range calculation in BudgetAnalysisCard using calculateTimeRange * add release note * fix: ensure correct date formatting in BudgetAnalysisCard for start and end dates * fix: rename release note file * Add Catppuccin Themes to custom theme catalog (#6857) * Add Catppuccin Themes to theme catalog * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Avoid duplicate category import errors in YNAB5 importer (#6878) * avoid duplicate category import errors Add normalizeError helper function * Add release notes file * Fix react-hooks/exhaustive-deps in DateSelect (#6864) * Fix react-hooks/exhaustive-deps in DateSelect * Add release notes for PR #6864 * Fix remaining suppressions * Change category to Maintenance and fix linting issues Updated category from Enhancements to Maintenance and fixed linting issues related to react-hooks/exhaustive-deps in DateSelect. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Add build-electron to tsconfig excludes (#6883) * Add build-electron to tsconfig excludes * Add release notes for PR #6883 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Add bank sync option to update dates. (#6850) Signed-off-by: Christian Speich <christian@spei.ch> * Add new theme 'You Need A Dark Mode' to catalog (#6891) * Add new theme 'You Need A Dark Mode' to catalog * Add 'You Need A Dark Mode' theme to catalog * Update the Create Linked Account workflow to prompt for Starting Date and Balance (#6629) * feat: Add optional starting date and balance for bank sync accounts Adds the ability to specify a custom starting date and balance when linking new bank sync accounts in the Select Linked Accounts modal. Addresses: https://discord.com/channels/937901803608096828/1402270361625563186 Changes: - Frontend: Added inline date and amount input fields in the account linking table for new accounts - Redux: Extended link account actions to accept startingDate and startingBalance parameters - Backend: Updated account linking handlers to pass custom values to sync logic - Sync: Modified syncAccount and processBankSyncDownload to use custom starting date/balance for initial sync transactions Features: - Only displays starting options when creating new accounts (not upgrades) - AmountInput with smart sign detection based on account balance (negative for credit cards/loans) - Defaults to 90 days ago for date and 0 for balance - Mobile-responsive with separate AccountCard layout - Works across all sync providers: GoCardless, SimpleFIN, Pluggy.ai The custom starting balance is used directly for the starting balance transaction, and the custom starting date determines both the sync start date and the transaction date for the starting balance entry. * refactor: Extract shared types and components for starting balance inputs - Create CustomStartingSettings type to replace repeated inline type definitions - Extract StartingOptionsInput component to consolidate duplicate UI between mobile/desktop views - Create LinkAccountBasePayload type shared across GoCardless, SimpleFIN, and PluggyAI link functions - Apply same base type pattern to server-side link account handlers This simplifies the code introduced for custom starting date/balance when linking bank accounts. [autofix.ci] apply automated fixes * allow explicit zero values * refactor: add type guard for BankSyncError to remove oxlint-disable - Create isBankSyncError() type guard function with proper type narrowing - Remove oxlint-disable-next-line comment that suppressed the no-explicit-any rule - Add JSDoc comments for both isBankSyncError and handleSyncError functions - Remove redundant type assertion now that type guard narrows correctly * refactor: address code review nitpicks for SelectLinkedAccountsModal - Use locale-aware date formatting instead of toISOString() - Extract isNewAccountOption helper to reduce duplication - Align AccountCardProps type definition pattern with TableRowProps * Add placeholder date/balance for already linked accounts * [autofix.ci] apply automated fixes * Use StartingBalanceInfo only, and add mobile view --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * :art: Storybook docs for block, card, colorpicker, formerror (#6874) * storybook docs for block, card, colorpicker, formerror * release notes * Fix Ctrl+Enter losing amount value when adding transaction (#6911) * Fix Ctrl+Enter losing amount value when adding transaction Fixes #6901 When using Ctrl+Enter to add a transaction immediately after typing in the amount field, the value wasn't being committed before the transaction was saved, resulting in a zero amount. The fix wraps the add-and-close logic in an afterSave() callback to ensure field values are committed before adding the transaction. Added regression tests for both debit and credit fields to verify the fix works correctly. * Add release notes for PR #6911 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * Fix feedback link for budget analysis report experimental flag (#6914) * :electron: Flathub PR to be draft on release (#6910) * make flathub pr draft so that we dont attract attention * release notes * grammar * Points: pay for contributions (#6481) * Add point totals display to all statistics sections in count-points script * Update funding contributors documentation and add release notes for contributor point counting script * Refactor contributor points calculation and enhance PR category determination - Updated point values for PR contributions: reduced points for Features, Enhancements, Bugfix, and Maintenance, and added a new category for Unknown contributions. - Introduced a new function to retrieve the last commit SHA before a specified date to improve accuracy in reading release notes. - Modified the getPRCategoryAndPoints function to accept a monthEnd parameter for better context in point assignment. * Update contributor points values in count-points script to reflect new scoring system * Add new blog post on funding contributors' next steps This post outlines plans to expand the contributor compensation system, including broader rewards for project involvement, targeted donations, and a points-based system for feature work. It emphasizes transparency and community feedback in shaping future funding strategies. * Increase Bugfix points from 2 to 3 * Change points awarded for Features to 2 * Enforce consistent TypeScript type import style (#6805) * Refactor: extract tooltip components and clean up lint suppressions (#6721) * Refactor: extract tooltip components and clean up lint suppressions Extract CustomTooltip components from CrossoverGraph and NetWorthGraph to module level to fix unstable nested components lint warnings. Also consolidate theme file lint rule into oxlintrc.json and add proper typing to styles object. * Add release notes for maintenance updates addressing lint violations * Remove style prop from CustomTooltip to prevent container layout styles from affecting tooltip Co-authored-by: matiss <matiss@mja.lv> * Refactor NetWorthGraph component by extracting TrendTooltip and StackedTooltip into separate functions for improved readability and maintainability. Update tooltip props to include necessary parameters for rendering. Clean up unused code and enhance tooltip styling. * Refactor NetWorthGraph component to streamline tooltip handling - Removed unnecessary prop passing for translation function in TrendTooltip. - Adjusted import statements for better clarity and consistency. - Cleaned up code to enhance readability and maintainability. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> * Remove duplication of CrossoverData type (#6928) * Remove duplication of CrossoverData type Move the CrossoverData type definition to crossover-spreadsheet.tsx and import it from the Crossover and CrossoverCard files instead of having duplicate definitions in each file. Signed-off-by: Jonathon Jongsma <jonathon@quotidian.org> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Signed-off-by: Jonathon Jongsma <jonathon@quotidian.org> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Add Tag API (#6746) * Add Tag API * Add Tag API tests * Add Release Note for #6746 * Make release note more user-facing * Remove unnecessary type coercion in tagModel.fromExternal Since APITagEntity picks all properties from TagEntity, the types are structurally identical and TypeScript can verify compatibility without manual coercion. Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv> --------- Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv> * [FIX] Update DesktopLinkedNotes so links stay inline (#6858) * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes so links stay inline * Update TransactionsTable.tsx make sure flexDirection is row. * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx * Update TransactionsTable.tsx * Update DesktopLinkedNotes.tsx * Update NotesTagFormatter.tsx trial * Update DesktopLinkedNotes.tsx * Update NotesTagFormatter.tsx * Update NotesTagFormatter.tsx * Update DesktopLinkedNotes.tsx * [autofix.ci] apply automated fixes * Update TransactionsTable.tsx * Update DesktopLinkedNotes.tsx Add role for accessibility * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx Revert to original * Update DesktopLinkedNotes.tsx Try to style the bare button to make it work. * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx Reverting to current master * Update DesktopLinkedNotes.tsx Add nowrap styling. * Update DesktopLinkedNotes.tsx * Update TransactionsTable.tsx * Update TransactionsTable.tsx * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx * Update TransactionsTable.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * revert TransactionsTable.tsx * Update TransactionsTable.tsx * Update TransactionsTable.tsx * Update TransactionsTable.tsx * Update DesktopLinkedNotes.tsx * Update TransactionsTable.tsx * Update TransactionsTable.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Revert DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx * Update DesktopLinkedNotes.tsx * [autofix.ci] apply automated fixes * Update DesktopLinkedNotes.tsx * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: youngcw <calebyoung94@gmail.com> * Add butterfly custom theme (#6900) * Added butterfly custom theme * Added release notes * Fix/6885 crash when rule has empty date field (#6905) * Fix crash when rule date field loses focus while empty Fixes #6885 * Remove ts-strict-ignore and fix types in DateSelect * Generate release note 6905 * fix(schedules): prevent past missed schedule dates from being marked as upcoming (#6925) Fixes #6872 * [Goals] fix tracking budget balance carryover for templates (#6922) * fix tracking budget balance carryover for templates * Add release notes for PR #6922 * fix note * fix tests --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * :art: Reorganising Storybook and more component stories (#6924) * reorg of storybook docs and add some new components * releaes notes * Update meta tags for Actual Budget Design System * Increase sidebar item font size from 14px to 16px * Move redux state to react-query - category states [Part 2 - expose react-query states e.g. isPending, isSuccess, etc] (#6882) * Move redux state to react-query - category states [Part 2 - expose react-query states] * Add release notes for PR #6882 * Add default values to useCategories destructuring to prevent undefined crashes (#6884) * Initial plan * Add missing defaults to all useCategories usages Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Fix lint errors * Fix rebase mistake * Change category from Enhancements to Maintenance Migrate state management for category from Redux to React Query and update related hooks and components. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Retrofit useTransactions to use react-query under the hood (#6757) * Retrofit useTransactions to use react-query under the hood * Add release notes for PR #6757 * Update packages/desktop-client/src/transactions/queries.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Disable when there is no query parameter * Fix typecheck errors * Remove space * Update tests * Coderabbit: Add pageSize to query key * Use isPending instead of isFetching * Unexport mockStore * Revert variables * Change category from Enhancements to Maintenance Refactor the useTransactions hook to improve data fetching with react-query. * Fix lint errors * Fix lint errors * Migrate setupTests.js to TypeScript with proper types (#6871) * Initial plan * Rename setupTests.js to setupTests.ts and add proper types Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Extract Size type to avoid duplication Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Add release note for setupTests TypeScript migration Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Rename release note file to match PR number 6871 Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * [autofix.ci] apply automated fixes * Update transactionQueries * Delete setupTests PR release note --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * feat(currency): Add South Korean Won (#6846) * Add South Korean Won * Update currencies.ts * Add release notes * feat(currency): Add Vietnamese Dong (VND) currency (#6902) * feat(currency): add support for vietnamese dong currency * release: add upcoming release note * fix(currency): change the number format for vietnamese currency * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Add refetchOnSync option to useTransactions to refetch when a server sync event is emitted (#6936) * Migrate setupTests.js to TypeScript with proper types (#6871) * Initial plan * Rename setupTests.js to setupTests.ts and add proper types Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Extract Size type to avoid duplication Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Add release note for setupTests TypeScript migration Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Rename release note file to match PR number 6871 Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Delete setupTests PR release note * Add refetchOnSync to useTransactions to refetch when a server sync event is emitted * Add release note for useTransactions refetchOnSync feature (#6937) * Initial plan * Add release note for PR 6936 Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Coderabbit feedback --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * :art: Add remaining component stories to storybook (#6940) * final storybook stories * release notes * spelling mistake * Fix react query cache not being cleared when switching budgets (#6953) * Fix react query cache not being cleared when switching budgets * React does not want to export function from src/index * Release note * Fix mobile budget amount inputs when hide decimal places is enabled (#6945) * Upgrade oxfmt and oxlint, update .oxfmtrc.json import patterns (#6955) Co-authored-by: Cursor <cursoragent@cursor.com> * Retrofit useReports to use react-query under the hood (#6951) * Retrofit useReports to use react-query under the hood * Add release notes for PR #6951 * Update 6951.md * Report mutations --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Update `send` function to propagate any errors and fix `catchErrors` to return the error in result when an unknown command/method is sent to the browser server (#6942) * Fix send not returning error when catchErrors option is enabled and an unknown method error is encountered * Add release notes for PR #6942 * Fix send to properly propagate errors from the server * Update release note --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * API Account Object (#6915) * api change * docs * lint * release notes * spelling * [autofix.ci] apply automated fixes * spelling * whoopsie, thanks rabbit --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * feat: add back button to reports pages (#6702) * feat: add back button to reports pages * Update VRT screenshots Auto-generated by VRT workflow PR: #6702 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Rename loot-core/platform/client/fetch to connection to match server-side package (#6943) * Rename loot-core/platform/client/fetch package to connection to match the server side package name. Also to avoid confusion with the native fetch package. * Update connection/init method to not receive any parameter to so browser and default implementation have the same signature * Add release notes for PR #6943 * Fix names * Fix imports --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat: show/hide reconciled transactions on mobile (#6896) * feat: show/hide reconciled transactions on mobile Resolves #2969 * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Move redux state to react-query - tags states (#6941) * Move redux state to react-query - tags states * Add release notes for PR #6941 * Cleanup sendThrow * Cleanup * Update import * Fix import --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * docs: add Architecture Decision Records page with bank sync credential ADR (#6965) * docs: add Architecture Decision Records page for controversial decisions Co-authored-by: Cursor <cursoragent@cursor.com> * Add release notes for PR #6965 --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Docs: add Claude Code Pro subscription benefit for core contributors (#6963) * Add Claude Code Pro subscription benefit for core contributors Co-authored-by: Cursor <cursoragent@cursor.com> * Add release notes for PR #6963 --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Agent instructions for commit messages and PR titles (#6964) * [AI] Add mandatory [AI] prefix requirement for commit messages and PR titles Co-authored-by: matiss <matiss@mja.lv> * [autofix.ci] apply automated fixes * Add release notes for PR #6964 --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> 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> * Move redux state to react-query - account states (#6140) * Fix typecheck errors * Move redux state to react-query - account states * TestProviders * Add release notes for PR #6140 * Fix lint error * Fix TestProviders * Coderabbit feedback * Cleanup * [autofix.ci] apply automated fixes * Fix TestProviders * Fix onbudget and offbudget displaying closed accounts * [skip ci] Change category to Maintenance and update migration text * Replace logger calls in desktop-client to console * Fix lint errors * Clear react query on closing of budget file similar to redux resetApp action * [autofix.ci] apply automated fixes * Remove sendThrow * Code review feedback * [autofix.ci] apply automated fixes * Fix import * Fix import * Coderabbit feedback --------- 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> * [AI] lint: convert oxlint warnings to errors (#6970) Co-authored-by: Cursor <cursoragent@cursor.com> * Add filter option for category groups (#6834) * Add filter by category groups * Add tests * Add release notes * [autofix.ci] apply automated fixes * Fix typecheck findings * Fix modal * Address nitpick comment (filterBy) * Fix e2e tests * Make group a subfield of category * Fix test by typing in autocomplete * Replace testId with a11y lookups * Apply new type import style rules * Apply feedback * Improve typing on array reduce, remove manual type coercion --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Fix some low-hanging-fruit `@ts-strict-ignore` (#6969) * Fix low-hanging-fruit `@ts-strict-ignore` * Add release notes * A few more * Include category group in transaction export (#6960) * include category group in transaction export * Apply suggestion from @yzAlvin Co-authored-by: Alvin Zhao <yzalvin@duck.com> --------- Co-authored-by: youngcw <calebyoung94@gmail.com> * Implement missing logic for limit template type (#6690) * core: support limit refill templates * notes: refill templates * core: apply refill limits during runs * core: prioritize refill limits * Patch * Update release note * Fix typecheck * rework. Tests and template notes still need reworked * fix parser syntax * Fix type issue * Fix after rebase, support merging limit+refill * PR feedback --------- Co-authored-by: youngcw <calebyoung94@gmail.com> * :book: Move pluggy.ai doc out of experimental (#6975) * move pluggy out of experimental * remove note * Add release notes for PR #6975 * fixes --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * [AI] Update CodeRabbit config for suspect AI generated labels (#6985) Co-authored-by: Cursor <cursoragent@cursor.com> * [AI] Introduce type-aware oxlint and disable no-duplicate-type-constituents rule (#6984) Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ios): restore status bar color on iOS 26.2 (Safari 26) (#6983) * fix(ios): restore status bar color on iOS 26.2 (Safari 26) Safari 26 no longer uses the theme-color meta tag for the status bar and instead derives the tint from the body background. Set body background-color in HTML and sync it with the app theme so the status bar shows purple (or the active theme) instead of white. Fixes #6946 Co-authored-by: Cursor <cursoragent@cursor.com> * [autofix.ci] apply automated fixes * refactor(theme): update useMetaThemeColor to accept theme values directly Modified the useMetaThemeColor hook to accept theme color values instead of predefined keys. Updated FinancesApp and ManagementApp components to utilize the new implementation, ensuring proper theme color handling based on screen width. * [autofix.ci] apply automated fixes * refactor(theme): remove unused body background color in index.html and add tests for useMetaThemeColor hook Deleted the commented-out body background color in index.html to clean up the code. Added comprehensive tests for the useMetaThemeColor hook to ensure proper handling of theme colors, including support for CSS variables and reactivity to theme changes. * refactor(theme): improve getPropertyValueFromVarString function in useMetaThemeColor hook * [autofix.ci] apply automated fixes * Add release notes for PR #6983 --------- Co-authored-by: Cursor <cursoragent@cursor.com> 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> * Address some more low-hanging fruit for ts-strict-ignore (#6992) * Address some more low-hanging fruit for ts-strict-ignore * Add release notes * Fix small issues * Rabbit * Retrofit dashboard hooks to use react-query (#6957) * Retrofit useReports to use react-query under the hood * Add release notes for PR #6951 * Update 6951.md * Report mutations * Fix react query cache not being cleared when switching budgets (#6953) * Fix react query cache not being cleared when switching budgets * React does not want to export function from src/index * Release note * Use react-query is dashboard queries and mutations * Add release notes for PR #6957 * [autofix.ci] apply automated fixes * Fix typecheck errors * Coderabbit feedback * Make error cause optional * Rename useDashboardWidgetCopyMenu and update useDashboardWidget to accept object to prevent need to default id to empty string --------- 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> * Fix operator precedence grouping for */ and +/- (#6993) * Fix operator precedence grouping for */ and +/- * Add release note for #6993 * Fix exponent associativity and add regression test --------- Co-authored-by: Hadi Ayache <hadiayache@Hadis-Mac-mini.local> * Add Tag API docs (#6979) * Add Tag object type definition for API docs * Add Tags nav entry to API reference sidebar * Add Tags methods and examples to API reference * Add theming to charts and hence allowing custom themes on charts (#6909) * Add theming to charts and hence allowing custom themes on charts * Removing additional color scales for charts. * Fixed return fail over value. * Add reports to command bar (#7002) * Add reports to command bar * Add release notes * Improve category server app and react query mutation error handling (#6958) * Improve category server app and react query mutation error handling * Add release notes for PR #6958 * Fix test * Fix throwing async test Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Do not swallow exceptions when batching messages - propagate instead * Update error type to make 'cause' optional Make 'cause' property optional in error type. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Fix redirect to accounts page when no accounts exists (#7007) * Fix redirect to accounts page when no accounts exists * Add release notes for PR #7007 * Use isFetching --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Update useAccounts to return react query states (#7009) * Fix redirect to accounts page when no accounts exists * Add release notes for PR #7007 * Use isFetching * Update useAccounts to return react query states (e.g. isPending, isFetching, etc.) * Add release notes for PR #7009 * Delete upcoming-release-notes/7007.md * Change category from Enhancements to Maintenance Refactor `useAccounts` to improve data handling. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Move redux state to react-query - payees states (#6880) * Move redux state to react-query - account states * Fix onbudget and offbudget displaying closed accounts * Move redux state to react-query - payees states * Add release notes for PR #6880 * Replace usage of logger in desktop-client with console * Address feedback on adding default data to usePayees (#6931) * Initial plan * Add default data to usePayees usages using inline destructuring Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Fix imports * Update empty payees list test * Cleanup and simplify AccountEntity definition to fix `satisfies` syntax --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: joel-jeremy <20313680+joel-jeremy@users.noreply.github.com> * Document graph color variables for custom themes (#7011) * Document graph color variables for custom themes Added documentation for graph color variables in custom themes. * [autofix.ci] apply automated fixes * Update custom themes documentation for clarity Clarify the impact of color palettes on custom report widget graphs and format the list of color variables. * Update packages/docs/docs/experimental/custom-themes.md Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> * Fix color variable syntax in custom themes documentation Updated color variable syntax for chart colors in documentation. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> * :book: start of reports dashboard updates (#6976) * start of reports dashboard updates * spelling * Add release notes for PR #6976 * don't need one of these * consistent naming * bunny fixes * images * image again * extenion * fix * consistent naming * naming * fix * last one * Ill be done with this someday --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * ⬆️ mid month dependency bump (#7013) * baseline-browser-mapping (^2.9.14 → ^2.9.19) * minimatch (^10.1.1 → ^10.1.2) * lage (^2.14.15 → ^2.14.17) * react-aria-components (^1.14.0 → ^1.15.1) * @storybook/addon-a11y (^10.2.0 → ^10.2.7) * p-limit (^7.2.0 → ^7.3.0) * better-sqlite3 (^12.5.0 → ^12.6.2) * vitest (^4.0.16 → ^4.0.18) * @storybook/addon-docs (^10.2.0 → ^10.2.7) * @storybook/react-vite (^10.2.0 → ^10.2.7) * eslint-plugin-storybook (^10.2.0 → ^10.2.7) * storybook (^10.2.0 → ^10.2.7) * @codemirror/state (^6.5.3 → ^6.5.4) * @swc/core (^1.15.8 → ^1.15.11) * @tanstack/react-query (^5.90.19 → ^5.90.20) * @vitejs/plugin-basic-ssl (^2.1.3 → ^2.1.4) * @vitejs/plugin-react (^5.1.2 → ^5.1.3) * i18next (^25.7.4 → ^25.8.4) * react-aria (^3.45.0 → ^3.46.0) * react-hotkeys-hook (^5.2.1 → ^5.2.4) * react-i18next (^16.5.1 → ^16.5.4) * sass (^1.97.2 → ^1.97.3) * @easyops-cn/docusaurus-search-local (^0.52.2 → ^0.52.3) * react (^19.2.3 → ^19.2.4) * react-dom (^19.2.3 → ^19.2.4) * component lib peer deps * eslint-vitest-rule-tester (^3.0.1 → ^3.1.0) * lru-cache (^11.2.4 → ^11.2.5) * ua-parser-js (^2.0.7 → ^2.0.9) * cors (^2.8.5 → ^2.8.6) * @babel/core (^7.28.5 → ^7.29.0) * @types/node (^22.19.3 → ^22.19.10) * react (mixed → 19.2.4) * @testing-library/react (16.3.0 → 16.3.2) * react-router (7.12.0 → 7.13.0) * vite-plugin-node-polyfills (^0.24.0 → ^0.25.0) * pluggy-sdk (^0.79.0 → ^0.83.0) * note * [AI] Allow var(--name) in custom theme CSS (no fallbacks) (#7018) Co-authored-by: Cursor <cursoragent@cursor.com> * ⬆️ @playwright/test (1.57.0 → 1.58.2) (#7021) * @playwright/test (1.57.0 → 1.58.2) * note * disable moving nav bar animations * vrt * [AI] lint: await-thenable, no-floating-promises (#6987) * [AI] Desktop client, E2E, loot-core, sync-server and tooling updates Co-authored-by: Cursor <cursoragent@cursor.com> * Refactor database handling in various modules to use async/await for improved readability and error handling. This includes updates to database opening and closing methods across multiple files, ensuring consistent asynchronous behavior. Additionally, minor adjustments were made to encryption functions to support async operations. * Refactor sync migration tests to utilize async/await for improved readability. Updated transaction handling to streamline event expectations and cleanup process. * Refactor various functions to utilize async/await for improved readability and error handling. Updated service stopping, encryption, and file upload/download methods to ensure consistent asynchronous behavior across the application. * Refactor BudgetFileSelection component to use async/await for onSelect method, enhancing error handling and readability. Update merge tests to utilize async/await for improved clarity in transaction merging expectations. * Refactor filesystem module to use async/await for init function and related database operations, enhancing error handling and consistency across file interactions. Updated tests to reflect asynchronous behavior in database operations and file writing. * Fix typo in init function declaration to ensure it returns a Promise<void> instead of Proise<void>. * Update VRT screenshots Auto-generated by VRT workflow PR: #6987 * Update tests to use async/await for init function in web filesystem, ensuring consistent asynchronous behavior in database operations. * Update VRT screenshot for payees filter test to reflect recent changes * [AI] Fix no-floating-promises lint error in desktop-electron Wrapped queuedClientWinLogs.map() with Promise.all and void operator to properly handle the array of promises for executing queued logs. Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> * Refactor promise handling in global and sync event handlers * Update VRT screenshots Auto-generated by VRT workflow PR: #6987 --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> * Bump @isaacs/brace-expansion from 5.0.0 to 5.0.1 (#7020) * Bump @isaacs/brace-expansion from 5.0.0 to 5.0.1 Bumps @isaacs/brace-expansion from 5.0.0 to 5.0.1. --- updated-dependencies: - dependency-name: "@isaacs/brace-expansion" dependency-version: 5.0.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> * note --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> * feat(currency): Add Dominican Peso (DOP) currency (#7028) * feat(currency): Add Dominican Peso (DOP) currency * Add release notes * ⬆️ recharts (3.4.0 → 3.7.1) (#7022) * recharts (3.4.1 -> 3.7.0) * Cell & activeShape deprecation * note * fix textAnchor * remove Cell in BarGraph * Fix Net Worth Calculations (#6968) * fix: computed priorPeriodNetWorth and use it as a baseline for net worth calculations * add release notes * correct spelling * Update VRT screenshots Auto-generated by VRT workflow PR: #6968 * Update VRT screenshots Auto-generated by VRT workflow PR: #6968 * Update VRT screenshots Auto-generated by VRT workflow PR: #6968 * Update VRT screenshots Auto-generated by VRT workflow PR: #6968 * Update VRT screenshots Auto-generated by VRT workflow PR: #6968 * note --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: youngcw <calebyoung94@gmail.com> * Set inital focus on category when covering overspending (#7012) * Set inital focus on category when covering overspending * Fixup: Make sure that the amount is set * Unused import * Fix bug where typing an amount and pressing enter uses previous value --------- Co-authored-by: Dagur Ammendrup <dagurp@vivaldi.com> * 🎨 High Contrast Light theme for Actual (#7032) * Update customThemeCatalog.json * [autofix.ci] apply automated fixes * Create 7032.md 🎨 High contrast light theme. * Update customThemeCatalog.json * Update 7032.md --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Require authentication for SimpleFIN and Pluggy.ai endpoints (#7034) * Add authentication middleware to SimpleFIN and Pluggy.ai endpoints Protect /simplefin/* and /pluggyai/* routes with validateSessionMiddleware so only authenticated users can access bank account and transaction data. Co-authored-by: Cursor <cursoragent@cursor.com> * Release notes --------- Co-authored-by: Cursor <cursoragent@cursor.com> * Enhance PR template with structured sections (#6989) * Enhance PR template with description, type of change, and checklist sections Co-authored-by: Cursor <cursoragent@cursor.com> * Update PR template to streamline instructions for writing release notes * Remove unnecessary lines from the PR template to streamline instructions for writing release notes * Add release notes for PR #6989 * Update category in release notes Changed category from Enhancements to Maintenance. * Update PULL_REQUEST_TEMPLATE.md * Update AGENTS.md and PULL_REQUEST_TEMPLATE.md to clarify PR submission guidelines * Update 6989.md --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Add ACTUAL_USER_CREATION_MODE documentation to oauth-auth.md (#6935) * Add ACTUAL_USER_CREATION_MODE documentation to oauth-auth.md * [autofix.ci] apply automated fixes * add note that first external auth user is admin and owner Added details about admin permissions and server ownership for users authenticating with OpenID/OAuth2. * improve ACTUAL_USER_CREATION_MODE environment documentation clarify warning about server owner * [autofix.ci] apply automated fixes * move first user admin warning to "after setup" section of OIDC documentation --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Add tooltip to imported payee in rule result window (#7031) * Add tooltip to imported payee column in rule result window The imported payee column in SimpleTransactionsTable was missing a title attribute, so truncated text had no tooltip on hover. Other columns (category, account, notes) already pass title for this purpose. Fixes #7003 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add release notes for #7031 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Your Name <your-email@example.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * Hide selected accounts in the mobile filter (#7030) When filtering for accounts in the mobile view of reports, hide the already selected accounts. * Prevent single-slash paths from being parsed as filepaths (#6966) * fix: prevent single-slash paths from being parsed as filepaths * add release notes * [autofix.ci] apply automated fixes * test: add tests related to filepath * additonal test from coderabbit --------- Co-authored-by: Pratik Silwal <pratiksilwal@Pratiks-MacBook-Air.local> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [AI] Remove usage of 'web' file types (#7033) * [AI] Desktop client, E2E, loot-core, sync-server and tooling updates Co-authored-by: Cursor <cursoragent@cursor.com> * Refactor database handling in various modules to use async/await for improved readability and error handling. This includes updates to database opening and closing methods across multiple files, ensuring consistent asynchronous behavior. Additionally, minor adjustments were made to encryption functions to support async operations. * Refactor sync migration tests to utilize async/await for improved readability. Updated transaction handling to streamline event expectations and cleanup process. * Refactor various functions to utilize async/await for improved readability and error handling. Updated service stopping, encryption, and file upload/download methods to ensure consistent asynchronous behavior across the application. * Refactor BudgetFileSelection component to use async/await for onSelect method, enhancing error handling and readability. Update merge tests to utilize async/await for improved clarity in transaction merging expectations. * Refactor filesystem module to use async/await for init function and related database operations, enhancing error handling and consistency across file interactions. Updated tests to reflect asynchronous behavior in database operations and file writing. * Fix typo in init function declaration to ensure it returns a Promise<void> instead of Proise<void>. * Update VRT screenshots Auto-generated by VRT workflow PR: #6987 * Update tests to use async/await for init function in web filesystem, ensuring consistent asynchronous behavior in database operations. * Update VRT screenshot for payees filter test to reflect recent changes * Update filesystem module to remove web-specific implementations and streamline path handling. Refactor file operations to enhance type safety and consistency across different environments. Add tests for SQLite interactions and ensure proper handling of database transactions. * Add release notes for maintenance: Remove usage of 'web' file types * Refactor filesystem module to use type annotations for exports and improve consistency across methods. Remove deprecated web file handling and enhance encryption functions for better browser compatibility. * Trigger CI * Add asyncStorage API file to export Electron index module * Trigger CI * Feedback: typo --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * [AI] Enforce file access authorization on sync API endpoints (#7040) * [AI] Enforce file access authorization on sync API endpoints Co-authored-by: Cursor <cursoragent@cursor.com> * Refactor file deletion authorization to return error message as text * Refactor file upload validation to improve error handling * Add tests to allow admin users to retrieve encryption keys and sync files for other users - Implemented a test for admin access to retrieve encryption keys for another user's file in the /user-get-key endpoint. - Added a test for admin users to sync another user's file in the /sync endpoint, ensuring proper response and headers. These changes enhance the authorization checks for admin actions on user files. * Refactor file cleanup in tests to use onTestFinished for better error handling * Enhance admin capabilities in file management tests * Add migration to backfill file owners with admin ID * Enhance file access authorization in sync API * Update migration to backfill file owners with admin ID to ensure consistent ordering in the query * Refactor access control tests for file downloads in sync API * Add test for non-owner file download access via user_access in sync API This test verifies that users with appropriate access can download files owned by others, utilizing the requireFileAccess logic and UserService.countUserAccess. It ensures correct response headers and content delivery for shared files. * Refactor file cleanup in upload and download tests to utilize onTestFinished for improved error handling This update consolidates file cleanup logic in the test suite, ensuring that temporary files are removed after each test execution. The changes enhance the reliability of tests by consistently managing file state across various scenarios. --------- Co-authored-by: Cursor <cursoragent@cursor.com> * Add limit/refill automation types (#6692) * Add limit/refill automation components * Add release note * Fix typecheck * Rabbit PR feedback * Review * [AI] Add per-package tsconfigs and typescript-strict-plugin for typecheck (#7019) * [AI] Add per-package tsconfigs and typescript-strict-plugin for typecheck Co-authored-by: Cursor <cursoragent@cursor.com> * Update TypeScript configuration across multiple packages to correct plugin path key from "path" to "paths" and add reference to process-worker typings in index.electron.ts. * Remove reference to process-worker typings in index.electron.ts and add new process-worker typings file for global Process augmentation. * Refactor TypeScript build configurations across multiple packages by removing tsconfig.dist.json files and updating build scripts to use default TypeScript compilation. Adjusted compiler options to target ES2021 and enable declaration generation. * Update TypeScript configuration in api package to refine include and exclude patterns for better file management. * Update build script in api package to ensure migration SQL files are copied to the correct directory by creating the destination folder if it doesn't exist. * Update TypeScript configurations in crdt and desktop-electron packages to refine include and exclude patterns for improved file management. * Update TypeScript dependencies across multiple packages to include typescript-strict-plugin for enhanced type checking and maintain consistency in package.json files. --------- Co-authored-by: Cursor <cursoragent@cursor.com> * v26.2.1: critical security fix for simplefin, pluggy and multi-user (#7043) * Add release notes for version 26.2.1, including critical security fixes for SimpleFin, Pluggy, and multi-user setups. Remove outdated upcoming release notes for related bugfixes. * Add release notes for PR #7043 * Delete upcoming-release-notes/7043.md --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * [AI] Bump version to 26.2.1 (#7052) Co-authored-by: Cursor <cursoragent@cursor.com> * Rename theme 'Okabe Ito' to 'Color-blind (dark)' (#7058) * Rename theme 'Okabe Ito' to 'Color-blind (dark)' * Rename 'Okabe Ito' theme to 'Color-blind (dark)' * Fix capitalization in theme name for consistency * Validate file IDs for correctness (#7067) * Validate file IDs for correctness * Add release notes * 🐞 Midnight theme: Change menuAutoCompleteTextHover color - Fixes #7029 (#7048) * Change menuAutoCompleteTextHover color to green400 * Change menuAutoCompleteTextHover color to green400 in Midnight theme. Change menuAutoCompleteTextHover color to green400 in Midnight theme. * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * :bug: Fix file path on windows (#7076) * fix file path on windows * file path in migrations * release notes * [AI] Fix API build output path (dist/index.js instead of dist/api/index.js) (#7084) * [AI] Fix API build output path (dist/index.js instead of dist/api/index.js) - Set rootDir in packages/api/tsconfig.json so output is under dist/ not dist/api/ - Remove loot-core pegjs.ts from include; add local typings/pegjs.d.ts - Use mkdir -p in build:migrations for idempotent build - Exclude **/@types/** so declaration output does not conflict with input Made-with: Cursor * Update TypeScript configuration in api package to refine exclude patterns * Mobile rules item alignment (#7081) * [AI] Fix mobile rules list items to be full width and left-aligned - Override Button's default justifyContent/alignItems centering in ActionableGridListItem to use flex-start alignment - Add width: 100% to RulesListItem's SpaceBetween to fill the item width Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> * Add release notes for PR #7081 * Change category from Enhancements to Bugfix --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * [AI] Remove 'suspect ai generated' label and associated workflow (#7087) * Initial plan * [AI] Remove 'suspect ai generated' label and associated workflow Co-authored-by: MatissJanis <886567+MatissJanis@users.noreply.github.com> * [AI] Remove 'suspect ai generated' label from coderabbit config Co-authored-by: MatissJanis <886567+MatissJanis@users.noreply.github.com> * Add release notes for PR #7087 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MatissJanis <886567+MatissJanis@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * [Cursor] Development environment setup (#7088) * [AI] Add Cursor Cloud specific instructions to AGENTS.md Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> * [autofix.ci] apply automated fixes * Add release notes for PR #7088 * [AI] Fix Node.js minimum version requirement in AGENTS.md (#7089) * [AI] Fix outdated Node.js version requirement in Build Failures section Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> * [AI] Add test budget tip to Cursor Cloud instructions Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> 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: Copilot <198982749+Copilot@users.noreply.github.com> * [AI] Github action for unfreezing PRs (#7094) * [AI] Add GitHub Action to add PR to Merge Freeze unblocked list when unfreeze label is added Made-with: Cursor * Rename 7093.md to 7094.md * Add concurrency control to unfreeze job in merge-freeze-unfreeze workflow - Introduced concurrency settings to prevent overlapping executions of the unfreeze job based on labels. - Updated error handling to abort the process if fetching the current merge freeze status fails, ensuring unblocked PRs are not overwritten. * Refactor Merge Freeze workflow to simplify PR unblocking process - Updated the workflow to directly post the PR to the unblocked list without fetching the current freeze status. - Improved error handling by ensuring the access token is set before proceeding with the API call. * Revert "feat(currency): Add Vietnamese Dong (VND) currency" (#7100) * Revert "feat(currency): Add Vietnamese Dong (VND) currency (#6902)" This reverts commit 7fa9fa900b3b590078ba88ac70377c25769782a7. * Add release notes for PR #7100 * Delete 7100.md --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix bugfix categorisation in contributor points counting script (#7103) * s/bugfix/bugfixes * note * add alias functionality * note update * [AI] Make merge-freeze-unfreeze workflow work on fork PRs (#7104) * [AI] Make merge-freeze-unfreeze workflow work on fork PRs via pull_request_target Made-with: Cursor * Add release notes for the "unfreeze" workflow functionality in fork PRs * Add empty permissions block to unfreeze job in merge-freeze-unfreeze workflow * 🔖 (26.3.0) (#7097) * 🔖 (26.3.0) * Remove used release notes * Add release notes for PR #7097 * Remove used release notes * Remove used release notes * Add release notes for version 26.3.0 * Add new terms to spelling expectation list * Fix spelling and capitalization in release notes Corrected spelling of 'reorganisation' to 'reorganization' and updated 'coderabbit' to 'CodeRabbit' for consistency. * Update patterns.txt to allowlist 'CodeRabbit' Add 'CodeRabbit' to allowlist of proper nouns. * Clarify chart theming support in release notes Updated the release notes to specify bar/pie chart theming support and added details about theme variables for customization. * Remove 'CodeRabbit' from spelling expectations * Refactor release notes and improve formatting Reorganize release notes for clarity and update content. * Create 2026-03-02-release-26-3-0.md * Change release date to 2026-03-02 Updated the release date for version 26.3.0. * Update release notes for version 26.3.0 --------- Co-authored-by: jfdoming <9922514+jfdoming@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com> --------- Signed-off-by: Christian Speich <christian@spei.ch> Signed-off-by: Jonathon Jongsma <jonathon@quotidian.org> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Matiss Janis Aboltins <matiss@mja.lv> Co-authored-by: Michael Clark <5285928+MikesGlitch@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Nam <nam.tr.ha02@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com> Co-authored-by: Matthias Benaets <89214559+MatthiasBenaets@users.noreply.github.com> Co-authored-by: Joshua Granick <jgranick@users.noreply.github.com> Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk> Co-authored-by: Adam <github.jodes@aleeas.com> Co-authored-by: Joel Jeremy Marquez <joeljeremy.marquez@gm…
No description provided.