fix: checklist step 5, secondary-profile migrations and Linux database paths (#390) #394

Merged
maximus merged 5 commits from issue-390-manual-flag-profile-migrations into main 2026-10-07 02:00:03 +00:00

5 commits

Author SHA1 Message Date
le king fu
5910387eb7 test(profiles): pin the review's quick suggestions on the catch-up (#390)
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m49s
PR Check — Rust / rust (pull_request) Successful in 3m39s
From the /pr-review of PR #394:
- the profile database opens only once prepare_profile_db has resolved
  (deferred preparation; a load started early used to pass, RT1);
- a real VACUUM INTO failure, through a dangling symlink, names the full
  path and comes out scrubbed (RV6); the test first checks the raw message
  does name the folder;
- deleting a profile removes the -journal side file, the only one this
  app produces (RV5);
- test folders are removed when each test ends, a failing one included
  (TestDir guard), instead of 42 folders left in /tmp per run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:46:26 -04:00
le king fu
71147c5083 test(profiles): cover a v0.15-v0.17 secondary profile without history (#390)
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m54s
PR Check — Rust / rust (pull_request) Successful in 5m9s
The released-states loop stops at v0.10-v0.14 (state E). State F, the
consolidated schema of v0.15.0 to v0.17.0 without a history, only had
its floor checked; this test runs the whole preparation on it: history
recorded up to v17, nothing applied, no copy, flag repaired.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:54:38 -04:00
le king fu
02fca2ad3c docs: ADR 0021, guide and changelog for the profile catch-up (#390)
ADR 0021 records the catch-up rules and amends ADR 0003 and 0005, whose
claims about secondary profiles were false. architecture.md, CLAUDE.md
and the migration rule describe the two migration paths; the guide tells
where the pre-update copy lives and how to remove a database a deletion
on Linux left behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:35:00 -04:00
le king fu
b0206ae56b fix(profiles): catch secondary profiles up on missed migrations (#390)
tauri-plugin-sql migrates only the database registered with add_migrations,
the default profile's. A secondary profile kept the consolidated schema of
the version that created it and never received a migration afterwards.

prepare_profile_db runs before every Database.load:
- secondary profiles catch up with the same migrations() list (pinned
  SHA-384), history kept in _sqlx_migrations; a database without history
  gets a floor inferred from its schema (the seven released creation
  states are test fixtures), so nothing at or below it is ever replayed;
- a VACUUM INTO copy is taken before the first write, synced, then renamed;
- each version runs in its own transaction with foreign keys on; one that
  fails on a foreign key is retried once without them and its orphans are
  set to NULL where the key declares ON DELETE SET NULL;
- every profile gets its TEXT manual-categorization flags repaired;
- failures are logged with file names only and the profile still opens.

New profiles are born with their full history (get_new_profile_init_sql).

The plugin keeps databases under app_config_dir(), not app_data_dir():
the same folder on Windows and macOS, not on Linux. repair_migrations,
delete_profile_db and compute_account_return looked in the wrong folder
there. profile_db_path resolves the plugin's folder and validates the
file name; deleting a profile now also removes its SQLite side files and
catch-up copies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:35:00 -04:00
le king fu
f758282c2e fix(transactions): bind the manual-categorization flag as an integer (#390)
updateTransactionCategory bound the JS boolean `true`. tauri-plugin-sql
passes a bool to sqlx as a JSON value, so the column received the TEXT
'true', which the getting-started checklist's `is_manually_categorized = 1`
never matches: step 5 never ticked.

toSqlFlag turns a boolean, a number or a backup's string into 0/1. It is
used when a category is set by hand and when a JSON or CSV backup is
restored, since a backup exported while the bug stood carries "true"
(the CSV path read it as 0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:35:00 -04:00