Inline profile storage into settings.json (ticket 049)

Fold ProfileStore's separate profiles.json into Settings itself, so
settings.json is the single source of truth instead of two files kept
in sync by hand. Settings now carries `profiles: Vec<Profile>` and
`active_profile: Option<String>` directly; every former ProfileStore
mutation (create, delete, set_active, record_param_declaration,
record_metric_declaration, dashboard CRUD, ensure_default) is now a
method on Settings that persists via Settings::save.

A custom Deserialize (via SettingsOnDisk) keeps an old settings.json
(with the removed Profiles pointer struct) loading cleanly, and
Settings::load runs a one-time migration: if profiles is empty and a
legacy <settings_dir>/profiles/profiles.json exists, its contents are
merged in, settings.json is resaved, and the old file is renamed so it
isn't re-imported.

Updated all call sites in api.rs and main.rs to the single-path API,
and ported profile.rs's ProfileStore tests to exercise Settings
directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
Hugh Kaznowski
2026-09-06 01:54:04 +01:00
co-authored by Claude Sonnet 5
parent 85fb145be7
commit e8baf2b004
5 changed files with 421 additions and 399 deletions
+1 -1
View File
@@ -190,7 +190,7 @@ impl From<&Settings> for SettingsDto {
fn from(settings: &Settings) -> Self {
SettingsDto {
color_scheme: settings.color_scheme,
active_profile: settings.profiles.active_profile.clone(),
active_profile: settings.active_profile.clone(),
max_logs: settings.max_logs,
custom_theme_id: settings.custom_theme_id.clone(),
ntfy_topic: settings.ntfy_topic.clone(),