Commit graph

19242 commits

Author SHA1 Message Date
Johannes Millan
34bf1d8277 fix(build): auto-generate env.generated.ts on checkout via husky hook 2026-03-06 16:39:21 +01:00
Johannes Millan
0631d3e868 Merge branch 'fix/carefully-review-all-the-changes-we'
* fix/carefully-review-all-the-changes-we:
  test(e2e): fix supersync E2E tests for mandatory encryption flow
  fix(sync): add defensive guards, improve error messages, and reset lastServerSeq after backup import
  fix(issue): show board title in Nextcloud Deck provider tooltip (#6751)
2026-03-06 16:38:51 +01:00
Johannes Millan
16ace15903 build: update package-lock.json 2026-03-06 16:38:44 +01:00
Johannes Millan
cce9576946 test(e2e): fix supersync E2E tests for mandatory encryption flow
- Extract shared encryption warning helper and fix race conditions
- Restructure concurrent-import tests to import before enabling sync
- Fix encryption password preservation and change tests
- Add "Change Password" button detection in supersync page object
- Mark backup-import ID mismatch test as fixme (known limitation)
2026-03-06 16:36:38 +01:00
Johannes Millan
f44e2d8183 fix(sync): add defensive guards, improve error messages, and reset lastServerSeq after backup import
- Add defensive undefined guard in sync hydration service
- Improve error messages for auth code exchange failures
- Reset lastServerSeq after backup import to ensure correct sync state
- Clarify revert comment in encryption toggle service
2026-03-06 16:36:03 +01:00
Johannes Millan
6d632c8c00 Merge branch 'fix/when-planner-is-scrolled-on-mobile'
* fix/when-planner-is-scrolled-on-mobile:
  fix(planner): show border at top of plan view when scrolled on mobile
2026-03-06 16:23:30 +01:00
Thorsten Klein
254a234c10
fix(issue): show board title in Nextcloud Deck provider tooltip (#6751)
Add missing NEXTCLOUD_DECK case to tooltip and initials helpers,
showing the selected board title prefixed with "Deck:" instead of
the raw provider key.
2026-03-06 16:22:18 +01:00
Johannes Millan
370348a877 fix(planner): show border at top of plan view when scrolled on mobile 2026-03-06 16:21:42 +01:00
Johannes Millan
93004d4859 feat(tasks): add dialog to view archived task details (#5425)
Add a read-only dialog to view archived task details including
subtasks, time spent/estimate, notes, attachments, issue links,
and repeat config. Accessible from:
- Search page (info icon for archived results)
- Worklog (clickable task titles)
- Quick history (clickable task titles)
- Daily summary worklog-week (clickable task titles)
- Daily summary task-summary-table (info button)
2026-03-06 16:13:25 +01:00
Johannes Millan
15ac7e853a fix(play-button): replace infinite CSS animation with periodic finite pulses 2026-03-06 16:13:04 +01:00
Johannes Millan
0a3444ad49 Merge branch 'fix/issue-6076'
* fix/issue-6076:
  fix(play-button): replace infinite CSS animation with periodic finite pulses
  fix(build): fix tag resolution and add error handling in bump-android-version
2026-03-06 15:44:49 +01:00
Johannes Millan
8adcbb2cc5 fix(play-button): replace infinite CSS animation with periodic finite pulses
The pulse circle behind the play button used `animation: pulse 2s infinite`,
which forces the browser compositor to run at 60fps continuously. This caused
~5-10% CPU and ~30% GPU usage while time tracking was active (#6076).

Replace with a finite CSS animation (`animation-iteration-count: 1`) triggered
every 5s via lazySetInterval. The compositor goes fully idle between pulses.
Combined with `will-change: transform` (own GPU layer), the animation does not
cause repaints of surrounding elements.

Closes #6076
2026-03-06 15:44:09 +01:00
Johannes Millan
a2d75478fb fix(tasks): preserve task order when carrying over to next day
Append new tasks after existing ones in TODAY_TAG.taskIds instead of
prepending, so manually sorted tasks retain their order across days.

Closes #6750
2026-03-06 13:43:16 +01:00
Johannes Millan
5b9f3f8278 Merge branch 'fix/issue-4933'
* fix/issue-4933:
  feat(work-view): show recurring tasks on tag views and show paused state
  feat(work-view): show recurring tasks in project view
2026-03-06 13:14:12 +01:00
Johannes Millan
6c9fae0b33 feat(work-view): show recurring tasks on tag views and show paused state
- Add selectTaskRepeatCfgsByTagId selector to filter repeat configs
  by tagIds
- Show recurring tasks section on both project and tag views
- Paused repeat configs are shown greyed out with a pause icon
- Alphabetical sorting maintained
2026-03-06 13:11:55 +01:00
Johannes Millan
6f7e204f3a Merge branch 'fix/test-gpt'
* fix/test-gpt:
  refactor(sync): use discriminated unions for sync orchestrator results
  docs(sync): replace completed simplification plan with new roadmap
2026-03-06 12:41:58 +01:00
Johannes Millan
564ca17254 feat(work-view): show recurring tasks in project view
Add a collapsible "Recurring Tasks" section at the bottom of the
project work-view showing repeatable task configs for the active
project. Clicking a row opens the edit dialog, hovering shows next
due date.

The section is hidden on tag views, when no repeat configs exist
for the project, and when task view filters/grouping are active.

Closes #4933
2026-03-06 12:41:25 +01:00
Johannes Millan
f35bd621ec Merge branch 'fix/issue-4931'
* fix/issue-4931:
  refactor(task-repeat-cfg): deprecate order field and remove from config UI
  feat(task-repeat-cfg): add skipOverdue option to recurring tasks
2026-03-06 12:40:12 +01:00
Johannes Millan
efaffe97a5 refactor(sync): use discriminated unions for sync orchestrator results
Replace flag-based result objects with DownloadOutcome and UploadOutcome
discriminated unions at the orchestrator level. This eliminates null
returns, optional boolean checks, and ambiguous flag combinations.

- Add DownloadOutcome (5 variants) and UploadOutcome (3 variants) types
- Update OperationLogSyncService to return discriminated unions
- Update SyncWrapperService and ImmediateUploadService consumers
- Use exhaustive switch in downloadCallback adapter
- Replace piggybackedOps array pass-through with piggybackedOpsCount
2026-03-06 12:38:09 +01:00
Johannes Millan
88d57e8e8b docs(sync): replace completed simplification plan with new roadmap
Remove supersync-client-simplification.md (all tasks implemented) and
add sync-core-simplification-roadmap.md for the next phase of work.
2026-03-06 12:37:52 +01:00
Johannes Millan
0a2e774c10 Merge branch 'fix/when-creating-worktrees-i-always-run'
* fix/when-creating-worktrees-i-always-run:
  fix(build): ensure env.generated.ts exists before ng serve
2026-03-06 12:37:05 +01:00
Johannes Millan
c698597af9 fix(build): ensure env.generated.ts exists before ng serve
Add --ensure flag to load-env.js that skips generation if
env.generated.ts already exists, allowing ng serve to work in
fresh worktrees without running npm run env first.

Also make load-env.js idempotent by comparing content before
writing and removing the timestamp from generated output.
2026-03-06 12:35:38 +01:00
Johannes Millan
eb2c414861 feat(task-repeat): show time spent summary for recurring task series (#4854)
Add total, this week, and this month time summaries above the heatmap
in the recurring task config dialog. Uses a pure utility function to
aggregate timeSpentOnDay across all current and archived task instances.
2026-03-06 12:24:09 +01:00
Johannes Millan
a2f34a0e9d refactor(task-repeat-cfg): deprecate order field and remove from config UI
The order field was confusing and not user-friendly. It is removed from
the repeat config dialog and translation keys. The field and its runtime
logic (isAddToBottom, sortRepeatableTaskCfgs) are kept intact for
backwards compatibility with existing configs that have a non-zero order.
order is also removed from SCHEDULE_AFFECTING_FIELDS since it is no
longer editable via the UI.
2026-03-06 12:22:09 +01:00
Johannes Millan
967b9e8c48 feat(task-repeat-cfg): add skipOverdue option to recurring tasks
When enabled on a repeat config, missed/overdue instances (scheduled
dates before today) are silently skipped instead of being created as
overdue tasks. The lastTaskCreationDay watermark is still advanced on
skip to prevent the same past date from being re-evaluated on every
subsequent app open.

Closes #4928, relates to #4931
2026-03-06 12:15:37 +01:00
Johannes Millan
9ef05b4fab Merge branch 'fix/issue-6746'
* fix/issue-6746:
  fix(sync): improve error messages for auth code exchange failures
2026-03-06 11:21:25 +01:00
Johannes Millan
ff05387628 fix(sync): improve error messages for auth code exchange failures
Differentiate between token exchange errors (HTTP 400 = invalid auth
code) and PKCE generation failures, showing appropriate messages for
each. Previously all auth errors showed a misleading "requires HTTPS"
message.

Also log Dropbox response body on token exchange errors for better
diagnostics.

Closes #6746
2026-03-06 11:16:14 +01:00
Johannes Millan
12d686d78c fix(sync): add defensive undefined guard and clarify revert comment
- Add undefined guard for newClock[clientId] in SyncHydrationService
  clock reset, matching the pattern in OperationLogStoreService
- Clarify enableEncryption revert comment explaining why explicit
  overrides exist despite existingCfg already having correct values
2026-03-06 10:30:08 +01:00
Johannes Millan
1f3c6cda9c test(e2e): extract shared encryption warning helper and fix race conditions
- Add handleEncryptionWarningDialog() to supersync-helpers.ts to
  eliminate duplicated dialog-handling blocks across import.page.ts
  and two supersync spec files
- Replace isVisible() point-in-time check with waitFor({ timeout: 1000 })
  in supersync.page.ts to avoid race when dialog is still animating in
- Replace silent .catch(() => {}) with a logged warning when the
  encryption dialog fails to close after confirmation
2026-03-05 21:18:39 +01:00
Johannes Millan
3dc86dd183
Fix/add rate limits (#6745)
* fix(build): fix tag resolution and add error handling in bump-android-version

The previous two-tag approach (`currentTag` → `prevTag`) would resolve the
wrong changelog range during `npm version` since the new tag doesn't exist
yet. Simplified to a single `lastTag...HEAD` range which correctly captures
all commits since the last release.

Added try-catch with fallback to last 20 commits when no tags exist, and
a fallback message for empty changelogs.

* fix(sync): differentiate auth error messages and clarify token revocation

- Rename server dashboard "Refresh Token" to "Revoke & Replace Token"
  with explicit warning that ALL devices will be disconnected
- Return rejection reason in 401 responses (revoked, expired, etc.)
  via discriminated union TokenVerificationResult type
- Show different client error messages for server-side token rejection
  vs missing local credentials to aid user diagnosis
- Extract server error reason from JSON response body in AuthFailSPError

Closes #6597

* refactor(sync): use generic auth reason and improve test readability

- Replace 'User not found' and 'Account not verified' with generic
  'Account unavailable' to avoid leaking account state in API responses
- Extract long reason strings to constants in middleware.spec.ts

* fix(sync-server): add per-route rate limits to silence CodeQL alert

Add explicit rate limits to routes that only had the global rate limit:
- GET /api/sync/status: 60/min
- DELETE /api/sync/data: 3/15min (destructive operation)
- GET /api/sync/restore-points: 30/min
- GET /api/sync/restore/:serverSeq: 10/5min (CPU-intensive)
- GET /reset-password: 20/15min
- GET /recover-passkey: 10/15min

These complement the global @fastify/rate-limit (100/15min) and silence
the CodeQL 'Missing rate limiting' alert on authenticated handlers.
2026-03-05 21:18:36 +01:00
Johannes Millan
7070fde51e
Pr 6741 (#6743)
* fix(build): fix tag resolution and add error handling in bump-android-version

The previous two-tag approach (`currentTag` → `prevTag`) would resolve the
wrong changelog range during `npm version` since the new tag doesn't exist
yet. Simplified to a single `lastTag...HEAD` range which correctly captures
all commits since the last release.

Added try-catch with fallback to last 20 commits when no tags exist, and
a fallback message for empty changelogs.

* fix(sync): differentiate auth error messages and clarify token revocation

- Rename server dashboard "Refresh Token" to "Revoke & Replace Token"
  with explicit warning that ALL devices will be disconnected
- Return rejection reason in 401 responses (revoked, expired, etc.)
  via discriminated union TokenVerificationResult type
- Show different client error messages for server-side token rejection
  vs missing local credentials to aid user diagnosis
- Extract server error reason from JSON response body in AuthFailSPError

Closes #6597

* refactor(sync): use generic auth reason and improve test readability

- Replace 'User not found' and 'Account not verified' with generic
  'Account unavailable' to avoid leaking account state in API responses
- Extract long reason strings to constants in middleware.spec.ts
2026-03-05 21:17:59 +01:00
Johannes Millan
bdef26c225 refactor(sync): use FULL_STATE_OP_TYPES constant and fix comment numbering 2026-03-05 21:02:26 +01:00
Johannes Millan
755cd705f5
Fix/run 22683814946 (#6740)
test(e2e): fix e2e tests
2026-03-05 19:37:48 +01:00
Johannes Millan
e92eb79db7
Reset vector clocks to minimal after SYNC_IMPORT to drop dead clients (#6738)
* fix(sync): reset vector clock to minimal after SYNC_IMPORT

After a SYNC_IMPORT, working clocks were carrying forward ALL accumulated
client IDs (including dead ones from reinstalls/old browsers), keeping the
clock permanently at MAX_VECTOR_CLOCK_SIZE. This caused unnecessary pruning
and comparison issues on every sync.

Three complementary changes:

1. Reset working clock to minimal after SYNC_IMPORT: When a client creates
   or receives a SYNC_IMPORT, its working clock is reset to only the import
   client's entry + own entry. Dead client IDs are dropped. The full clock
   is preserved in the stored SYNC_IMPORT operation for filtering.

2. Import-client-counter exception in SyncImportFilterService: Post-import
   ops with minimal clocks appear CONCURRENT with the import (missing old
   entries). A new exception recognizes them as post-import by checking if
   the op has the import client's counter >= the import's own counter value.

3. Updated SimulatedClient test helper to reset clocks on SYNC_IMPORT,
   matching the real behavior in OperationLogStoreService and
   SyncHydrationService.

https://claude.ai/code/session_01T5K1kq8m6LPDc6dEGyXnEW

* chore: update package-lock.json

https://claude.ai/code/session_01T5K1kq8m6LPDc6dEGyXnEW

* refactor(sync): use FULL_STATE_OP_TYPES constant and improve test assertions

- Replace magic string casts `(opType as string) === 'REPAIR'` with
  `FULL_STATE_OP_TYPES.has(opType)` in simulated-client helper
- Document transitive propagation assumption in import-client-counter
  exception comment
- Improve test assertion to use toContain for better failure messages

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-05 19:19:51 +01:00
Johannes Millan
0ea0ba143f fix(electron): improve protocol URL handling and register URL scheme on Linux
Suppress noisy "EXITING due to failed single instance lock" message when
a second instance is launched via xdg-open for protocol URL handling.
Register superproductivity:// as a MIME type handler in the .desktop file
so Linux users no longer need manual xdg-settings configuration.
Remove duplicate requestSingleInstanceLock() call in start-app.ts.

Closes #173
2026-03-05 16:45:05 +01:00
Johannes Millan
49d24bfec0 fix(sync): fix encryption key loss on revert and isSubTask detection in LWW update
- Pre-capture provider config before destructive deleteAndReuploadWithNewEncryption
  call so disableEncryption revert restores the original encryption key
- Merge guard check and config pre-capture in enableEncryption to eliminate
  redundant getActiveProvider()/privateCfg.load() calls
- Fix isSubTask detection in LWW meta-reducer to use new parentId when present,
  correctly handling subtask-to-main-task promotion
- Remove redundant unique() calls guarded by preceding includes() checks
2026-03-05 16:45:05 +01:00
Johannes Millan
8fe938a5f8 fix(build): fix tag resolution and add error handling in bump-android-version
The previous two-tag approach (`currentTag` → `prevTag`) would resolve the
wrong changelog range during `npm version` since the new tag doesn't exist
yet. Simplified to a single `lastTag...HEAD` range which correctly captures
all commits since the last release.

Added try-catch with fallback to last 20 commits when no tags exist, and
a fallback message for empty changelogs.
2026-03-05 16:45:05 +01:00
dependabot[bot]
d094881f73
chore(deps): bump the npm_and_yarn group across 1 directory with 4 updates (#6736)
Bumps the npm_and_yarn group with 4 updates in the / directory: [ajv](https://github.com/ajv-validator/ajv), [dompurify](https://github.com/cure53/DOMPurify), [immutable](https://github.com/immutable-js/immutable-js) and [tar](https://github.com/isaacs/node-tar).


Updates `ajv` from 8.17.1 to 8.18.0
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v8.17.1...v8.18.0)

Updates `dompurify` from 3.2.5 to 3.3.2
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.2.5...3.3.2)

Updates `immutable` from 5.1.4 to 5.1.5
- [Release notes](https://github.com/immutable-js/immutable-js/releases)
- [Changelog](https://github.com/immutable-js/immutable-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/immutable-js/immutable-js/compare/v5.1.4...v5.1.5)

Updates `tar` from 7.5.9 to 7.5.10
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.9...v7.5.10)

---
updated-dependencies:
- dependency-name: ajv
  dependency-version: 8.18.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: dompurify
  dependency-version: 3.3.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: immutable
  dependency-version: 5.1.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: tar
  dependency-version: 7.5.10
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 16:35:34 +01:00
overcuriousity
95883a68a7
fix #6684 (#6732) 2026-03-05 14:18:13 +01:00
dependabot[bot]
bb9c3bc614
chore(deps): bump the npm_and_yarn group across 1 directory with 4 updates (#6730)
Bumps the npm_and_yarn group with 4 updates in the / directory: [ajv](https://github.com/ajv-validator/ajv), [@hono/node-server](https://github.com/honojs/node-server), [hono](https://github.com/honojs/hono) and [rollup](https://github.com/rollup/rollup).


Updates `ajv` from 6.12.6 to 6.14.0
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.6...v6.14.0)

Updates `@hono/node-server` from 1.19.9 to 1.19.10
- [Release notes](https://github.com/honojs/node-server/releases)
- [Commits](https://github.com/honojs/node-server/compare/v1.19.9...v1.19.10)

Updates `hono` from 4.12.0 to 4.12.5
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.12.0...v4.12.5)

Updates `rollup` from 4.52.3 to 4.59.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.52.3...v4.59.0)

---
updated-dependencies:
- dependency-name: ajv
  dependency-version: 6.14.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: "@hono/node-server"
  dependency-version: 1.19.10
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: hono
  dependency-version: 4.12.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 13:44:57 +01:00
Johannes Millan
c640247d1d fix(build): fix tag resolution and add error handling in bump-android-version
The previous two-tag approach (`currentTag` → `prevTag`) would resolve the
wrong changelog range during `npm version` since the new tag doesn't exist
yet. Simplified to a single `lastTag...HEAD` range which correctly captures
all commits since the last release.

Added try-catch with fallback to last 20 commits when no tags exist, and
a fallback message for empty changelogs.
2026-03-04 19:56:40 +01:00
Johannes Millan
9f014dc3b8 chore: gitignore .claude/ directory and fix focus-mode test
Ignore entire .claude/ directory to keep local settings and commands
out of version control. Also fix test expectation to match Bug #6726
behavior where pausedTaskId is intentionally undefined on skipBreak.
2026-03-04 19:38:37 +01:00
Johannes Millan
46d9e27d66 fix(tasks): prevent right sidebar from opening after closing focus session
Remove unnecessary setSelectedId call from goToFocusMode() in the task
context menu. This aligns behavior with other focus mode entry points
(keyboard shortcut, header button) which only set currentTaskId.

Closes #6727
2026-03-04 19:38:37 +01:00
Johannes Millan
1388dfe1b5 fix(focus-mode): allow switching tasks during Pomodoro breaks (#6726)
Don't override user's task choice when a break ends or is skipped.
Guard setCurrentTask dispatch with currentTaskId check in skipBreak$
and resumeTrackingOnBreakComplete$ effects, and pass undefined
pausedTaskId when syncTrackingStartToSession$ auto-skips a break.
2026-03-04 19:38:37 +01:00
Johannes Millan
1272d6e7bf chore: replace CHANGELOG.md with git-based release notes
Remove the 15k-line auto-generated CHANGELOG.md and its conventional-changelog
tooling. The bump-android-version script now derives Play Store fastlane
changelogs from git log between tags instead of parsing CHANGELOG.md.

- Use execFileSync with argv to avoid shell injection
- Filter merge commits with --no-merges
- Handle breaking-change prefix (feat!:) in regex
- Truncate at line boundaries for 500-char Play Store limit
- Remove conventional-changelog-cli and @conventional-changelog/git-client deps
- Remove release.changelog script from package.json
2026-03-04 19:38:37 +01:00
Johannes Millan
7164a5e44b test(e2e): fix encryption button timing and drag-handle strict mode violation
Two root causes for failing E2E tests in CI:

1. Encryption button not visible after provider selection: The async
   provider change listener loads config from IndexedDB and updates the
   Formly model, but the 1000ms waitForTimeout was insufficient in CI.
   Replace with polling (200ms intervals, 10s timeout) that waits for
   either enable or disable encryption button to become visible.
   Also removes ~130 lines of leftover debug logging from disableEncryption().

2. Drag-handle strict mode violation on parent tasks with subtasks:
   task.locator('.drag-handle') matched both the parent's drag handle
   and nested subtask drag handles. Add .first() to all drag-handle
   locator usages to target only the parent task's own handle.
2026-03-04 19:38:37 +01:00
Johannes Millan
ef07ae8ff2 fix(android): make sidebar settings button visible above system nav bar
Use JS-computed var(--safe-area-bottom) instead of env(safe-area-inset-bottom)
which returns 0 on Android WebView. Also account for bottom nav height and
position sidebar below status bar on native mobile.

Closes #6561
2026-03-04 19:38:37 +01:00
Johannes Millan
1471b101fe docs: add SignPath code signing acknowledgment to README 2026-03-04 19:38:37 +01:00
Johannes Millan
49bf056ee0
refactor(sync): simplify SuperSync client code (#6728)
- Unify duplicated HTTP methods in SuperSyncProvider into shared helpers
- Remove 5 encryption DI injection tokens, use private properties for test spying
- Remove DerivedKeyCacheService wrapper, use direct imports
- Cache _getServerSeqKey() result in SuperSyncProvider
- Split SyncProviderServiceInterface into SyncProviderBase + FileSyncProvider
- Remove dead file-op stubs from SuperSync provider
- Extract shared delete-and-reupload pattern into SnapshotUploadService
- Extract helper methods from operation-log-sync.service.ts
- Auto-invalidate WrappedProviderService cache on config changes
- Fix: preserve auth credentials in encryption toggle revert paths
- Fix: add config revert on disableEncryption failure

~720 lines net reduction across 26 files.
2026-03-04 19:01:20 +01:00
Johannes Millan
7c30916d28 test: fix 4 failing unit tests after recent sync and dueDay changes
- Add TODAY_TAG to FAKE_ROOT_STATE in TaskArchiveService so
  handleUpdateTask can find it when marking tasks as done
- Update dueDay assertion to expect defined value (set to today
  by updateDoneOnForTask)
- Add mock tasks to LWW integration tests so orphan filter
  doesn't remove taskIds from PROJECT/TAG entities
2026-03-04 13:16:01 +01:00