app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 5690d115fcd7062dbb2538f0bb9f2fadb97d49a4
parent 4a74758b7fcd3c6eda3aad55f4fc51fe837e8ab3
Author: triesap <triesap@radroots.dev>
Date:   Wed, 21 Jan 2026 16:27:05 +0000

app: remove cfg data bootstrap

- drop settings model and datastore helpers

- remove settings key map and validation rules

- remove bootstrap_settings health check and UI

- update tests for new bootstrap state

Diffstat:
Mapp/src/app.rs | 10----------
Mapp/src/bootstrap.rs | 60+-----------------------------------------------------------
Mapp/src/config.rs | 19-------------------
Mapp/src/data.rs | 33+--------------------------------
Mapp/src/health.rs | 29+----------------------------
Mapp/src/init.rs | 16----------------
Mapp/src/lib.rs | 7+------
7 files changed, 4 insertions(+), 170 deletions(-)

diff --git a/app/src/app.rs b/app/src/app.rs @@ -369,16 +369,6 @@ fn HomePage() -> impl IntoView { <span style=move || format!( "display:inline-block;width:10px;height:10px;border-radius:50%;background:{};", - health_status_color(health_report.get().bootstrap_settings.status) - ) - ></span> - <span>"bootstrap_settings"</span> - <span>{move || health_result_label(&health_report.get().bootstrap_settings)}</span> - </div> - <div style="display: flex; align-items: center; gap: 8px;"> - <span - style=move || format!( - "display:inline-block;width:10px;height:10px;border-radius:50%;background:{};", health_status_color(health_report.get().bootstrap_state.status) ) ></span> diff --git a/app/src/bootstrap.rs b/app/src/bootstrap.rs @@ -4,42 +4,14 @@ use radroots_app_core::datastore::{RadrootsClientDatastore, RadrootsClientDatast use radroots_app_core::notifications::RadrootsClientNotificationsPermission; use crate::{ - app_datastore_obj_key_settings, app_datastore_obj_key_state, app_log_debug_emit, RadrootsAppState, - RadrootsAppSettings, RadrootsAppInitError, RadrootsAppInitResult, RadrootsAppKeyMapConfig, }; -pub async fn app_datastore_write_settings<T: RadrootsClientDatastore>( - datastore: &T, - key_maps: &RadrootsAppKeyMapConfig, - data: &RadrootsAppSettings, -) -> RadrootsAppInitResult<RadrootsAppSettings> { - let key = app_datastore_obj_key_settings(key_maps).map_err(RadrootsAppInitError::Config)?; - let value = datastore - .set_obj(key, data) - .await - .map_err(RadrootsAppInitError::Datastore)?; - let _ = app_log_debug_emit("log.app.bootstrap.config", "write", Some(key.to_string())); - Ok(value) -} - -pub async fn app_datastore_has_settings<T: RadrootsClientDatastore>( - datastore: &T, - key_maps: &RadrootsAppKeyMapConfig, -) -> RadrootsAppInitResult<bool> { - let key = app_datastore_obj_key_settings(key_maps).map_err(RadrootsAppInitError::Config)?; - match datastore.get_obj::<RadrootsAppSettings>(key).await { - Ok(_) => Ok(true), - Err(RadrootsClientDatastoreError::NoResult) => Ok(false), - Err(err) => Err(RadrootsAppInitError::Datastore(err)), - } -} - pub async fn app_datastore_write_state<T: RadrootsClientDatastore>( datastore: &T, key_maps: &RadrootsAppKeyMapConfig, @@ -83,11 +55,6 @@ pub async fn app_datastore_clear_bootstrap<T: RadrootsClientDatastore>( datastore: &T, key_maps: &RadrootsAppKeyMapConfig, ) -> RadrootsAppInitResult<()> { - let cfg_key = app_datastore_obj_key_settings(key_maps).map_err(RadrootsAppInitError::Config)?; - datastore - .del_obj(cfg_key) - .await - .map_err(RadrootsAppInitError::Datastore)?; let app_key = app_datastore_obj_key_state(key_maps).map_err(RadrootsAppInitError::Config)?; datastore .del_obj(app_key) @@ -132,33 +99,17 @@ mod tests { use super::{ app_datastore_clear_bootstrap, app_datastore_has_state, - app_datastore_has_settings, app_datastore_read_state, app_state_set_notifications_permission, app_state_set_notifications_permission_value, app_state_notifications_permission_value, app_datastore_write_state, - app_datastore_write_settings, }; - use crate::{app_key_maps_default, RadrootsAppState, RadrootsAppSettings, RadrootsAppInitError}; + use crate::{app_key_maps_default, RadrootsAppState, RadrootsAppInitError}; use radroots_app_core::datastore::{RadrootsClientDatastoreError, RadrootsClientWebDatastore}; use radroots_app_core::notifications::RadrootsClientNotificationsPermission; #[test] - fn settings_write_maps_idb_errors() { - let datastore = RadrootsClientWebDatastore::new(None); - let key_maps = app_key_maps_default(); - let data = RadrootsAppSettings::default(); - let err = futures::executor::block_on(app_datastore_write_settings( - &datastore, - &key_maps, - &data, - )) - .expect_err("idb undefined"); - assert_eq!(err, RadrootsAppInitError::Datastore(RadrootsClientDatastoreError::IdbUndefined)); - } - - #[test] fn state_write_maps_idb_errors() { let datastore = RadrootsClientWebDatastore::new(None); let key_maps = app_key_maps_default(); @@ -197,15 +148,6 @@ mod tests { } #[test] - fn has_settings_maps_idb_errors() { - let datastore = RadrootsClientWebDatastore::new(None); - let key_maps = app_key_maps_default(); - let err = futures::executor::block_on(app_datastore_has_settings(&datastore, &key_maps)) - .expect_err("idb undefined"); - assert_eq!(err, RadrootsAppInitError::Datastore(RadrootsClientDatastoreError::IdbUndefined)); - } - - #[test] fn has_state_maps_idb_errors() { let datastore = RadrootsClientWebDatastore::new(None); let key_maps = app_key_maps_default(); diff --git a/app/src/config.rs b/app/src/config.rs @@ -16,7 +16,6 @@ pub type RadrootsAppKeystoreKeyMap = BTreeMap<&'static str, &'static str>; pub const APP_DATASTORE_KEY_NOSTR_KEY: &str = "nostr:key"; pub const APP_DATASTORE_KEY_EULA_DATE: &str = "app:eula:date"; -pub const APP_DATASTORE_KEY_OBJ_SETTINGS: &str = "cfg:data"; pub const APP_DATASTORE_KEY_OBJ_STATE: &str = "app:data"; pub const APP_DATASTORE_KEY_LOG_ENTRY: &str = "log:entry"; pub const APP_KEYSTORE_KEY_NOSTR_DEFAULT: &str = "nostr:default"; @@ -62,7 +61,6 @@ pub fn app_key_maps_default() -> RadrootsAppKeyMapConfig { ); param_map.insert("log_entry", app_datastore_param_log_entry as RadrootsAppDatastoreKeyParam); let mut obj_map = BTreeMap::new(); - obj_map.insert("settings", APP_DATASTORE_KEY_OBJ_SETTINGS); obj_map.insert("state", APP_DATASTORE_KEY_OBJ_STATE); RadrootsAppKeyMapConfig { key_map, @@ -116,9 +114,6 @@ pub fn app_key_maps_validate(config: &RadrootsAppKeyMapConfig) -> RadrootsAppCon if !config.param_map.contains_key("log_entry") { return Err(RadrootsAppConfigError::MissingParamMap("log_entry")); } - if !config.obj_map.contains_key("settings") { - return Err(RadrootsAppConfigError::MissingObjMap("settings")); - } if !config.obj_map.contains_key("state") { return Err(RadrootsAppConfigError::MissingObjMap("state")); } @@ -170,10 +165,6 @@ pub fn app_datastore_key_eula_date(config: &RadrootsAppKeyMapConfig) -> Radroots app_datastore_key(config, "eula_date") } -pub fn app_datastore_obj_key_settings(config: &RadrootsAppKeyMapConfig) -> RadrootsAppConfigResult<&'static str> { - app_datastore_obj_key(config, "settings") -} - pub fn app_datastore_obj_key_state(config: &RadrootsAppKeyMapConfig) -> RadrootsAppConfigResult<&'static str> { app_datastore_obj_key(config, "state") } @@ -292,7 +283,6 @@ mod tests { app_datastore_key_eula_date, app_datastore_key_nostr_key, app_datastore_obj_key_state, - app_datastore_obj_key_settings, app_key_maps_validate, app_keystore_key_maps_default, app_keystore_key_maps_validate, @@ -311,7 +301,6 @@ mod tests { APP_DATASTORE_KEY_EULA_DATE, APP_DATASTORE_KEY_NOSTR_KEY, APP_DATASTORE_KEY_OBJ_STATE, - APP_DATASTORE_KEY_OBJ_SETTINGS, APP_DATASTORE_KEY_LOG_ENTRY, APP_KEYSTORE_KEY_NOSTR_DEFAULT, }; @@ -393,10 +382,6 @@ mod tests { Some(&APP_DATASTORE_KEY_EULA_DATE) ); assert_eq!( - config.obj_map.get("settings"), - Some(&APP_DATASTORE_KEY_OBJ_SETTINGS) - ); - assert_eq!( config.obj_map.get("state"), Some(&APP_DATASTORE_KEY_OBJ_STATE) ); @@ -439,10 +424,6 @@ mod tests { APP_DATASTORE_KEY_EULA_DATE ); assert_eq!( - app_datastore_obj_key_settings(&config).expect("settings key"), - APP_DATASTORE_KEY_OBJ_SETTINGS - ); - assert_eq!( app_datastore_obj_key_state(&config).expect("state key"), APP_DATASTORE_KEY_OBJ_STATE ); diff --git a/app/src/data.rs b/app/src/data.rs @@ -14,27 +14,6 @@ impl Default for RadrootsAppRole { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct RadrootsAppSettings { - pub nostr_public_key: Option<String>, - pub nostr_profile: Option<String>, - pub role: Option<RadrootsAppRole>, - pub nip05_request: Option<bool>, - pub nip05_key: Option<String>, -} - -impl Default for RadrootsAppSettings { - fn default() -> Self { - Self { - nostr_public_key: None, - nostr_profile: None, - role: None, - nip05_request: None, - nip05_key: None, - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct RadrootsAppState { pub active_key: String, pub role: RadrootsAppRole, @@ -61,7 +40,7 @@ pub fn app_state_is_initialized(state: &RadrootsAppState) -> bool { #[cfg(test)] mod tests { - use super::{app_state_is_initialized, RadrootsAppRole, RadrootsAppSettings, RadrootsAppState}; + use super::{app_state_is_initialized, RadrootsAppRole, RadrootsAppState}; #[test] fn role_defaults_to_public() { @@ -69,16 +48,6 @@ mod tests { } #[test] - fn settings_defaults_empty() { - let data = RadrootsAppSettings::default(); - assert!(data.nostr_public_key.is_none()); - assert!(data.nostr_profile.is_none()); - assert!(data.role.is_none()); - assert!(data.nip05_request.is_none()); - assert!(data.nip05_key.is_none()); - } - - #[test] fn state_defaults_empty() { let data = RadrootsAppState::default(); assert_eq!(data.active_key, ""); diff --git a/app/src/health.rs b/app/src/health.rs @@ -49,7 +49,6 @@ impl RadrootsAppHealthCheckResult { #[derive(Debug, Clone, PartialEq, Eq)] pub struct RadrootsAppHealthReport { pub key_maps: RadrootsAppHealthCheckResult, - pub bootstrap_settings: RadrootsAppHealthCheckResult, pub bootstrap_state: RadrootsAppHealthCheckResult, pub state_active_key: RadrootsAppHealthCheckResult, pub notifications: RadrootsAppHealthCheckResult, @@ -62,7 +61,6 @@ impl Default for RadrootsAppHealthReport { fn default() -> Self { Self { key_maps: RadrootsAppHealthCheckResult::skipped(), - bootstrap_settings: RadrootsAppHealthCheckResult::skipped(), bootstrap_state: RadrootsAppHealthCheckResult::skipped(), state_active_key: RadrootsAppHealthCheckResult::skipped(), notifications: RadrootsAppHealthCheckResult::skipped(), @@ -81,7 +79,6 @@ impl RadrootsAppHealthReport { use crate::{ app_datastore_has_state, - app_datastore_has_settings, app_datastore_key_nostr_key, app_datastore_read_state, app_log_buffer_flush_critical, @@ -128,17 +125,6 @@ pub fn app_health_check_key_maps(key_maps: &RadrootsAppKeyMapConfig) -> Radroots } } -pub async fn app_health_check_bootstrap_settings<T: RadrootsClientDatastore>( - datastore: &T, - key_maps: &RadrootsAppKeyMapConfig, -) -> RadrootsAppHealthCheckResult { - match app_datastore_has_settings(datastore, key_maps).await { - Ok(true) => RadrootsAppHealthCheckResult::ok(), - Ok(false) => RadrootsAppHealthCheckResult::error("missing"), - Err(err) => RadrootsAppHealthCheckResult::error(err.to_string()), - } -} - pub async fn app_health_check_bootstrap_state<T: RadrootsClientDatastore>( datastore: &T, key_maps: &RadrootsAppKeyMapConfig, @@ -287,7 +273,6 @@ pub async fn app_health_check_all<T: RadrootsClientDatastore, K: RadrootsClientK log_health_start("key_maps"); let key_maps_result = app_health_check_key_maps(key_maps); log_health_end("key_maps", &key_maps_result); - log_health_start("bootstrap_settings"); log_health_start("bootstrap_state"); log_health_start("state_active_key"); log_health_start("notifications"); @@ -299,7 +284,6 @@ pub async fn app_health_check_all<T: RadrootsClientDatastore, K: RadrootsClientK .as_ref() .and_then(|data| data.notifications_permission.as_deref()); let ( - bootstrap_settings, bootstrap_state, state_active_key, notifications_result, @@ -307,7 +291,6 @@ pub async fn app_health_check_all<T: RadrootsClientDatastore, K: RadrootsClientK datastore_roundtrip, keystore_result, ) = join!( - app_health_check_bootstrap_settings(datastore, key_maps), app_health_check_bootstrap_state(datastore, key_maps), app_health_check_state_active_key_with_state(datastore, key_maps, stored_state.as_ref()), app_health_check_notifications_with_state(notifications, stored_permission), @@ -315,7 +298,6 @@ pub async fn app_health_check_all<T: RadrootsClientDatastore, K: RadrootsClientK app_health_check_datastore_roundtrip(datastore), app_health_check_keystore_access(datastore, keystore, key_maps), ); - log_health_end("bootstrap_settings", &bootstrap_settings); log_health_end("bootstrap_state", &bootstrap_state); log_health_end("state_active_key", &state_active_key); log_health_end("notifications", &notifications_result); @@ -324,7 +306,6 @@ pub async fn app_health_check_all<T: RadrootsClientDatastore, K: RadrootsClientK log_health_end("keystore", &keystore_result); RadrootsAppHealthReport { key_maps: key_maps_result, - bootstrap_settings, bootstrap_state, state_active_key, notifications: notifications_result, @@ -355,7 +336,6 @@ mod tests { app_health_check_all_logged, app_health_check_key_maps, app_health_check_bootstrap_state, - app_health_check_bootstrap_settings, app_health_check_datastore_roundtrip, app_health_check_keystore_access, app_health_check_notifications, @@ -419,7 +399,6 @@ mod tests { fn health_report_defaults_skipped() { let report = RadrootsAppHealthReport::default(); assert_eq!(report.key_maps.status, RadrootsAppHealthCheckStatus::Skipped); - assert_eq!(report.bootstrap_settings.status, RadrootsAppHealthCheckStatus::Skipped); assert_eq!(report.bootstrap_state.status, RadrootsAppHealthCheckStatus::Skipped); assert_eq!(report.state_active_key.status, RadrootsAppHealthCheckStatus::Skipped); assert_eq!(report.notifications.status, RadrootsAppHealthCheckStatus::Skipped); @@ -440,14 +419,9 @@ mod tests { } #[test] - fn health_check_bootstrap_reports_idb_errors() { + fn health_check_bootstrap_state_reports_idb_errors() { let datastore = RadrootsClientWebDatastore::new(None); let key_maps = crate::app_key_maps_default(); - let result = futures::executor::block_on(app_health_check_bootstrap_settings( - &datastore, - &key_maps, - )); - assert_eq!(result.status, RadrootsAppHealthCheckStatus::Error); let result = futures::executor::block_on(app_health_check_bootstrap_state( &datastore, &key_maps, @@ -763,7 +737,6 @@ mod tests { &key_maps, )); assert_eq!(report.key_maps.status, RadrootsAppHealthCheckStatus::Ok); - assert_eq!(report.bootstrap_settings.status, RadrootsAppHealthCheckStatus::Error); assert_eq!(report.bootstrap_state.status, RadrootsAppHealthCheckStatus::Error); assert_eq!(report.state_active_key.status, RadrootsAppHealthCheckStatus::Error); assert_eq!(report.notifications.status, RadrootsAppHealthCheckStatus::Error); diff --git a/app/src/init.rs b/app/src/init.rs @@ -22,11 +22,9 @@ use radroots_app_core::keystore::{ use crate::{ app_datastore_clear_bootstrap, app_datastore_has_state, - app_datastore_has_settings, app_datastore_key_nostr_key, app_datastore_read_state, app_datastore_write_state, - app_datastore_write_settings, app_assets_geocoder_db_url, app_assets_sql_wasm_url, app_keystore_nostr_ensure_key, @@ -34,7 +32,6 @@ use crate::{ app_state_is_initialized, RadrootsAppState, RadrootsAppConfig, - RadrootsAppSettings, RadrootsAppConfigError, RadrootsAppKeystoreError, RadrootsAppKeyMapConfig, @@ -414,19 +411,6 @@ pub async fn app_init_backends(config: RadrootsAppConfig) -> RadrootsAppInitResu .await .map_err(RadrootsAppInitError::Datastore)?; let _ = app_log_debug_emit("log.app.init.backends", "datastore_ready", None); - let has_config = - app_datastore_has_settings(datastore.as_ref(), &config.datastore.key_maps).await?; - if !has_config { - let config_data = RadrootsAppSettings::default(); - let _ = - app_datastore_write_settings( - datastore.as_ref(), - &config.datastore.key_maps, - &config_data, - ) - .await?; - } - let _ = app_log_debug_emit("log.app.init.backends", "config_ready", None); let nostr_keystore = RadrootsClientWebKeystoreNostr::new(Some(config.keystore.nostr_store)); let key_start = app_init_timer_start(); let nostr_public_key = app_keystore_nostr_ensure_key(&nostr_keystore) diff --git a/app/src/lib.rs b/app/src/lib.rs @@ -18,22 +18,19 @@ pub use app::RadrootsApp; pub use bootstrap::{ app_datastore_clear_bootstrap, app_datastore_has_state, - app_datastore_has_settings, app_datastore_read_state, app_state_set_notifications_permission, app_state_set_notifications_permission_value, app_state_notifications_permission_value, app_datastore_write_state, - app_datastore_write_settings, }; pub use context::{app_context, RadrootsAppContext}; -pub use data::{app_state_is_initialized, RadrootsAppRole, RadrootsAppSettings, RadrootsAppState}; +pub use data::{app_state_is_initialized, RadrootsAppRole, RadrootsAppState}; pub use health::{ app_health_check_all, app_health_check_all_logged, app_health_check_state_active_key, app_health_check_bootstrap_state, - app_health_check_bootstrap_settings, app_health_check_datastore_roundtrip, app_health_check_keystore_access, app_health_check_notifications, @@ -104,7 +101,6 @@ pub use config::{ app_datastore_param_key, app_datastore_obj_key, app_datastore_obj_key_state, - app_datastore_obj_key_settings, app_assets_geocoder_db_url, app_assets_sql_wasm_url, app_keystore_key_maps_default, @@ -129,7 +125,6 @@ pub use config::{ APP_DATASTORE_KEY_LOG_ENTRY, APP_DATASTORE_KEY_NOSTR_KEY, APP_DATASTORE_KEY_OBJ_STATE, - APP_DATASTORE_KEY_OBJ_SETTINGS, APP_KEYSTORE_KEY_NOSTR_DEFAULT, }; pub use init::{