cli

Command-line interface for Radroots
git clone https://radroots.dev/git/cli.git
Log | Files | Refs | README | LICENSE

commit 30d95fa82ca329c543d3f08b92d827bf4d6ade3b
parent ff3133f85a5f28ad326c46a131845ba0c503c078
Author: triesap <tyson@radroots.org>
Date:   Sat, 11 Jul 2026 23:24:48 +0000

crate-surface: use runtime store namespace

- update CLI dependencies to runtime_store and singular event crates
- rename runtime-store path helpers and output fields
- update shared record import and export tests to runtime-store paths
- keep locked CLI validation green without old dependency keys

Diffstat:
MCargo.lock | 40++++++++++++++++++++--------------------
MCargo.toml | 6+++---
Msrc/ops/exec/basket.rs | 8++++----
Msrc/runtime/farm.rs | 20++++++++++----------
Msrc/runtime/farm_config.rs | 10+++++-----
Msrc/runtime/listing.rs | 64++++++++++++++++++++++++++++++++--------------------------------
Dsrc/runtime/local_events.rs | 190-------------------------------------------------------------------------------
Msrc/runtime/mod.rs | 8++++----
Msrc/runtime/order.rs | 86++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/runtime/order/sdk_status.rs | 4++--
Asrc/runtime/runtime_store.rs | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/runtime/sdk.rs | 12++++++------
Msrc/runtime/signer.rs | 2+-
Msrc/runtime/sync.rs | 26+++++++++++++-------------
Msrc/runtime/transport.rs | 2+-
Msrc/runtime/validation_receipt.rs | 4++--
Msrc/view/runtime.rs | 16++++++++--------
Mtests/support/mod.rs | 52+++++++++++++++++++++++++++-------------------------
Mtests/target_cli.rs | 106++++++++++++++++++++++++++++++++++++++++++-------------------------------------
19 files changed, 431 insertions(+), 417 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -3603,7 +3603,7 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" name = "radroots_authority" version = "0.1.0-alpha.2" dependencies = [ - "radroots_events", + "radroots_event", "radroots_nostr", ] @@ -3620,10 +3620,10 @@ dependencies = [ "nostr", "radroots_authority", "radroots_core", - "radroots_events", - "radroots_events_codec", + "radroots_event", + "radroots_event_codec", "radroots_identity", - "radroots_local_events", + "radroots_runtime_store", "radroots_log", "radroots_mesh", "radroots_nostr", @@ -3669,7 +3669,7 @@ dependencies = [ name = "radroots_event_store" version = "0.1.0-alpha.2" dependencies = [ - "radroots_events", + "radroots_event", "radroots_nostr", "radroots_transport", "serde", @@ -3679,7 +3679,7 @@ dependencies = [ ] [[package]] -name = "radroots_events" +name = "radroots_event" version = "0.1.0-alpha.2" dependencies = [ "hex", @@ -3690,12 +3690,12 @@ dependencies = [ ] [[package]] -name = "radroots_events_codec" +name = "radroots_event_codec" version = "0.1.0-alpha.2" dependencies = [ "nostr", "radroots_core", - "radroots_events", + "radroots_event", "serde", "serde_json", ] @@ -3720,7 +3720,7 @@ name = "radroots_identity" version = "0.1.0-alpha.2" dependencies = [ "nostr", - "radroots_events", + "radroots_event", "radroots_protected_store", "radroots_runtime", "radroots_runtime_paths", @@ -3732,7 +3732,7 @@ dependencies = [ ] [[package]] -name = "radroots_local_events" +name = "radroots_runtime_store" version = "0.1.0-alpha.2" dependencies = [ "radroots_sql_core", @@ -3765,8 +3765,8 @@ version = "0.1.0-alpha.2" dependencies = [ "nostr", "nostr-sdk", - "radroots_events", - "radroots_events_codec", + "radroots_event", + "radroots_event_codec", "radroots_identity", "serde", "serde_json", @@ -3823,7 +3823,7 @@ version = "0.1.0-alpha.2" dependencies = [ "hex", "radroots_event_store", - "radroots_events", + "radroots_event", "radroots_transport", "serde", "serde_json", @@ -3873,8 +3873,8 @@ dependencies = [ "base64 0.22.1", "hex", "radroots_core", - "radroots_events", - "radroots_events_codec", + "radroots_event", + "radroots_event_codec", "radroots_replica_db", "radroots_replica_db_schema", "radroots_sql_core", @@ -3924,8 +3924,8 @@ dependencies = [ "nostr", "radroots_authority", "radroots_event_store", - "radroots_events", - "radroots_events_codec", + "radroots_event", + "radroots_event_codec", "radroots_geocoder", "radroots_identity", "radroots_nostr", @@ -4000,8 +4000,8 @@ dependencies = [ "radroots_authority", "radroots_core", "radroots_event_store", - "radroots_events", - "radroots_events_codec", + "radroots_event", + "radroots_event_codec", "serde", "serde_json", "sha2", @@ -4024,7 +4024,7 @@ dependencies = [ "futures", "nostr", "radroots_event_store", - "radroots_events", + "radroots_event", "radroots_nostr", "radroots_outbox", "radroots_transport", diff --git a/Cargo.toml b/Cargo.toml @@ -29,10 +29,10 @@ clap = { version = "4.5", features = ["derive"] } getrandom = "0.2" radroots_authority = { path = "../lib/crates/authority", default-features = false, features = ["std", "local_signer"] } radroots_core = { path = "../lib/crates/core", features = ["std", "serde"] } -radroots_events = { path = "../lib/crates/events" } -radroots_events_codec = { path = "../lib/crates/events_codec", features = ["nostr", "serde_json"] } +radroots_event = { path = "../lib/crates/event" } +radroots_event_codec = { path = "../lib/crates/event_codec", features = ["nostr", "serde_json"] } radroots_identity = { path = "../lib/crates/identity" } -radroots_local_events = { path = "../lib/crates/local_events" } +radroots_runtime_store = { path = "../lib/crates/runtime_store" } radroots_log = { path = "../lib/crates/log" } radroots_mesh = { path = "../lib/crates/mesh", default-features = false } radroots_nostr_accounts = { path = "../lib/crates/nostr_accounts", features = ["os-keyring"] } diff --git a/src/ops/exec/basket.rs b/src/ops/exec/basket.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; -use radroots_events::order::RadrootsOrderEconomics; +use radroots_event::order::RadrootsOrderEconomics; use radroots_replica_db::{ReplicaSql, trade_product}; use radroots_replica_db_schema::trade_product::{ITradeProductFieldsFilter, ITradeProductFindMany}; use radroots_sql_core::SqliteExecutor; @@ -1314,9 +1314,9 @@ fn invalid_input(operation_id: &str, message: String) -> OperationAdapterError { mod tests { use std::path::{Path, PathBuf}; - use radroots_events::RadrootsEventEnvelope; - use radroots_events::ids::RadrootsListingAddress; - use radroots_events::kinds::{KIND_FARM, KIND_LISTING}; + use radroots_event::RadrootsEventEnvelope; + use radroots_event::ids::RadrootsListingAddress; + use radroots_event::kinds::{KIND_FARM, KIND_LISTING}; use radroots_replica_sync::{RadrootsReplicaIngestOutcome, radroots_replica_ingest_event}; use radroots_secret_vault::RadrootsSecretBackend; use radroots_sql_core::{SqlExecutor, SqliteExecutor}; diff --git a/src/runtime/farm.rs b/src/runtime/farm.rs @@ -2,14 +2,14 @@ use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; use radroots_authority::RadrootsActorContext; -use radroots_events::contract::RadrootsActorRole; -use radroots_events::farm::{RadrootsFarm, RadrootsFarmPublicLocation}; -use radroots_events::ids::RadrootsAddressableCoordinate; -use radroots_events::kinds::{KIND_FARM, KIND_PROFILE}; -use radroots_events::listing::RadrootsListingPublicLocation; -use radroots_events::profile::{RadrootsProfile, RadrootsProfileType}; -use radroots_events_codec::d_tag::is_d_tag_base64url; -use radroots_events_codec::profile::encode::to_wire_parts_with_profile_type; +use radroots_event::contract::RadrootsActorRole; +use radroots_event::farm::{RadrootsFarm, RadrootsFarmPublicLocation}; +use radroots_event::ids::RadrootsAddressableCoordinate; +use radroots_event::kinds::{KIND_FARM, KIND_PROFILE}; +use radroots_event::listing::RadrootsListingPublicLocation; +use radroots_event::profile::{RadrootsProfile, RadrootsProfileType}; +use radroots_event_codec::d_tag::is_d_tag_base64url; +use radroots_event_codec::profile::encode::to_wire_parts_with_profile_type; use radroots_sdk::{ FarmEnqueuePublishRequest, FarmEnqueueReceipt, FarmPreparePublishRequest, FarmPrivateLocationClearRequest, FarmPrivateLocationInput, FarmPrivateLocationLookupCandidate, @@ -32,7 +32,7 @@ use crate::runtime::farm_config::{ self, FarmConfigDocument, FarmConfigScope, FarmConfigSelection, FarmListingDefaults, FarmMissingField, FarmPublicationStatus, ResolvedFarmConfig, SUPPORTED_FARM_CONFIG_VERSION, }; -use crate::runtime::local_events::append_local_work; +use crate::runtime::runtime_store::append_local_work; use crate::runtime::sdk::{ CliSdkAdapterError, CliSdkSession, sdk_nostr_relay_url_policy, sdk_target_outcome_kind_label, sdk_target_policy, sdk_transport_outcome_kind_label, validate_configured_signer_for_actor, @@ -2258,7 +2258,7 @@ fn encode_base64url_no_pad(bytes: [u8; 16]) -> String { #[cfg(test)] mod tests { use super::generate_d_tag; - use radroots_events_codec::d_tag::is_d_tag_base64url; + use radroots_event_codec::d_tag::is_d_tag_base64url; #[test] fn generated_farm_d_tag_is_valid_base64url() { diff --git a/src/runtime/farm_config.rs b/src/runtime/farm_config.rs @@ -1,10 +1,10 @@ use std::fs; use std::path::{Path, PathBuf}; -use radroots_events::farm::RadrootsFarm; -use radroots_events::listing::{RadrootsListingDeliveryMethod, RadrootsListingPublicLocation}; -use radroots_events::profile::RadrootsProfile; -use radroots_events_codec::d_tag::is_d_tag_base64url; +use radroots_event::farm::RadrootsFarm; +use radroots_event::listing::{RadrootsListingDeliveryMethod, RadrootsListingPublicLocation}; +use radroots_event::profile::RadrootsProfile; +use radroots_event_codec::d_tag::is_d_tag_base64url; use serde::{Deserialize, Serialize}; use crate::runtime::RuntimeError; @@ -388,7 +388,7 @@ mod tests { use std::path::PathBuf; - use radroots_events::farm::RadrootsFarmPublicLocation; + use radroots_event::farm::RadrootsFarmPublicLocation; use tempfile::tempdir; fn sample_paths(profile: &str, root: &Path) -> PathsConfig { diff --git a/src/runtime/listing.rs b/src/runtime/listing.rs @@ -10,21 +10,21 @@ use radroots_core::{ RadrootsCoreDiscountThreshold, RadrootsCoreDiscountValue, RadrootsCoreMoney, RadrootsCorePercent, RadrootsCoreQuantity, RadrootsCoreQuantityPrice, RadrootsCoreUnit, }; -use radroots_events::RadrootsEventEnvelope; -use radroots_events::contract::RadrootsActorRole; -use radroots_events::farm::RadrootsFarmRef; -use radroots_events::ids::{RadrootsDTag, RadrootsInventoryBinId}; -use radroots_events::kinds::{KIND_LISTING, KIND_LISTING_DRAFT}; -use radroots_events::listing::{ +use radroots_event::RadrootsEventEnvelope; +use radroots_event::contract::RadrootsActorRole; +use radroots_event::farm::RadrootsFarmRef; +use radroots_event::ids::{RadrootsDTag, RadrootsInventoryBinId}; +use radroots_event::kinds::{KIND_LISTING, KIND_LISTING_DRAFT}; +use radroots_event::listing::{ RadrootsListing, RadrootsListingAvailability, RadrootsListingBin, RadrootsListingDeliveryMethod, RadrootsListingProduct, RadrootsListingPublicLocation, RadrootsListingStatus, }; -use radroots_events::trade_validation::RadrootsTradeValidationListingError; -use radroots_events_codec::d_tag::is_d_tag_base64url; -use radroots_events_codec::listing::encode::to_wire_parts_with_kind; -use radroots_local_events::{LocalEventRecord, LocalRecordFamily, SourceRuntime}; +use radroots_event::trade_validation::RadrootsTradeValidationListingError; +use radroots_event_codec::d_tag::is_d_tag_base64url; +use radroots_event_codec::listing::encode::to_wire_parts_with_kind; use radroots_replica_db::ReplicaSql; +use radroots_runtime_store::{RuntimeStoreRecord, RuntimeStoreRecordFamily, SourceRuntime}; use radroots_sdk::{ ListingEnqueuePublishRequest, ListingEnqueueReceipt, ListingPreparePublishRequest, ListingPublishPlan, PushOutboxEventReceipt, PushOutboxEventState, PushOutboxReceipt, @@ -43,9 +43,9 @@ use crate::runtime::RuntimeError; use crate::runtime::account; use crate::runtime::config::RuntimeConfig; use crate::runtime::farm_config; -use crate::runtime::local_events::{ +use crate::runtime::runtime_store::{ append_local_work, get_shared_record, list_shared_records_before, list_shared_records_latest, - shared_local_events_db_path, + shared_runtime_store_db_path, }; use crate::runtime::sdk::{ CliSdkAdapterError, CliSdkSession, sdk_nostr_relay_url_policy, sdk_target_outcome_kind_label, @@ -65,7 +65,7 @@ use crate::view::runtime::{ const DRAFT_KIND: &str = "listing_draft_v1"; const LISTING_SOURCE: &str = "local draft · local first"; const LISTING_READ_SOURCE: &str = "local replica · local first"; -const LISTING_APP_RECORD_SOURCE: &str = "shared local events · app"; +const LISTING_APP_RECORD_SOURCE: &str = "shared runtime store · app"; const SDK_LISTING_WRITE_SOURCE: &str = "SDK listing publish · configured signer"; const LISTING_DRAFTS_DIR: &str = "listings/drafts"; const LISTING_SELLER_ACTOR_SOURCE_FARM_CONFIG: &str = "farm_config"; @@ -686,7 +686,7 @@ pub fn list(config: &RuntimeConfig) -> Result<ListingListView, RuntimeError> { } pub fn app_record_list(config: &RuntimeConfig) -> Result<ListingAppRecordListView, RuntimeError> { - let database_path = shared_local_events_db_path(config)?; + let database_path = shared_runtime_store_db_path(config)?; let mut entries = current_app_record_entries(app_local_records(config)?); let has_more = entries.len() > APP_RECORD_LIST_LIMIT as usize; if has_more { @@ -718,7 +718,7 @@ pub fn app_record_list(config: &RuntimeConfig) -> Result<ListingAppRecordListVie has_more, next_before_change_seq: next_cursor.map(|(change_seq, _)| change_seq), next_before_seq: next_cursor.map(|(_, seq)| seq), - local_events_db: database_path.display().to_string(), + runtime_store_db: database_path.display().to_string(), records, actions, }) @@ -1192,11 +1192,11 @@ fn summary_for_invalid_file(path: &Path, issue: ListingValidationIssueView) -> L #[derive(Debug, Clone)] struct AppRecordListEntry { - record: LocalEventRecord, + record: RuntimeStoreRecord, superseded_count: usize, } -fn app_local_records(config: &RuntimeConfig) -> Result<Vec<LocalEventRecord>, RuntimeError> { +fn app_local_records(config: &RuntimeConfig) -> Result<Vec<RuntimeStoreRecord>, RuntimeError> { let mut app_records = Vec::new(); let mut before_cursor = None::<(i64, i64)>; loop { @@ -1230,16 +1230,16 @@ fn app_local_records(config: &RuntimeConfig) -> Result<Vec<LocalEventRecord>, Ru Ok(app_records) } -fn is_supported_app_local_record(record: &LocalEventRecord) -> bool { +fn is_supported_app_local_record(record: &RuntimeStoreRecord) -> bool { record.source_runtime == SourceRuntime::App - && record.family == LocalRecordFamily::LocalWork + && record.family == RuntimeStoreRecordFamily::LocalWork && matches!( local_record_kind(record).as_deref(), Some("farm_config_v1" | DRAFT_KIND) ) } -fn current_app_record_entries(mut records: Vec<LocalEventRecord>) -> Vec<AppRecordListEntry> { +fn current_app_record_entries(mut records: Vec<RuntimeStoreRecord>) -> Vec<AppRecordListEntry> { records.sort_by(|left, right| { right .change_seq @@ -1267,8 +1267,8 @@ fn current_app_record_entries(mut records: Vec<LocalEventRecord>) -> Vec<AppReco fn current_app_record_for( config: &RuntimeConfig, - record: &LocalEventRecord, -) -> Result<Option<LocalEventRecord>, RuntimeError> { + record: &RuntimeStoreRecord, +) -> Result<Option<RuntimeStoreRecord>, RuntimeError> { let key = app_record_current_key(record); Ok(app_local_records(config)? .into_iter() @@ -1281,7 +1281,7 @@ fn current_app_record_for( } fn app_record_summary( - record: &LocalEventRecord, + record: &RuntimeStoreRecord, superseded_count: usize, ) -> ListingAppRecordSummaryView { let record_kind = local_record_kind(record).unwrap_or_else(|| "unknown".to_owned()); @@ -1348,7 +1348,7 @@ fn app_record_summary( } } -fn app_record_current_key(record: &LocalEventRecord) -> String { +fn app_record_current_key(record: &RuntimeStoreRecord) -> String { match local_record_kind(record).as_deref() { Some(DRAFT_KIND) => { if let Some(listing_addr) = record @@ -1400,7 +1400,7 @@ fn canonical_hex_pubkey(value: &str) -> Option<String> { } } -fn app_record_canonical_owner_pubkey(record: &LocalEventRecord) -> Option<String> { +fn app_record_canonical_owner_pubkey(record: &RuntimeStoreRecord) -> Option<String> { record .owner_pubkey .as_deref() @@ -1408,7 +1408,7 @@ fn app_record_canonical_owner_pubkey(record: &LocalEventRecord) -> Option<String } fn app_listing_display_parts( - record: &LocalEventRecord, + record: &RuntimeStoreRecord, ) -> (Option<String>, Option<String>, Option<String>) { let document = record .local_work_json @@ -1432,7 +1432,7 @@ fn app_listing_display_parts( (listing_id, title, farm_d_tag) } -fn app_record_exportability_reason(record: &LocalEventRecord) -> Option<String> { +fn app_record_exportability_reason(record: &RuntimeStoreRecord) -> Option<String> { if local_record_kind(record).as_deref() == Some(DRAFT_KIND) && app_record_canonical_owner_pubkey(record).is_none() { @@ -1464,7 +1464,7 @@ fn app_record_exportability_reason(record: &LocalEventRecord) -> Option<String> } fn app_listing_draft_from_record( - record: &LocalEventRecord, + record: &RuntimeStoreRecord, ) -> Result<ListingDraftDocument, String> { if record.source_runtime != SourceRuntime::App { return Err(format!( @@ -1472,7 +1472,7 @@ fn app_listing_draft_from_record( record.source_runtime.as_str() )); } - if record.family != LocalRecordFamily::LocalWork { + if record.family != RuntimeStoreRecordFamily::LocalWork { return Err(format!( "record family `{}` is not local_work", record.family.as_str() @@ -1593,7 +1593,7 @@ fn app_record_listing_addr(draft: &ListingDraftDocument) -> Option<String> { } } -fn local_record_kind(record: &LocalEventRecord) -> Option<String> { +fn local_record_kind(record: &RuntimeStoreRecord) -> Option<String> { record .local_work_json .as_ref() @@ -3140,8 +3140,8 @@ mod tests { sdk_push_accepted_transport_endpoints, sdk_push_failed_transport_targets, }; use crate::cli::global::ListingMutationArgs; - use radroots_events::ids::RadrootsEventId; - use radroots_events_codec::d_tag::is_d_tag_base64url; + use radroots_event::ids::RadrootsEventId; + use radroots_event_codec::d_tag::is_d_tag_base64url; use radroots_sdk::{ PushOutboxEventReceipt, PushOutboxEventState, PushOutboxTargetOutcomeKind, PushOutboxTargetReceipt, PushOutboxTransportOutcomeKind, diff --git a/src/runtime/local_events.rs b/src/runtime/local_events.rs @@ -1,190 +0,0 @@ -use std::fs; -use std::path::PathBuf; -use std::sync::atomic::{AtomicU64, Ordering}; -use std::time::{SystemTime, UNIX_EPOCH}; - -use radroots_local_events::{ - LocalEventRecord, LocalEventRecordInput, LocalEventsStore, LocalRecordFamily, - LocalRecordStatus, PublishOutboxStatus, SourceRuntime, -}; -use radroots_runtime_paths::{ - default_shared_local_events_database_path_from_shared_accounts_data_root, - default_shared_local_events_root_from_shared_accounts_data_root, -}; -use radroots_sql_core::SqliteExecutor; -use serde_json::Value; - -use crate::runtime::RuntimeError; -use crate::runtime::config::{PathsConfig, RuntimeConfig}; - -static RECORD_COUNTER: AtomicU64 = AtomicU64::new(0); - -pub fn append_local_work( - config: &RuntimeConfig, - subject: &str, - owner_account_id: Option<String>, - owner_pubkey: Option<String>, - farm_id: Option<String>, - listing_addr: Option<String>, - payload: Value, -) -> Result<LocalEventRecord, RuntimeError> { - let timestamp = current_time_ms()?; - let sequence = RECORD_COUNTER.fetch_add(1, Ordering::Relaxed); - let input = LocalEventRecordInput { - record_id: format!("cli:local_work:{subject}:{timestamp}:{sequence}"), - family: LocalRecordFamily::LocalWork, - status: LocalRecordStatus::LocalSaved, - source_runtime: SourceRuntime::Cli, - created_at_ms: timestamp, - inserted_at_ms: timestamp, - owner_account_id, - owner_pubkey, - farm_id, - listing_addr, - local_work_json: Some(payload), - event_id: None, - event_kind: None, - event_pubkey: None, - event_created_at: None, - event_tags_json: None, - event_content: None, - event_sig: None, - raw_event_json: None, - outbox_status: PublishOutboxStatus::None, - }; - let store = open_store(config)?; - Ok(store.append_record(&input)?) -} - -pub fn shared_local_events_db_path(config: &RuntimeConfig) -> Result<PathBuf, RuntimeError> { - shared_local_events_db_path_from_paths(&config.paths) -} - -fn shared_local_events_db_path_from_paths(paths: &PathsConfig) -> Result<PathBuf, RuntimeError> { - default_shared_local_events_database_path_from_shared_accounts_data_root( - &paths.shared_accounts_data_root, - ) - .map_err(|err| { - RuntimeError::Config(format!("resolve shared local-events database path: {err}")) - }) -} - -pub fn list_shared_records_latest( - config: &RuntimeConfig, - limit: u32, -) -> Result<Vec<LocalEventRecord>, RuntimeError> { - let database_path = shared_local_events_db_path(config)?; - if !database_path.exists() { - return Ok(Vec::new()); - } - let executor = SqliteExecutor::open(database_path)?; - let store = LocalEventsStore::new(executor); - Ok(store.list_records_changed_latest(limit)?) -} - -pub fn list_shared_records_before( - config: &RuntimeConfig, - before_change_seq: i64, - before_seq: i64, - limit: u32, -) -> Result<Vec<LocalEventRecord>, RuntimeError> { - let database_path = shared_local_events_db_path(config)?; - if !database_path.exists() { - return Ok(Vec::new()); - } - let executor = SqliteExecutor::open(database_path)?; - let store = LocalEventsStore::new(executor); - Ok(store.list_records_changed_before(before_change_seq, before_seq, limit)?) -} - -pub fn get_shared_record( - config: &RuntimeConfig, - record_id: &str, -) -> Result<Option<LocalEventRecord>, RuntimeError> { - let database_path = shared_local_events_db_path(config)?; - if !database_path.exists() { - return Ok(None); - } - let executor = SqliteExecutor::open(database_path)?; - let store = LocalEventsStore::new(executor); - Ok(store.get_record(record_id)?) -} - -fn open_store(config: &RuntimeConfig) -> Result<LocalEventsStore<SqliteExecutor>, RuntimeError> { - let root = shared_local_events_root_from_paths(&config.paths)?; - fs::create_dir_all(&root)?; - let executor = SqliteExecutor::open(shared_local_events_db_path_from_paths(&config.paths)?)?; - let store = LocalEventsStore::new(executor); - store.migrate_up()?; - Ok(store) -} - -fn shared_local_events_root_from_paths(paths: &PathsConfig) -> Result<PathBuf, RuntimeError> { - default_shared_local_events_root_from_shared_accounts_data_root( - &paths.shared_accounts_data_root, - ) - .map_err(|err| RuntimeError::Config(format!("resolve shared local-events root: {err}"))) -} - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use super::{shared_local_events_db_path_from_paths, shared_local_events_root_from_paths}; - use crate::runtime::config::PathsConfig; - - #[test] - fn shared_local_events_paths_use_shared_runtime_contract() { - let paths = paths_config("/repo/infra/local/runtime/radroots/data/shared/accounts"); - - assert_eq!( - shared_local_events_root_from_paths(&paths).expect("shared local-events root"), - PathBuf::from("/repo/infra/local/runtime/radroots/data/shared/local_events") - ); - assert_eq!( - shared_local_events_db_path_from_paths(&paths).expect("shared local-events database"), - PathBuf::from( - "/repo/infra/local/runtime/radroots/data/shared/local_events/local_events.sqlite" - ) - ); - } - - fn paths_config(shared_accounts_data_root: &str) -> PathsConfig { - PathsConfig { - profile: "repo_local".to_owned(), - profile_source: "test".to_owned(), - allowed_profiles: vec!["repo_local".to_owned()], - root_source: "repo_local_root".to_owned(), - repo_local_root: Some(PathBuf::from("/repo/infra/local/runtime/radroots")), - repo_local_root_source: Some("test".to_owned()), - subordinate_path_override_source: "runtime_config".to_owned(), - app_namespace: "apps/cli".to_owned(), - shared_accounts_namespace: "shared/accounts".to_owned(), - shared_identities_namespace: "shared/identities".to_owned(), - app_config_path: PathBuf::from( - "/repo/infra/local/runtime/radroots/config/apps/cli/config.toml", - ), - workspace_config_path: None, - app_data_root: PathBuf::from("/repo/infra/local/runtime/radroots/data/apps/cli"), - shared_cache_root: PathBuf::from("/repo/infra/local/runtime/radroots/cache"), - app_logs_root: PathBuf::from("/repo/infra/local/runtime/radroots/logs/apps/cli"), - shared_accounts_data_root: PathBuf::from(shared_accounts_data_root), - shared_accounts_secrets_root: PathBuf::from( - "/repo/infra/local/runtime/radroots/secrets/shared/accounts", - ), - default_identity_path: PathBuf::from( - "/repo/infra/local/runtime/radroots/secrets/shared/identities/default.json", - ), - } - } -} - -fn current_time_ms() -> Result<i64, RuntimeError> { - let duration = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map_err(|error| { - RuntimeError::Config(format!("system clock is before unix epoch: {error}")) - })?; - i64::try_from(duration.as_millis()) - .map_err(|_| RuntimeError::Config("current timestamp exceeds i64 milliseconds".to_owned())) -} diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs @@ -5,12 +5,12 @@ pub mod farm_config; pub mod find; pub mod hyf; pub mod listing; -pub mod local_events; pub mod logging; pub mod mesh; pub mod order; pub mod paths; pub mod provider; +pub mod runtime_store; pub mod sdk; pub mod signer; pub mod store; @@ -34,8 +34,8 @@ pub enum RuntimeError { Sql(#[from] radroots_replica_db::SqlError), #[error("replica sync error: {0}")] ReplicaSync(#[from] radroots_replica_sync::RadrootsReplicaEventsError), - #[error("local events error: {0}")] - LocalEvents(#[from] radroots_local_events::LocalEventsError), + #[error("runtime store error: {0}")] + RuntimeStore(#[from] radroots_runtime_store::RuntimeStoreError), #[error("network error: {0}")] Network(String), #[error("failed to serialize json output: {0}")] @@ -52,7 +52,7 @@ impl RuntimeError { | Self::Accounts(_) | Self::Sql(_) | Self::ReplicaSync(_) - | Self::LocalEvents(_) + | Self::RuntimeStore(_) | Self::Network(_) | Self::Json(_) | Self::Io(_) => ExitCode::from(1), diff --git a/src/runtime/order.rs b/src/runtime/order.rs @@ -12,29 +12,24 @@ use radroots_core::{ RadrootsCoreDiscountThreshold, RadrootsCoreDiscountValue, RadrootsCoreMoney, RadrootsCoreUnit, convert_unit_decimal, }; -use radroots_events::RadrootsEventPtr; -use radroots_events::contract::RadrootsActorRole; -use radroots_events::ids::{ +use radroots_event::RadrootsEventPtr; +use radroots_event::contract::RadrootsActorRole; +use radroots_event::ids::{ RadrootsEventId, RadrootsInventoryBinId, RadrootsListingAddress, RadrootsOrderId, RadrootsOrderQuoteId, RadrootsOrderRevisionId, RadrootsPublicKey, }; -use radroots_events::kinds::{ +use radroots_event::kinds::{ KIND_LISTING, KIND_ORDER_CANCELLATION, KIND_ORDER_DECISION, KIND_ORDER_REQUEST, KIND_ORDER_REVISION_DECISION, KIND_ORDER_REVISION_PROPOSAL, }; -use radroots_events::order::{ +use radroots_event::order::{ RadrootsOrderEconomicActor, RadrootsOrderEconomicEffect, RadrootsOrderEconomicItem, RadrootsOrderEconomicLine, RadrootsOrderEconomicLineKind, RadrootsOrderEconomics, RadrootsOrderEventType, RadrootsOrderInventoryCommitment, RadrootsOrderItem, RadrootsOrderPricingBasis, RadrootsOrderRequest, RadrootsOrderRevisionOutcome, }; -use radroots_events_codec::d_tag::is_d_tag_base64url; -use radroots_events_codec::order::{order_event_context_from_tags, order_request_from_event}; -use radroots_local_events::{ - BUYER_ORDER_REQUEST_LOCAL_WORK_RECORD_KIND, LocalEventRecord, LocalRecordFamily, - LocalRecordStatus, PublishOutboxStatus, SourceRuntime, - validate_supported_buyer_order_request_local_work_payload, -}; +use radroots_event_codec::d_tag::is_d_tag_base64url; +use radroots_event_codec::order::{order_event_context_from_tags, order_request_from_event}; use radroots_nostr::prelude::{ RadrootsNostrEvent, RadrootsNostrFilter, radroots_event_from_nostr, radroots_nostr_filter_tag, radroots_nostr_kind, @@ -48,6 +43,11 @@ use radroots_replica_db_schema::nostr_event_head::{ use radroots_replica_db_schema::trade_product::{ ITradeProductFieldsFilter, ITradeProductFindMany, TradeProduct, }; +use radroots_runtime_store::{ + BUYER_ORDER_REQUEST_LOCAL_WORK_RECORD_KIND, PublishOutboxStatus, RuntimeStoreRecord, + RuntimeStoreRecordFamily, RuntimeStoreRecordStatus, SourceRuntime, + validate_supported_buyer_order_request_local_work_payload, +}; use radroots_sdk::{ PrivacyPreflightConfirmation, ProductSensitivityField, PublishMode, PushOutboxEventReceipt, PushOutboxEventState, PushOutboxReceipt, PushOutboxTargetOutcomeKind, SatisfactionPolicy, @@ -77,9 +77,9 @@ use crate::cli::global::{ use crate::runtime::RuntimeError; use crate::runtime::account; use crate::runtime::config::RuntimeConfig; -use crate::runtime::local_events::{ +use crate::runtime::runtime_store::{ get_shared_record, list_shared_records_before, list_shared_records_latest, - shared_local_events_db_path, + shared_runtime_store_db_path, }; use crate::runtime::sdk::{ CliSdkAdapterError, CliSdkSession, fetch_relay_events_via_shared_transport, @@ -314,7 +314,7 @@ struct LoadedAppOrderRecord { #[derive(Debug, Clone)] struct AppOrderRecordListEntry { - record: LocalEventRecord, + record: RuntimeStoreRecord, superseded_count: usize, } @@ -711,7 +711,7 @@ pub fn list(config: &RuntimeConfig) -> Result<OrderListView, RuntimeError> { } pub fn app_record_list(config: &RuntimeConfig) -> Result<OrderAppRecordListView, RuntimeError> { - let database_path = shared_local_events_db_path(config)?; + let database_path = shared_runtime_store_db_path(config)?; let mut entries = current_app_order_record_entries(app_order_local_records(config)?); let has_more = entries.len() > ORDER_APP_RECORD_LIST_LIMIT as usize; if has_more { @@ -743,7 +743,7 @@ pub fn app_record_list(config: &RuntimeConfig) -> Result<OrderAppRecordListView, has_more, next_before_change_seq: next_cursor.map(|(change_seq, _)| change_seq), next_before_seq: next_cursor.map(|(_, seq)| seq), - local_events_db: database_path.display().to_string(), + runtime_store_db: database_path.display().to_string(), records, actions, }) @@ -3441,7 +3441,9 @@ fn summary_for_invalid_file(path: &Path, reason: String) -> OrderSummaryView { } } -fn app_order_local_records(config: &RuntimeConfig) -> Result<Vec<LocalEventRecord>, RuntimeError> { +fn app_order_local_records( + config: &RuntimeConfig, +) -> Result<Vec<RuntimeStoreRecord>, RuntimeError> { let mut app_records = Vec::new(); let mut before_cursor = None::<(i64, i64)>; loop { @@ -3471,15 +3473,15 @@ fn app_order_local_records(config: &RuntimeConfig) -> Result<Vec<LocalEventRecor Ok(app_records) } -fn is_app_order_local_record(record: &LocalEventRecord) -> bool { +fn is_app_order_local_record(record: &RuntimeStoreRecord) -> bool { record.source_runtime == SourceRuntime::App - && record.family == LocalRecordFamily::LocalWork - && record.status == LocalRecordStatus::LocalSaved + && record.family == RuntimeStoreRecordFamily::LocalWork + && record.status == RuntimeStoreRecordStatus::LocalSaved && local_record_kind(record).as_deref() == Some(BUYER_ORDER_REQUEST_LOCAL_WORK_RECORD_KIND) } fn current_app_order_record_entries( - mut records: Vec<LocalEventRecord>, + mut records: Vec<RuntimeStoreRecord>, ) -> Vec<AppOrderRecordListEntry> { records.sort_by(|left, right| { right @@ -3508,8 +3510,8 @@ fn current_app_order_record_entries( fn current_app_order_record_for( config: &RuntimeConfig, - record: &LocalEventRecord, -) -> Result<Option<LocalEventRecord>, RuntimeError> { + record: &RuntimeStoreRecord, +) -> Result<Option<RuntimeStoreRecord>, RuntimeError> { let key = app_order_record_current_key(record); Ok(app_order_local_records(config)? .into_iter() @@ -3523,7 +3525,7 @@ fn current_app_order_record_for( fn app_order_conflicting_record_ids_for( config: &RuntimeConfig, - record: &LocalEventRecord, + record: &RuntimeStoreRecord, ) -> Result<Vec<String>, RuntimeError> { if app_order_record_order_id(record).is_none() { return Ok(Vec::new()); @@ -3559,7 +3561,7 @@ fn load_app_order_record_for_lookup( fn load_app_order_record_from_record( config: &RuntimeConfig, - record: LocalEventRecord, + record: RuntimeStoreRecord, ) -> Result<LoadedAppOrderRecord, RuntimeError> { let mut source_issues = app_order_record_source_issues(config, &record)?; let payload = record.local_work_json.clone().unwrap_or(Value::Null); @@ -3585,7 +3587,7 @@ fn load_app_order_record_from_record( } }; let loaded = LoadedOrderDraft { - file: PathBuf::from(format!("shared-local-events/{}", record.record_id)), + file: PathBuf::from(format!("shared-runtime-store/{}", record.record_id)), updated_at_unix: u64::try_from(record.updated_at_ms / 1000).unwrap_or_default(), document, }; @@ -3599,7 +3601,7 @@ fn load_app_order_record_from_record( fn app_order_record_source_issues( config: &RuntimeConfig, - record: &LocalEventRecord, + record: &RuntimeStoreRecord, ) -> Result<Vec<OrderIssueView>, RuntimeError> { let mut issues = Vec::new(); if record.source_runtime != SourceRuntime::App { @@ -3609,14 +3611,14 @@ fn app_order_record_source_issues( "trade record must come from radroots_studio_app", )); } - if record.family != LocalRecordFamily::LocalWork { + if record.family != RuntimeStoreRecordFamily::LocalWork { issues.push(issue_with_code( "app_order_unsupported", "family", "trade record must be shared local work", )); } - if record.status != LocalRecordStatus::LocalSaved { + if record.status != RuntimeStoreRecordStatus::LocalSaved { issues.push(issue_with_code( "app_order_unsupported", "status", @@ -3796,7 +3798,7 @@ fn app_order_signed_evidence_issues( fn visible_signed_order_request_records( config: &RuntimeConfig, order_id: &str, -) -> Result<Vec<LocalEventRecord>, RuntimeError> { +) -> Result<Vec<RuntimeStoreRecord>, RuntimeError> { let mut records = Vec::new(); let mut before_cursor = None::<(i64, i64)>; loop { @@ -3830,9 +3832,9 @@ fn visible_signed_order_request_records( Ok(records) } -fn is_visible_signed_order_request_record(record: &LocalEventRecord, order_id: &str) -> bool { - record.family == LocalRecordFamily::SignedEvent - && record.status == LocalRecordStatus::Published +fn is_visible_signed_order_request_record(record: &RuntimeStoreRecord, order_id: &str) -> bool { + record.family == RuntimeStoreRecordFamily::SignedEvent + && record.status == RuntimeStoreRecordStatus::Published && record.outbox_status == PublishOutboxStatus::Acknowledged && record.event_kind == Some(i64::from(KIND_ORDER_REQUEST)) && signed_record_tag_values(record, "d") @@ -3841,7 +3843,7 @@ fn is_visible_signed_order_request_record(record: &LocalEventRecord, order_id: & } fn signed_order_request_from_record( - record: &LocalEventRecord, + record: &RuntimeStoreRecord, ) -> Result<RadrootsNostrEvent, RuntimeError> { let raw_event_json = record.raw_event_json.as_ref().ok_or_else(|| { RuntimeError::Config(format!( @@ -3857,7 +3859,7 @@ fn signed_order_request_from_record( }) } -fn signed_record_tag_values(record: &LocalEventRecord, key: &str) -> Vec<String> { +fn signed_record_tag_values(record: &RuntimeStoreRecord, key: &str) -> Vec<String> { record .event_tags_json .as_ref() @@ -3881,7 +3883,7 @@ fn signed_record_tag_values(record: &LocalEventRecord, key: &str) -> Vec<String> .unwrap_or_default() } -fn signed_record_event_id(record: &LocalEventRecord) -> String { +fn signed_record_event_id(record: &RuntimeStoreRecord) -> String { record .event_id .clone() @@ -3902,7 +3904,7 @@ fn source_and_document_issues( fn app_order_record_summary( config: &RuntimeConfig, - record: &LocalEventRecord, + record: &RuntimeStoreRecord, superseded_count: usize, ) -> Result<OrderAppRecordSummaryView, RuntimeError> { let record_kind = local_record_kind(record).unwrap_or_else(|| "unknown".to_owned()); @@ -3964,13 +3966,13 @@ fn app_order_record_summary( }) } -fn app_order_record_current_key(record: &LocalEventRecord) -> String { +fn app_order_record_current_key(record: &RuntimeStoreRecord) -> String { app_order_record_order_id(record) .map(|order_id| format!("order:{order_id}")) .unwrap_or_else(|| format!("record:{}", record.record_id)) } -fn app_order_record_order_id(record: &LocalEventRecord) -> Option<String> { +fn app_order_record_order_id(record: &RuntimeStoreRecord) -> Option<String> { record .local_work_json .as_ref() @@ -3980,7 +3982,7 @@ fn app_order_record_order_id(record: &LocalEventRecord) -> Option<String> { .map(str::to_owned) } -fn placeholder_app_order_document(record: &LocalEventRecord) -> OrderDraftDocument { +fn placeholder_app_order_document(record: &RuntimeStoreRecord) -> OrderDraftDocument { OrderDraftDocument { version: 0, kind: "invalid_app_order_record".to_owned(), @@ -4077,7 +4079,7 @@ fn validate_order_export_output_target(output_path: &Path) -> Result<(), Runtime Ok(()) } -fn local_record_kind(record: &LocalEventRecord) -> Option<String> { +fn local_record_kind(record: &RuntimeStoreRecord) -> Option<String> { record .local_work_json .as_ref() diff --git a/src/runtime/order/sdk_status.rs b/src/runtime/order/sdk_status.rs @@ -1,6 +1,6 @@ -use radroots_events::ids::RadrootsEventId; +use radroots_event::ids::RadrootsEventId; #[cfg(test)] -use radroots_events::ids::RadrootsOrderId; +use radroots_event::ids::RadrootsOrderId; use radroots_sdk::{ SdkTradeStatusIssue, TradeStatusAmbiguityCandidate, TradeStatusEligibility, TradeStatusEvidenceSummary, TradeStatusKind, TradeStatusNextActionKind, TradeStatusReceipt, diff --git a/src/runtime/runtime_store.rs b/src/runtime/runtime_store.rs @@ -0,0 +1,192 @@ +use std::fs; +use std::path::PathBuf; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::time::{SystemTime, UNIX_EPOCH}; + +use radroots_runtime_paths::{ + default_shared_runtime_store_database_path_from_shared_accounts_data_root, + default_shared_runtime_store_root_from_shared_accounts_data_root, +}; +use radroots_runtime_store::{ + PublishOutboxStatus, RuntimeStore, RuntimeStoreRecord, RuntimeStoreRecordFamily, + RuntimeStoreRecordInput, RuntimeStoreRecordStatus, SourceRuntime, +}; +use radroots_sql_core::SqliteExecutor; +use serde_json::Value; + +use crate::runtime::RuntimeError; +use crate::runtime::config::{PathsConfig, RuntimeConfig}; + +static RECORD_COUNTER: AtomicU64 = AtomicU64::new(0); + +pub fn append_local_work( + config: &RuntimeConfig, + subject: &str, + owner_account_id: Option<String>, + owner_pubkey: Option<String>, + farm_id: Option<String>, + listing_addr: Option<String>, + payload: Value, +) -> Result<RuntimeStoreRecord, RuntimeError> { + let timestamp = current_time_ms()?; + let sequence = RECORD_COUNTER.fetch_add(1, Ordering::Relaxed); + let input = RuntimeStoreRecordInput { + record_id: format!("cli:local_work:{subject}:{timestamp}:{sequence}"), + family: RuntimeStoreRecordFamily::LocalWork, + status: RuntimeStoreRecordStatus::LocalSaved, + source_runtime: SourceRuntime::Cli, + created_at_ms: timestamp, + inserted_at_ms: timestamp, + owner_account_id, + owner_pubkey, + farm_id, + listing_addr, + local_work_json: Some(payload), + event_id: None, + event_kind: None, + event_pubkey: None, + event_created_at: None, + event_tags_json: None, + event_content: None, + event_sig: None, + raw_event_json: None, + outbox_status: PublishOutboxStatus::None, + relay_set_fingerprint: None, + relay_delivery_json: None, + }; + let store = open_store(config)?; + Ok(store.append_record(&input)?) +} + +pub fn shared_runtime_store_db_path(config: &RuntimeConfig) -> Result<PathBuf, RuntimeError> { + shared_runtime_store_db_path_from_paths(&config.paths) +} + +fn shared_runtime_store_db_path_from_paths(paths: &PathsConfig) -> Result<PathBuf, RuntimeError> { + default_shared_runtime_store_database_path_from_shared_accounts_data_root( + &paths.shared_accounts_data_root, + ) + .map_err(|err| { + RuntimeError::Config(format!("resolve shared runtime-store database path: {err}")) + }) +} + +pub fn list_shared_records_latest( + config: &RuntimeConfig, + limit: u32, +) -> Result<Vec<RuntimeStoreRecord>, RuntimeError> { + let database_path = shared_runtime_store_db_path(config)?; + if !database_path.exists() { + return Ok(Vec::new()); + } + let executor = SqliteExecutor::open(database_path)?; + let store = RuntimeStore::new(executor); + Ok(store.list_records_changed_latest(limit)?) +} + +pub fn list_shared_records_before( + config: &RuntimeConfig, + before_change_seq: i64, + before_seq: i64, + limit: u32, +) -> Result<Vec<RuntimeStoreRecord>, RuntimeError> { + let database_path = shared_runtime_store_db_path(config)?; + if !database_path.exists() { + return Ok(Vec::new()); + } + let executor = SqliteExecutor::open(database_path)?; + let store = RuntimeStore::new(executor); + Ok(store.list_records_changed_before(before_change_seq, before_seq, limit)?) +} + +pub fn get_shared_record( + config: &RuntimeConfig, + record_id: &str, +) -> Result<Option<RuntimeStoreRecord>, RuntimeError> { + let database_path = shared_runtime_store_db_path(config)?; + if !database_path.exists() { + return Ok(None); + } + let executor = SqliteExecutor::open(database_path)?; + let store = RuntimeStore::new(executor); + Ok(store.get_record(record_id)?) +} + +fn open_store(config: &RuntimeConfig) -> Result<RuntimeStore<SqliteExecutor>, RuntimeError> { + let root = shared_runtime_store_root_from_paths(&config.paths)?; + fs::create_dir_all(&root)?; + let executor = SqliteExecutor::open(shared_runtime_store_db_path_from_paths(&config.paths)?)?; + let store = RuntimeStore::new(executor); + store.migrate_up()?; + Ok(store) +} + +fn shared_runtime_store_root_from_paths(paths: &PathsConfig) -> Result<PathBuf, RuntimeError> { + default_shared_runtime_store_root_from_shared_accounts_data_root( + &paths.shared_accounts_data_root, + ) + .map_err(|err| RuntimeError::Config(format!("resolve shared runtime-store root: {err}"))) +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use super::{shared_runtime_store_db_path_from_paths, shared_runtime_store_root_from_paths}; + use crate::runtime::config::PathsConfig; + + #[test] + fn shared_runtime_store_paths_use_shared_runtime_contract() { + let paths = paths_config("/repo/infra/local/runtime/radroots/data/shared/accounts"); + + assert_eq!( + shared_runtime_store_root_from_paths(&paths).expect("shared runtime-store root"), + PathBuf::from("/repo/infra/local/runtime/radroots/data/shared/runtime_store") + ); + assert_eq!( + shared_runtime_store_db_path_from_paths(&paths).expect("shared runtime-store database"), + PathBuf::from( + "/repo/infra/local/runtime/radroots/data/shared/runtime_store/runtime_store.sqlite" + ) + ); + } + + fn paths_config(shared_accounts_data_root: &str) -> PathsConfig { + PathsConfig { + profile: "repo_local".to_owned(), + profile_source: "test".to_owned(), + allowed_profiles: vec!["repo_local".to_owned()], + root_source: "repo_local_root".to_owned(), + repo_local_root: Some(PathBuf::from("/repo/infra/local/runtime/radroots")), + repo_local_root_source: Some("test".to_owned()), + subordinate_path_override_source: "runtime_config".to_owned(), + app_namespace: "apps/cli".to_owned(), + shared_accounts_namespace: "shared/accounts".to_owned(), + shared_identities_namespace: "shared/identities".to_owned(), + app_config_path: PathBuf::from( + "/repo/infra/local/runtime/radroots/config/apps/cli/config.toml", + ), + workspace_config_path: None, + app_data_root: PathBuf::from("/repo/infra/local/runtime/radroots/data/apps/cli"), + shared_cache_root: PathBuf::from("/repo/infra/local/runtime/radroots/cache"), + app_logs_root: PathBuf::from("/repo/infra/local/runtime/radroots/logs/apps/cli"), + shared_accounts_data_root: PathBuf::from(shared_accounts_data_root), + shared_accounts_secrets_root: PathBuf::from( + "/repo/infra/local/runtime/radroots/secrets/shared/accounts", + ), + default_identity_path: PathBuf::from( + "/repo/infra/local/runtime/radroots/secrets/shared/identities/default.json", + ), + } + } +} + +fn current_time_ms() -> Result<i64, RuntimeError> { + let duration = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|error| { + RuntimeError::Config(format!("system clock is before unix epoch: {error}")) + })?; + i64::try_from(duration.as_millis()) + .map_err(|_| RuntimeError::Config("current timestamp exceeds i64 milliseconds".to_owned())) +} diff --git a/src/runtime/sdk.rs b/src/runtime/sdk.rs @@ -835,14 +835,14 @@ mod tests { }, DirectRrRsDependency { section: "dependencies", - name: "radroots_events", + name: "radroots_event", owner: "cli-drafts-and-non-migrated-workflows", reason: "event DTOs for local drafts, views, relay reads, and validation receipt surfaces", lifecycle: "retain until the remaining event-authoring and inspection surfaces migrate", }, DirectRrRsDependency { section: "dependencies", - name: "radroots_events_codec", + name: "radroots_event_codec", owner: "cli-drafts-and-non-migrated-workflows", reason: "event encoding and decoding for farm, listing draft, order, sync pull, and validation inspection", lifecycle: "retain until those command families are SDK-backed", @@ -856,10 +856,10 @@ mod tests { }, DirectRrRsDependency { section: "dependencies", - name: "radroots_local_events", + name: "radroots_runtime_store", owner: "cli-app-interop", reason: "shared local work and signed-event interop with the desktop app", - lifecycle: "retain until a shared local-events SDK boundary replaces direct CLI access", + lifecycle: "retain until a shared runtime-store SDK boundary replaces direct CLI access", }, DirectRrRsDependency { section: "dependencies", @@ -976,8 +976,8 @@ mod tests { DirectRrRsDependency { section: "dependencies", name: "radroots_sql_core", - owner: "derived-projection-and-local-events", - reason: "SQLite executor for derived projection and shared local-events storage", + owner: "derived-projection-and-runtime-store", + reason: "SQLite executor for derived projection and shared runtime-store storage", lifecycle: "transitional until those storage surfaces move behind SDK or shared runtime APIs", }, DirectRrRsDependency { diff --git a/src/runtime/signer.rs b/src/runtime/signer.rs @@ -9,7 +9,7 @@ use crate::view::runtime::{ IdentityPublicView, LocalSignerStatusView, MycStatusView, SignerBindingStatusView, SignerStatusView, SignerWriteKindReadinessView, }; -use radroots_events::kinds::{ +use radroots_event::kinds::{ KIND_FARM, KIND_LISTING, KIND_ORDER_CANCELLATION, KIND_ORDER_DECISION, KIND_ORDER_REQUEST, KIND_ORDER_REVISION_DECISION, KIND_ORDER_REVISION_PROPOSAL, KIND_PROFILE, }; diff --git a/src/runtime/sync.rs b/src/runtime/sync.rs @@ -1,7 +1,7 @@ use std::thread; use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use radroots_events::kinds::{ +use radroots_event::kinds::{ KIND_FARM, KIND_LIST_SET_APP_CURATION, KIND_LIST_SET_BOOKMARK, KIND_LIST_SET_CALENDAR, KIND_LIST_SET_CURATION, KIND_LIST_SET_EMOJI, KIND_LIST_SET_FOLLOW, KIND_LIST_SET_GENERIC, KIND_LIST_SET_INTEREST, KIND_LIST_SET_KIND_MUTE, KIND_LIST_SET_MEDIA_STARTER_PACK, @@ -1754,18 +1754,18 @@ fn relative_age(age_seconds: u64) -> String { mod tests { use std::path::{Path, PathBuf}; - use radroots_events::farm::{RadrootsFarm, RadrootsFarmRef}; - use radroots_events::ids::RadrootsEventId; - use radroots_events::kinds::{KIND_FARM, KIND_LIST_SET_GENERIC, KIND_LISTING, KIND_POST}; - use radroots_events::list::RadrootsListEntry; - use radroots_events::list_set::RadrootsListSet; - use radroots_events::plot::RadrootsPlot; - use radroots_events::profile::{RadrootsProfile, RadrootsProfileType}; - use radroots_events_codec::farm::encode as farm_encode; - use radroots_events_codec::list_set::encode as list_set_encode; - use radroots_events_codec::plot::encode as plot_encode; - use radroots_events_codec::profile::encode as profile_encode; - use radroots_events_codec::wire::WireEventParts; + use radroots_event::farm::{RadrootsFarm, RadrootsFarmRef}; + use radroots_event::ids::RadrootsEventId; + use radroots_event::kinds::{KIND_FARM, KIND_LIST_SET_GENERIC, KIND_LISTING, KIND_POST}; + use radroots_event::list::RadrootsListEntry; + use radroots_event::list_set::RadrootsListSet; + use radroots_event::plot::RadrootsPlot; + use radroots_event::profile::{RadrootsProfile, RadrootsProfileType}; + use radroots_event_codec::farm::encode as farm_encode; + use radroots_event_codec::list_set::encode as list_set_encode; + use radroots_event_codec::plot::encode as plot_encode; + use radroots_event_codec::profile::encode as profile_encode; + use radroots_event_codec::wire::WireEventParts; use radroots_identity::RadrootsIdentity; use radroots_nostr::prelude::{ RadrootsNostrEvent, RadrootsNostrFilter, RadrootsNostrTimestamp, radroots_nostr_build_event, diff --git a/src/runtime/transport.rs b/src/runtime/transport.rs @@ -714,7 +714,7 @@ fn string_array_input(input: &OperationData, key: &str) -> Vec<String> { #[cfg(test)] mod tests { use super::*; - use radroots_events::ids::RadrootsEventId; + use radroots_event::ids::RadrootsEventId; use radroots_sdk::{ PushOutboxEventReceipt, PushOutboxTargetReceipt, PushOutboxTransportOutcomeKind, }; diff --git a/src/runtime/validation_receipt.rs b/src/runtime/validation_receipt.rs @@ -716,7 +716,7 @@ fn validation_receipt_resource(id: &str) -> ValidationReceiptResourceView { } } -fn event_view(event: radroots_events::RadrootsEventEnvelope) -> ValidationReceiptEventView { +fn event_view(event: radroots_event::RadrootsEventEnvelope) -> ValidationReceiptEventView { ValidationReceiptEventView { id: event.id, author: event.author, @@ -1263,7 +1263,7 @@ fn sdk_relay_failures( } fn summary_view( - event: &radroots_events::RadrootsEventEnvelope, + event: &radroots_event::RadrootsEventEnvelope, receipt: &RadrootsTradeValidationReceipt, tags: &TradeValidationReceiptTags, proof_verification: &ValidationReceiptProofVerificationView, diff --git a/src/view/runtime.rs b/src/view/runtime.rs @@ -1,11 +1,11 @@ use std::process::ExitCode; -use radroots_events::farm::RadrootsFarm; -use radroots_events::ids::RadrootsListingAddress; -use radroots_events::kinds::KIND_LISTING; -use radroots_events::listing::RadrootsListingPublicLocation; -use radroots_events::order::RadrootsOrderEconomics; -use radroots_events::profile::RadrootsProfile; +use radroots_event::farm::RadrootsFarm; +use radroots_event::ids::RadrootsListingAddress; +use radroots_event::kinds::KIND_LISTING; +use radroots_event::listing::RadrootsListingPublicLocation; +use radroots_event::order::RadrootsOrderEconomics; +use radroots_event::profile::RadrootsProfile; use radroots_nostr_accounts::prelude::RadrootsNostrAccountRecord; use serde::Serialize; @@ -1611,7 +1611,7 @@ pub struct OrderAppRecordListView { pub next_before_change_seq: Option<i64>, #[serde(skip_serializing_if = "Option::is_none")] pub next_before_seq: Option<i64>, - pub local_events_db: String, + pub runtime_store_db: String, pub records: Vec<OrderAppRecordSummaryView>, #[serde(default, skip_serializing_if = "Vec::is_empty")] pub actions: Vec<String>, @@ -2587,7 +2587,7 @@ pub struct ListingAppRecordListView { pub next_before_change_seq: Option<i64>, #[serde(skip_serializing_if = "Option::is_none")] pub next_before_seq: Option<i64>, - pub local_events_db: String, + pub runtime_store_db: String, pub records: Vec<ListingAppRecordSummaryView>, #[serde(default, skip_serializing_if = "Vec::is_empty")] pub actions: Vec<String>, diff --git a/tests/support/mod.rs b/tests/support/mod.rs @@ -4,16 +4,16 @@ use std::process::{Command, Output}; use std::sync::Mutex; use assert_cmd::prelude::*; -use radroots_events::RadrootsEventEnvelope; -use radroots_events::ids::RadrootsListingAddress; -use radroots_events::kinds::{KIND_FARM, KIND_LISTING}; +use radroots_event::RadrootsEventEnvelope; +use radroots_event::ids::RadrootsListingAddress; +use radroots_event::kinds::{KIND_FARM, KIND_LISTING}; use radroots_identity::{RadrootsIdentity, RadrootsIdentityPublic}; -use radroots_local_events::{ - LocalEventRecord, LocalEventRecordInput, LocalEventsStore, LocalRecordFamily, - LocalRecordStatus, PublishOutboxStatus, SourceRuntime, -}; use radroots_protected_store::RadrootsProtectedFileSecretVault; use radroots_replica_sync::{RadrootsReplicaIngestOutcome, radroots_replica_ingest_event}; +use radroots_runtime_store::{ + PublishOutboxStatus, RuntimeStore, RuntimeStoreRecord, RuntimeStoreRecordFamily, + RuntimeStoreRecordInput, RuntimeStoreRecordStatus, SourceRuntime, +}; use radroots_secret_vault::RadrootsSecretVault; use radroots_sql_core::{SqlExecutor, SqliteExecutor}; use serde_json::{Value, json}; @@ -129,20 +129,20 @@ impl RadrootsCliSandbox { .join("data/apps/cli/replica/replica.sqlite") } - pub fn local_events_db_path(&self) -> PathBuf { + pub fn runtime_store_db_path(&self) -> PathBuf { self.root .path() - .join("data/shared/local_events/local_events.sqlite") + .join("data/shared/runtime_store/runtime_store.sqlite") } - pub fn local_event_records(&self) -> Vec<LocalEventRecord> { - let path = self.local_events_db_path(); + pub fn runtime_store_records(&self) -> Vec<RuntimeStoreRecord> { + let path = self.runtime_store_db_path(); if !path.exists() { return Vec::new(); } - let executor = SqliteExecutor::open(path).expect("open local events db"); - let store = LocalEventsStore::new(executor); - store.migrate_up().expect("migrate local events db"); + let executor = SqliteExecutor::open(path).expect("open runtime store db"); + let store = RuntimeStore::new(executor); + store.migrate_up().expect("migrate runtime store db"); store .list_records_after_seq(0, 200) .expect("list local event records") @@ -174,8 +174,8 @@ const _: () = { let _ = RadrootsCliSandbox::write_nostr_transport_profile as fn(&RadrootsCliSandbox, &[&str]) -> PathBuf; let _ = RadrootsCliSandbox::replica_db_path as fn(&RadrootsCliSandbox) -> PathBuf; - let _ = - RadrootsCliSandbox::local_event_records as fn(&RadrootsCliSandbox) -> Vec<LocalEventRecord>; + let _ = RadrootsCliSandbox::runtime_store_records + as fn(&RadrootsCliSandbox) -> Vec<RuntimeStoreRecord>; #[cfg(unix)] let _ = RadrootsCliSandbox::write_fake_myc as fn(&RadrootsCliSandbox, &str, &str) -> PathBuf; let _ = assert_hex_len as fn(&Value, usize); @@ -429,17 +429,17 @@ fn seed_orderable_listing_signed_event( event: &RadrootsEventEnvelope, listing_addr: &str, ) { - let database_path = sandbox.local_events_db_path(); - fs::create_dir_all(database_path.parent().expect("local events parent")) - .expect("local events parent"); - let executor = SqliteExecutor::open(database_path).expect("open local events"); - let store = LocalEventsStore::new(executor); - store.migrate_up().expect("migrate local events"); + let database_path = sandbox.runtime_store_db_path(); + fs::create_dir_all(database_path.parent().expect("runtime store parent")) + .expect("runtime store parent"); + let executor = SqliteExecutor::open(database_path).expect("open runtime store"); + let store = RuntimeStore::new(executor); + store.migrate_up().expect("migrate runtime store"); store - .append_record(&LocalEventRecordInput { + .append_record(&RuntimeStoreRecordInput { record_id: format!("test:signed_listing:{}", event.id), - family: LocalRecordFamily::SignedEvent, - status: LocalRecordStatus::Published, + family: RuntimeStoreRecordFamily::SignedEvent, + status: RuntimeStoreRecordStatus::Published, source_runtime: SourceRuntime::Cli, created_at_ms: 1_779_000_001_000, inserted_at_ms: 1_779_000_001_000, @@ -457,6 +457,8 @@ fn seed_orderable_listing_signed_event( event_sig: Some(event.sig.clone()), raw_event_json: Some(json!(event)), outbox_status: PublishOutboxStatus::Acknowledged, + relay_set_fingerprint: None, + relay_delivery_json: None, }) .expect("append listing signed event record"); } diff --git a/tests/target_cli.rs b/tests/target_cli.rs @@ -13,19 +13,15 @@ use std::time::{Duration, Instant}; use nostr::nips::nip44::{self, Version}; use nostr::{EventBuilder, Keys, Kind, PublicKey, SecretKey, Tag}; -use radroots_events::RadrootsEventPtr; -use radroots_events::draft::RadrootsEventDraft; -use radroots_events::ids::{ +use radroots_event::RadrootsEventPtr; +use radroots_event::draft::RadrootsEventDraft; +use radroots_event::ids::{ RadrootsInventoryBinId, RadrootsListingAddress, RadrootsOrderId, RadrootsPublicKey, }; -use radroots_events::kinds::{KIND_LISTING, KIND_ORDER_REQUEST, KIND_POST}; -use radroots_events::order::{RadrootsOrderEconomics, RadrootsOrderItem, RadrootsOrderRequest}; -use radroots_events_codec::order::order_request_event_build; +use radroots_event::kinds::{KIND_LISTING, KIND_ORDER_REQUEST, KIND_POST}; +use radroots_event::order::{RadrootsOrderEconomics, RadrootsOrderItem, RadrootsOrderRequest}; +use radroots_event_codec::order::order_request_event_build; use radroots_identity::RadrootsIdentity; -use radroots_local_events::{ - BUYER_ORDER_REQUEST_LOCAL_WORK_RECORD_KIND, LocalEventRecordInput, LocalEventsStore, - LocalRecordFamily, LocalRecordStatus, PublishOutboxStatus, SourceRuntime, -}; use radroots_nostr::prelude::{ RadrootsNostrEvent, RadrootsNostrKeys, radroots_nostr_build_event, radroots_nostr_sign_frozen_draft, @@ -41,6 +37,10 @@ use radroots_outbox::{ use radroots_replica_db::{farm, migrations}; use radroots_replica_db_schema::farm::IFarmFields; use radroots_replica_sync::radroots_replica_pending_publish_batch; +use radroots_runtime_store::{ + BUYER_ORDER_REQUEST_LOCAL_WORK_RECORD_KIND, PublishOutboxStatus, RuntimeStore, + RuntimeStoreRecordFamily, RuntimeStoreRecordInput, RuntimeStoreRecordStatus, SourceRuntime, +}; use radroots_sql_core::SqliteExecutor; use radroots_transport::{ RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI, RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE, @@ -776,10 +776,10 @@ fn seed_app_farm_record( farm_d_tag: &str, ) { append_app_local_record( - LocalEventRecordInput { + RuntimeStoreRecordInput { record_id: format!("app:local_work:farm:{farm_d_tag}:test"), - family: LocalRecordFamily::LocalWork, - status: LocalRecordStatus::LocalSaved, + family: RuntimeStoreRecordFamily::LocalWork, + status: RuntimeStoreRecordStatus::LocalSaved, source_runtime: SourceRuntime::App, created_at_ms: 1_779_000_001_000, inserted_at_ms: 1_779_000_001_000, @@ -831,6 +831,8 @@ fn seed_app_farm_record( event_sig: None, raw_event_json: None, outbox_status: PublishOutboxStatus::None, + relay_set_fingerprint: None, + relay_delivery_json: None, }, sandbox, ); @@ -992,10 +994,10 @@ fn seed_app_listing_record_identity_variant( payload["exportability"] = exportability; } append_app_local_record( - LocalEventRecordInput { + RuntimeStoreRecordInput { record_id: record_id.clone(), - family: LocalRecordFamily::LocalWork, - status: LocalRecordStatus::LocalSaved, + family: RuntimeStoreRecordFamily::LocalWork, + status: RuntimeStoreRecordStatus::LocalSaved, source_runtime: SourceRuntime::App, created_at_ms: 1_779_000_002_000, inserted_at_ms: 1_779_000_002_000, @@ -1016,19 +1018,21 @@ fn seed_app_listing_record_identity_variant( event_sig: None, raw_event_json: None, outbox_status: PublishOutboxStatus::None, + relay_set_fingerprint: None, + relay_delivery_json: None, }, sandbox, ); record_id } -fn append_app_local_record(input: LocalEventRecordInput, sandbox: &RadrootsCliSandbox) { - let database_path = sandbox.local_events_db_path(); - fs::create_dir_all(database_path.parent().expect("local events parent")) - .expect("local events parent"); - let executor = SqliteExecutor::open(database_path).expect("open local events"); - let store = LocalEventsStore::new(executor); - store.migrate_up().expect("migrate local events"); +fn append_app_local_record(input: RuntimeStoreRecordInput, sandbox: &RadrootsCliSandbox) { + let database_path = sandbox.runtime_store_db_path(); + fs::create_dir_all(database_path.parent().expect("runtime store parent")) + .expect("runtime store parent"); + let executor = SqliteExecutor::open(database_path).expect("open runtime store"); + let store = RuntimeStore::new(executor); + store.migrate_up().expect("migrate runtime store"); store .append_record(&input) .expect("append app local event record"); @@ -1202,10 +1206,10 @@ fn seed_app_order_record_variant_with_record_id( }, }); append_app_local_record( - LocalEventRecordInput { + RuntimeStoreRecordInput { record_id: record_id.clone(), - family: LocalRecordFamily::LocalWork, - status: LocalRecordStatus::LocalSaved, + family: RuntimeStoreRecordFamily::LocalWork, + status: RuntimeStoreRecordStatus::LocalSaved, source_runtime: SourceRuntime::App, created_at_ms: 1_779_000_010_000, inserted_at_ms: 1_779_000_010_000, @@ -1223,6 +1227,8 @@ fn seed_app_order_record_variant_with_record_id( event_sig: None, raw_event_json: None, outbox_status: PublishOutboxStatus::None, + relay_set_fingerprint: None, + relay_delivery_json: None, }, sandbox, ); @@ -1319,10 +1325,10 @@ fn append_app_signed_order_request_record( .collect::<Vec<_>>(); let record_id = format!("app:signed_event:{event_id}"); append_app_local_record( - LocalEventRecordInput { + RuntimeStoreRecordInput { record_id: record_id.clone(), - family: LocalRecordFamily::SignedEvent, - status: LocalRecordStatus::Published, + family: RuntimeStoreRecordFamily::SignedEvent, + status: RuntimeStoreRecordStatus::Published, source_runtime: SourceRuntime::App, created_at_ms: i64::try_from(event.created_at.as_secs()).expect("event created_at") * 1_000, @@ -1351,6 +1357,8 @@ fn append_app_signed_order_request_record( "sig": event.sig.to_string(), })), outbox_status: PublishOutboxStatus::Acknowledged, + relay_set_fingerprint: None, + relay_delivery_json: None, }, sandbox, ); @@ -4755,7 +4763,7 @@ fn offline_listing_publish_enqueues_sdk_outbox_without_direct_publish_push() { let listing_file = create_listing_draft(&sandbox, "offline-sdk-enqueue"); make_listing_publishable(&listing_file, farm_d_tag); let relay = "ws://127.0.0.1:9"; - let local_event_records_before_publish = sandbox.local_event_records().len(); + let runtime_store_records_before_publish = sandbox.runtime_store_records().len(); configure_nostr_transport(&sandbox, relay); let publish = sandbox.json_success(&[ @@ -4791,8 +4799,8 @@ fn offline_listing_publish_enqueues_sdk_outbox_without_direct_publish_push() { .exists() ); assert_eq!( - sandbox.local_event_records().len(), - local_event_records_before_publish + sandbox.runtime_store_records().len(), + runtime_store_records_before_publish ); } @@ -5795,7 +5803,7 @@ fn seller_dry_runs_do_not_write_shared_local_work_records() { "--delivery-method", "pickup", ]); - assert!(sandbox.local_event_records().is_empty()); + assert!(sandbox.runtime_store_records().is_empty()); let listing_path = sandbox.root().join("dry-run-local-work.toml"); let listing_path_arg = listing_path.to_string_lossy(); @@ -5832,7 +5840,7 @@ fn seller_dry_runs_do_not_write_shared_local_work_records() { "--available", "10", ]); - assert!(sandbox.local_event_records().is_empty()); + assert!(sandbox.runtime_store_records().is_empty()); } #[test] @@ -5867,7 +5875,7 @@ fn seller_local_writes_append_shared_local_work_records() { .expect("seller pubkey"); let listing_file = create_listing_draft(&sandbox, "shared-local-eggs"); - let records = sandbox.local_event_records(); + let records = sandbox.runtime_store_records(); assert_eq!(records.len(), 2); let farm_record = records @@ -5880,8 +5888,8 @@ fn seller_local_writes_append_shared_local_work_records() { == Some("farm_config_v1") }) .expect("farm local work record"); - assert_eq!(farm_record.family, LocalRecordFamily::LocalWork); - assert_eq!(farm_record.status, LocalRecordStatus::LocalSaved); + assert_eq!(farm_record.family, RuntimeStoreRecordFamily::LocalWork); + assert_eq!(farm_record.status, RuntimeStoreRecordStatus::LocalSaved); assert_eq!(farm_record.source_runtime, SourceRuntime::Cli); assert_eq!(farm_record.outbox_status, PublishOutboxStatus::None); assert_eq!(farm_record.owner_account_id.as_deref(), Some(account_id)); @@ -5905,8 +5913,8 @@ fn seller_local_writes_append_shared_local_work_records() { == Some("listing_draft_v1") }) .expect("listing local work record"); - assert_eq!(listing_record.family, LocalRecordFamily::LocalWork); - assert_eq!(listing_record.status, LocalRecordStatus::LocalSaved); + assert_eq!(listing_record.family, RuntimeStoreRecordFamily::LocalWork); + assert_eq!(listing_record.status, RuntimeStoreRecordStatus::LocalSaved); assert_eq!(listing_record.source_runtime, SourceRuntime::Cli); assert_eq!(listing_record.outbox_status, PublishOutboxStatus::None); assert_eq!(listing_record.owner_account_id.as_deref(), Some(account_id)); @@ -5957,7 +5965,7 @@ fn seller_local_writes_append_shared_local_work_records() { farm_d_tag, ]); - let updated_records = sandbox.local_event_records(); + let updated_records = sandbox.runtime_store_records(); assert_eq!(updated_records.len(), 4); let latest_farm_payload = updated_records .iter() @@ -6552,7 +6560,7 @@ fn order_app_records_list_export_get_and_submit_supported_app_order() { ); assert_eq!( orders["result"]["trades"][0]["file"], - format!("shared-local-events/{record_id}") + format!("shared-runtime-store/{record_id}") ); assert_no_removed_command_reference(&orders, &["trade", "list"]); assert_no_daemon_runtime_reference(&orders, &["trade", "list"]); @@ -7206,7 +7214,7 @@ fn farm_publish_uses_sdk_outbox_without_legacy_signed_event_records() { "pickup", ]); let relay_url = "ws://127.0.0.1:9"; - let local_event_records_before_publish = sandbox.local_event_records().len(); + let runtime_store_records_before_publish = sandbox.runtime_store_records().len(); configure_nostr_transport(&sandbox, relay_url); let (output, publish) = sandbox.json_output(&[ @@ -7241,17 +7249,17 @@ fn farm_publish_uses_sdk_outbox_without_legacy_signed_event_records() { 64 ); - let records = sandbox.local_event_records(); - assert_eq!(records.len(), local_event_records_before_publish); + let records = sandbox.runtime_store_records(); + assert_eq!(records.len(), runtime_store_records_before_publish); let signed_records = records .iter() - .filter(|record| record.family == LocalRecordFamily::SignedEvent) + .filter(|record| record.family == RuntimeStoreRecordFamily::SignedEvent) .collect::<Vec<_>>(); assert!(signed_records.is_empty()); } #[test] -fn listing_publish_failure_uses_sdk_outbox_without_legacy_local_event_record() { +fn listing_publish_failure_uses_sdk_outbox_without_legacy_runtime_store_record() { let sandbox = RadrootsCliSandbox::new(); sandbox.json_success(&["--format", "json", "account", "create"]); let farm = sandbox.json_success(&[ @@ -7278,7 +7286,7 @@ fn listing_publish_failure_uses_sdk_outbox_without_legacy_local_event_record() { let listing_file = create_listing_draft(&sandbox, "failed-outbox-eggs"); make_listing_publishable(&listing_file, farm_d_tag); let relay_url = "ws://127.0.0.1:9"; - let local_event_records_before_publish = sandbox.local_event_records().len(); + let runtime_store_records_before_publish = sandbox.runtime_store_records().len(); configure_nostr_transport(&sandbox, relay_url); let (output, publish) = sandbox.json_output(&[ @@ -7319,8 +7327,8 @@ fn listing_publish_failure_uses_sdk_outbox_without_legacy_local_event_record() { 64 ); assert_eq!( - sandbox.local_event_records().len(), - local_event_records_before_publish + sandbox.runtime_store_records().len(), + runtime_store_records_before_publish ); }