app

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

interop.rs (342726B)


      1 use std::{fs, path::Path};
      2 
      3 use radroots_app_view::{
      4     FarmId, FarmOrderMethod, FarmReadiness, FarmSetupDraft, FarmSetupProjection, FarmSummary,
      5     FulfillmentWindowId, OrderId, PickupLocationId, ProductId, ProductStatus,
      6     TradeProvenanceProjection, TradeRevisionStatus, TradeValidationReceiptProofSystem,
      7     TradeValidationReceiptResult, TradeValidationReceiptType, TradeWorkflowProjection,
      8     TradeWorkflowSource, order_status_from_active_order_projection,
      9 };
     10 use radroots_events::{
     11     RadrootsNostrEvent,
     12     ids::{RadrootsEventId, RadrootsOrderId, RadrootsPublicKey},
     13     kinds::{
     14         KIND_FARM as RADROOTS_KIND_FARM, KIND_LISTING as RADROOTS_KIND_LISTING,
     15         KIND_LISTING_DRAFT as RADROOTS_KIND_LISTING_DRAFT,
     16         KIND_ORDER_CANCELLATION as RADROOTS_KIND_ORDER_CANCELLATION,
     17         KIND_ORDER_DECISION as RADROOTS_KIND_ORDER_DECISION,
     18         KIND_ORDER_REQUEST as RADROOTS_KIND_ORDER_REQUEST,
     19         KIND_ORDER_REVISION_DECISION as RADROOTS_KIND_ORDER_REVISION_DECISION,
     20         KIND_ORDER_REVISION_PROPOSAL as RADROOTS_KIND_ORDER_REVISION_PROPOSAL,
     21         KIND_TRADE_VALIDATION_RECEIPT,
     22     },
     23     order::{
     24         RadrootsOrderEconomics, RadrootsOrderItem, RadrootsOrderRequest,
     25         RadrootsOrderRevisionOutcome,
     26     },
     27 };
     28 use radroots_events_codec::order::{
     29     order_cancellation_from_event, order_decision_from_event, order_event_context_from_tags,
     30     order_request_from_event, order_revision_decision_from_event,
     31     order_revision_proposal_from_event,
     32 };
     33 use radroots_local_events::{
     34     LocalEventRecord, LocalEventsStore, LocalRecordFamily, LocalRecordStatus, PublishOutboxStatus,
     35     RelayDeliveryEvidence, RelayDeliveryState, SourceRuntime,
     36 };
     37 use radroots_sql_core::{SqlExecutor, SqliteExecutor};
     38 use radroots_trade::order::{
     39     RadrootsOrderCancellationRecord, RadrootsOrderDecisionRecord, RadrootsOrderProjection,
     40     RadrootsOrderReductionInputs, RadrootsOrderRequestRecord, RadrootsOrderRevisionDecisionRecord,
     41     RadrootsOrderRevisionProposalRecord, reduce_order_events,
     42 };
     43 use radroots_trade::validation_receipt::{
     44     RadrootsTradeValidationReceipt, RadrootsValidationReceiptTags, validation_receipt_from_event,
     45 };
     46 use rusqlite::{Connection, OptionalExtension, params};
     47 use serde_json::Value;
     48 use uuid::Uuid;
     49 
     50 use crate::repo::farm_setup::AppFarmSetupRepository;
     51 use crate::{AppSqliteError, AppSqliteStore};
     52 
     53 const LOCAL_EVENTS_BATCH_LIMIT: u32 = 500;
     54 const APP_LOCAL_INTEROP_CURSOR_ID: &str = "radroots_app_sqlite_projection_v1";
     55 const KIND_FARM: i64 = RADROOTS_KIND_FARM as i64;
     56 const KIND_LISTING: i64 = RADROOTS_KIND_LISTING as i64;
     57 const KIND_LISTING_DRAFT: i64 = RADROOTS_KIND_LISTING_DRAFT as i64;
     58 const KIND_ORDER_REQUEST: i64 = RADROOTS_KIND_ORDER_REQUEST as i64;
     59 const KIND_ORDER_DECISION: i64 = RADROOTS_KIND_ORDER_DECISION as i64;
     60 const KIND_ORDER_REVISION: i64 = RADROOTS_KIND_ORDER_REVISION_PROPOSAL as i64;
     61 const KIND_ORDER_REVISION_DECISION: i64 = RADROOTS_KIND_ORDER_REVISION_DECISION as i64;
     62 const KIND_ORDER_CANCEL: i64 = RADROOTS_KIND_ORDER_CANCELLATION as i64;
     63 const KIND_VALIDATION_RECEIPT: i64 = KIND_TRADE_VALIDATION_RECEIPT as i64;
     64 const ACTIVE_ORDER_EVENT_KINDS: [i64; 5] = [
     65     KIND_ORDER_REQUEST,
     66     KIND_ORDER_DECISION,
     67     KIND_ORDER_REVISION,
     68     KIND_ORDER_REVISION_DECISION,
     69     KIND_ORDER_CANCEL,
     70 ];
     71 
     72 #[derive(Clone, Debug, Default, Eq, PartialEq)]
     73 pub struct AppLocalInteropImportReport {
     74     pub scanned_records: u32,
     75     pub imported_records: u32,
     76     pub skipped_records: u32,
     77     pub self_observed_records: u32,
     78     pub last_change_seq: Option<i64>,
     79 }
     80 
     81 #[derive(Clone, Debug, Eq, PartialEq)]
     82 pub struct StoredLocalInteropRecord {
     83     pub record_id: String,
     84     pub local_seq: i64,
     85     pub record_family: String,
     86     pub local_status: String,
     87     pub source_runtime: String,
     88     pub owner_account_id: Option<String>,
     89     pub owner_pubkey: Option<String>,
     90     pub farm_key: Option<String>,
     91     pub listing_addr: Option<String>,
     92     pub projected_kind: String,
     93     pub projected_id: Option<String>,
     94     pub event_id: Option<String>,
     95     pub event_kind: Option<i64>,
     96     pub outbox_status: String,
     97     pub relay_delivery_json: Option<String>,
     98 }
     99 
    100 pub struct AppLocalInteropRepository<'a> {
    101     connection: &'a Connection,
    102 }
    103 
    104 impl<'a> AppLocalInteropRepository<'a> {
    105     pub const fn new(connection: &'a Connection) -> Self {
    106         Self { connection }
    107     }
    108 
    109     pub fn import_from_path(
    110         &self,
    111         shared_database_path: &Path,
    112     ) -> Result<AppLocalInteropImportReport, AppSqliteError> {
    113         if let Some(parent) = shared_database_path.parent() {
    114             fs::create_dir_all(parent).map_err(|source| AppSqliteError::CreateParentDirectory {
    115                 path: parent.to_path_buf(),
    116                 source,
    117             })?;
    118         }
    119         let executor = SqliteExecutor::open(shared_database_path).map_err(|source| {
    120             AppSqliteError::LocalEventsSql {
    121                 operation: "open shared local events database",
    122                 source,
    123             }
    124         })?;
    125         let store = LocalEventsStore::new(executor);
    126         store
    127             .migrate_up()
    128             .map_err(|source| AppSqliteError::LocalEventsSql {
    129                 operation: "migrate shared local events database",
    130                 source,
    131             })?;
    132         self.import_from_store(&store)
    133     }
    134 
    135     pub fn import_from_store<E>(
    136         &self,
    137         store: &LocalEventsStore<E>,
    138     ) -> Result<AppLocalInteropImportReport, AppSqliteError>
    139     where
    140         E: SqlExecutor,
    141     {
    142         let mut report = AppLocalInteropImportReport::default();
    143         let mut after_change_seq = self.last_imported_change_seq()?;
    144         loop {
    145             let records = store
    146                 .list_records_changed_after(after_change_seq, LOCAL_EVENTS_BATCH_LIMIT)
    147                 .map_err(|source| AppSqliteError::LocalEvents {
    148                     operation: "list changed shared local event records",
    149                     source,
    150                 })?;
    151             let batch_len = records.len();
    152             for record in records {
    153                 after_change_seq = record.change_seq;
    154                 report.scanned_records += 1;
    155                 report.last_change_seq = Some(record.change_seq);
    156                 match self.import_record(&record)? {
    157                     ImportOutcome::Imported => report.imported_records += 1,
    158                     ImportOutcome::Skipped => report.skipped_records += 1,
    159                 }
    160             }
    161             if batch_len < LOCAL_EVENTS_BATCH_LIMIT as usize {
    162                 break;
    163             }
    164         }
    165         if let Some(last_change_seq) = report.last_change_seq {
    166             self.advance_import_cursor(last_change_seq)?;
    167         }
    168         Ok(report)
    169     }
    170 
    171     pub fn import_records(
    172         &self,
    173         records: &[LocalEventRecord],
    174     ) -> Result<AppLocalInteropImportReport, AppSqliteError> {
    175         let mut report = AppLocalInteropImportReport::default();
    176         for record in records {
    177             report.scanned_records += 1;
    178             report.last_change_seq = Some(record.change_seq);
    179             match self.import_record(record)? {
    180                 ImportOutcome::Imported => report.imported_records += 1,
    181                 ImportOutcome::Skipped => report.skipped_records += 1,
    182             }
    183         }
    184         Ok(report)
    185     }
    186 
    187     pub fn load_records(&self) -> Result<Vec<StoredLocalInteropRecord>, AppSqliteError> {
    188         let mut statement = self
    189             .connection
    190             .prepare(
    191                 "SELECT
    192                     record_id,
    193                     local_seq,
    194                     record_family,
    195                     local_status,
    196                     source_runtime,
    197                     owner_account_id,
    198                     owner_pubkey,
    199                     farm_key,
    200                     listing_addr,
    201                     projected_kind,
    202                     projected_id,
    203                     event_id,
    204                     event_kind,
    205                     outbox_status,
    206                     relay_delivery_json
    207                  FROM local_interop_imports
    208                  ORDER BY local_seq ASC, record_id ASC",
    209             )
    210             .map_err(|source| AppSqliteError::Query {
    211                 operation: "prepare local interop import query",
    212                 source,
    213             })?;
    214         let rows = statement
    215             .query_map([], |row| {
    216                 Ok(StoredLocalInteropRecord {
    217                     record_id: row.get(0)?,
    218                     local_seq: row.get(1)?,
    219                     record_family: row.get(2)?,
    220                     local_status: row.get(3)?,
    221                     source_runtime: row.get(4)?,
    222                     owner_account_id: row.get(5)?,
    223                     owner_pubkey: row.get(6)?,
    224                     farm_key: row.get(7)?,
    225                     listing_addr: row.get(8)?,
    226                     projected_kind: row.get(9)?,
    227                     projected_id: row.get(10)?,
    228                     event_id: row.get(11)?,
    229                     event_kind: row.get(12)?,
    230                     outbox_status: row.get(13)?,
    231                     relay_delivery_json: row.get(14)?,
    232                 })
    233             })
    234             .map_err(|source| AppSqliteError::Query {
    235                 operation: "query local interop imports",
    236                 source,
    237             })?;
    238         rows.map(|row| {
    239             row.map_err(|source| AppSqliteError::Query {
    240                 operation: "read local interop import row",
    241                 source,
    242             })
    243         })
    244         .collect()
    245     }
    246 
    247     pub fn load_signed_events_by_kind(
    248         &self,
    249         event_kind: i64,
    250     ) -> Result<Vec<RadrootsNostrEvent>, AppSqliteError> {
    251         let mut statement = self
    252             .connection
    253             .prepare(
    254                 "SELECT
    255                     event_id,
    256                     event_kind,
    257                     local_status,
    258                     outbox_status,
    259                     relay_delivery_json,
    260                     event_pubkey,
    261                     event_created_at,
    262                     event_tags_json,
    263                     event_content,
    264                     event_sig
    265                  FROM local_interop_imports
    266                  WHERE record_family = 'signed_event'
    267                     AND local_status = 'published'
    268                     AND event_kind = ?1
    269                  ORDER BY local_seq ASC, record_id ASC",
    270             )
    271             .map_err(|source| AppSqliteError::Query {
    272                 operation: "prepare local interop signed event evidence query",
    273                 source,
    274             })?;
    275         let rows = statement
    276             .query_map(params![event_kind], |row| {
    277                 Ok(StoredLocalInteropSignedEventEvidence {
    278                     event_id: row.get(0)?,
    279                     event_kind: row.get(1)?,
    280                     local_status: row.get(2)?,
    281                     outbox_status: row.get(3)?,
    282                     relay_delivery_json: row.get(4)?,
    283                     event_pubkey: row.get(5)?,
    284                     event_created_at: row.get(6)?,
    285                     event_tags_json: row.get(7)?,
    286                     event_content: row.get(8)?,
    287                     event_sig: row.get(9)?,
    288                 })
    289             })
    290             .map_err(|source| AppSqliteError::Query {
    291                 operation: "query local interop signed event evidence",
    292                 source,
    293             })?;
    294         let mut events = Vec::new();
    295         for row in rows {
    296             let evidence = row.map_err(|source| AppSqliteError::Query {
    297                 operation: "read local interop signed event evidence row",
    298                 source,
    299             })?;
    300             if !signed_event_local_interop_evidence_is_usable(&evidence) {
    301                 continue;
    302             }
    303             if let Some(event) = signed_event_from_local_interop_evidence(&evidence)? {
    304                 events.push(event);
    305             }
    306         }
    307         Ok(events)
    308     }
    309 
    310     fn load_signed_event_by_event_id(
    311         &self,
    312         event_id: &str,
    313     ) -> Result<Option<RadrootsNostrEvent>, AppSqliteError> {
    314         let mut statement = self
    315             .connection
    316             .prepare(
    317                 "SELECT
    318                     event_id,
    319                     event_kind,
    320                     local_status,
    321                     outbox_status,
    322                     relay_delivery_json,
    323                     event_pubkey,
    324                     event_created_at,
    325                     event_tags_json,
    326                     event_content,
    327                     event_sig
    328                  FROM local_interop_imports
    329                  WHERE record_family = 'signed_event'
    330                     AND event_id = ?1
    331                  ORDER BY local_seq DESC, record_id DESC",
    332             )
    333             .map_err(|source| AppSqliteError::Query {
    334                 operation: "prepare local interop signed event id evidence query",
    335                 source,
    336             })?;
    337         let rows = statement
    338             .query_map(params![event_id], |row| {
    339                 Ok(StoredLocalInteropSignedEventEvidence {
    340                     event_id: row.get(0)?,
    341                     event_kind: row.get(1)?,
    342                     local_status: row.get(2)?,
    343                     outbox_status: row.get(3)?,
    344                     relay_delivery_json: row.get(4)?,
    345                     event_pubkey: row.get(5)?,
    346                     event_created_at: row.get(6)?,
    347                     event_tags_json: row.get(7)?,
    348                     event_content: row.get(8)?,
    349                     event_sig: row.get(9)?,
    350                 })
    351             })
    352             .map_err(|source| AppSqliteError::Query {
    353                 operation: "query local interop signed event id evidence",
    354                 source,
    355             })?;
    356 
    357         for row in rows {
    358             let evidence = row.map_err(|source| AppSqliteError::Query {
    359                 operation: "read local interop signed event id evidence row",
    360                 source,
    361             })?;
    362             if !signed_event_local_interop_evidence_is_usable(&evidence) {
    363                 continue;
    364             }
    365             if let Some(event) = signed_event_from_local_interop_evidence(&evidence)? {
    366                 return Ok(Some(event));
    367             }
    368         }
    369 
    370         Ok(None)
    371     }
    372 
    373     fn last_imported_change_seq(&self) -> Result<i64, AppSqliteError> {
    374         match self.connection.query_row(
    375             "SELECT last_change_seq
    376              FROM local_interop_projection_cursor
    377              WHERE consumer_id = ?1
    378              LIMIT 1",
    379             [APP_LOCAL_INTEROP_CURSOR_ID],
    380             |row| row.get::<_, i64>(0),
    381         ) {
    382             Ok(last_change_seq) => Ok(last_change_seq),
    383             Err(rusqlite::Error::QueryReturnedNoRows) => Ok(0),
    384             Err(source) => Err(AppSqliteError::Query {
    385                 operation: "read app local interop projection cursor",
    386                 source,
    387             }),
    388         }
    389     }
    390 
    391     fn advance_import_cursor(&self, last_change_seq: i64) -> Result<(), AppSqliteError> {
    392         self.connection
    393             .execute(
    394                 "INSERT INTO local_interop_projection_cursor (
    395                     consumer_id,
    396                     last_change_seq,
    397                     updated_at
    398                  ) VALUES (?1, ?2, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
    399                  ON CONFLICT(consumer_id) DO UPDATE SET
    400                     last_change_seq = max(
    401                         local_interop_projection_cursor.last_change_seq,
    402                         excluded.last_change_seq
    403                     ),
    404                     updated_at = excluded.updated_at",
    405                 params![APP_LOCAL_INTEROP_CURSOR_ID, last_change_seq],
    406             )
    407             .map_err(|source| AppSqliteError::Query {
    408                 operation: "advance app local interop projection cursor",
    409                 source,
    410             })?;
    411         Ok(())
    412     }
    413 
    414     fn import_record(&self, record: &LocalEventRecord) -> Result<ImportOutcome, AppSqliteError> {
    415         self.begin_import_record_savepoint()?;
    416         match self.import_record_inner(record) {
    417             Ok(outcome) => {
    418                 self.release_import_record_savepoint()?;
    419                 Ok(outcome)
    420             }
    421             Err(error) => {
    422                 let _ = self.rollback_import_record_savepoint();
    423                 let _ = self.release_import_record_savepoint();
    424                 Err(error)
    425             }
    426         }
    427     }
    428 
    429     fn import_record_inner(
    430         &self,
    431         record: &LocalEventRecord,
    432     ) -> Result<ImportOutcome, AppSqliteError> {
    433         let superseded_listing_ids = match self.duplicate_signed_event_action(record)? {
    434             DuplicateSignedEventAction::Import => Vec::new(),
    435             DuplicateSignedEventAction::ReplaceExisting(event_id) => self
    436                 .delete_duplicate_signed_event_imports(
    437                     event_id.as_str(),
    438                     record.record_id.as_str(),
    439                 )?,
    440             DuplicateSignedEventAction::Skip => return Ok(ImportOutcome::Skipped),
    441         };
    442         let projection = match record.family {
    443             LocalRecordFamily::LocalWork => self.import_local_work(record)?,
    444             LocalRecordFamily::SignedEvent => self.import_signed_event(record)?,
    445         };
    446         match projection {
    447             Some(projection) => {
    448                 let projected_kind = projection.kind;
    449                 let projected_id = projection.projected_id;
    450                 self.record_import(record, projected_kind, projected_id.clone())?;
    451                 if projected_kind == "listing" {
    452                     if let Some(projected_id) = projected_id.as_deref() {
    453                         self.finish_duplicate_listing_replacement(
    454                             &superseded_listing_ids,
    455                             projected_id,
    456                         )?;
    457                     }
    458                 }
    459                 Ok(ImportOutcome::Imported)
    460             }
    461             None => {
    462                 self.record_import(record, "unsupported", None)?;
    463                 Ok(ImportOutcome::Skipped)
    464             }
    465         }
    466     }
    467 
    468     fn begin_import_record_savepoint(&self) -> Result<(), AppSqliteError> {
    469         self.connection
    470             .execute_batch("SAVEPOINT app_local_interop_import_record")
    471             .map_err(|source| AppSqliteError::Query {
    472                 operation: "begin local interop import record transaction",
    473                 source,
    474             })
    475     }
    476 
    477     fn rollback_import_record_savepoint(&self) -> Result<(), AppSqliteError> {
    478         self.connection
    479             .execute_batch("ROLLBACK TO app_local_interop_import_record")
    480             .map_err(|source| AppSqliteError::Query {
    481                 operation: "rollback local interop import record transaction",
    482                 source,
    483             })
    484     }
    485 
    486     fn release_import_record_savepoint(&self) -> Result<(), AppSqliteError> {
    487         self.connection
    488             .execute_batch("RELEASE app_local_interop_import_record")
    489             .map_err(|source| AppSqliteError::Query {
    490                 operation: "release local interop import record transaction",
    491                 source,
    492             })
    493     }
    494 
    495     fn duplicate_signed_event_action(
    496         &self,
    497         record: &LocalEventRecord,
    498     ) -> Result<DuplicateSignedEventAction, AppSqliteError> {
    499         if record.family != LocalRecordFamily::SignedEvent {
    500             return Ok(DuplicateSignedEventAction::Import);
    501         }
    502         let Some(event_id) = record
    503             .event_id
    504             .as_deref()
    505             .map(str::trim)
    506             .filter(|event_id| !event_id.is_empty())
    507         else {
    508             return Ok(DuplicateSignedEventAction::Import);
    509         };
    510         let mut statement = self
    511             .connection
    512             .prepare(
    513                 "SELECT source_runtime, owner_account_id, local_status, outbox_status
    514                  FROM local_interop_imports
    515                  WHERE event_id = ?1
    516                     AND record_id <> ?2
    517                     AND record_family = 'signed_event'",
    518             )
    519             .map_err(|source| AppSqliteError::Query {
    520                 operation: "prepare duplicate local interop signed event query",
    521                 source,
    522             })?;
    523         let rows = statement
    524             .query_map(params![event_id, record.record_id.as_str()], |row| {
    525                 Ok(StoredSignedEventDuplicate {
    526                     source_runtime: row.get(0)?,
    527                     owner_account_id: row.get(1)?,
    528                     local_status: row.get(2)?,
    529                     outbox_status: row.get(3)?,
    530                 })
    531             })
    532             .map_err(|source| AppSqliteError::Query {
    533                 operation: "query duplicate local interop signed events",
    534                 source,
    535             })?;
    536         let mut existing_precedence = None;
    537         for row in rows {
    538             let duplicate = row.map_err(|source| AppSqliteError::Query {
    539                 operation: "read duplicate local interop signed event",
    540                 source,
    541             })?;
    542             existing_precedence = Some(existing_precedence.unwrap_or(0).max(
    543                 signed_event_evidence_precedence(
    544                     duplicate.source_runtime.as_str(),
    545                     duplicate.owner_account_id.as_deref(),
    546                     duplicate.local_status.as_str(),
    547                     duplicate.outbox_status.as_str(),
    548                 ),
    549             ));
    550         }
    551         let Some(existing_precedence) = existing_precedence else {
    552             return Ok(DuplicateSignedEventAction::Import);
    553         };
    554         let incoming_precedence = signed_event_evidence_precedence(
    555             record.source_runtime.as_str(),
    556             record.owner_account_id.as_deref(),
    557             record.status.as_str(),
    558             record.outbox_status.as_str(),
    559         );
    560         if incoming_precedence > existing_precedence {
    561             Ok(DuplicateSignedEventAction::ReplaceExisting(
    562                 event_id.to_owned(),
    563             ))
    564         } else {
    565             Ok(DuplicateSignedEventAction::Skip)
    566         }
    567     }
    568 
    569     fn delete_duplicate_signed_event_imports(
    570         &self,
    571         event_id: &str,
    572         record_id: &str,
    573     ) -> Result<Vec<String>, AppSqliteError> {
    574         let superseded_listing_ids =
    575             self.superseded_duplicate_listing_projection_ids(event_id, record_id)?;
    576         self.connection
    577             .execute(
    578                 "DELETE FROM local_interop_imports
    579                  WHERE event_id = ?1
    580                     AND record_id <> ?2
    581                     AND record_family = 'signed_event'",
    582                 params![event_id, record_id],
    583             )
    584             .map_err(|source| AppSqliteError::Query {
    585                 operation: "delete superseded duplicate local interop signed event",
    586                 source,
    587             })?;
    588         Ok(superseded_listing_ids)
    589     }
    590 
    591     fn finish_duplicate_listing_replacement(
    592         &self,
    593         superseded_listing_ids: &[String],
    594         canonical_listing_product_id: &str,
    595     ) -> Result<(), AppSqliteError> {
    596         self.migrate_duplicate_buyer_cart_lines(
    597             superseded_listing_ids,
    598             canonical_listing_product_id,
    599         )?;
    600         self.delete_unreferenced_listing_products(superseded_listing_ids)?;
    601         Ok(())
    602     }
    603 
    604     fn superseded_duplicate_listing_projection_ids(
    605         &self,
    606         event_id: &str,
    607         record_id: &str,
    608     ) -> Result<Vec<String>, AppSqliteError> {
    609         let mut statement = self
    610             .connection
    611             .prepare(
    612                 "SELECT projected_id
    613                  FROM local_interop_imports
    614                  WHERE event_id = ?1
    615                     AND record_id <> ?2
    616                     AND record_family = 'signed_event'
    617                     AND projected_kind = 'listing'
    618                     AND projected_id IS NOT NULL",
    619             )
    620             .map_err(|source| AppSqliteError::Query {
    621                 operation: "prepare superseded duplicate listing projection query",
    622                 source,
    623             })?;
    624         let rows = statement
    625             .query_map(params![event_id, record_id], |row| row.get::<_, String>(0))
    626             .map_err(|source| AppSqliteError::Query {
    627                 operation: "query superseded duplicate listing projections",
    628                 source,
    629             })?;
    630         rows.map(|row| {
    631             row.map_err(|source| AppSqliteError::Query {
    632                 operation: "read superseded duplicate listing projection",
    633                 source,
    634             })
    635         })
    636         .collect()
    637     }
    638 
    639     fn delete_unreferenced_listing_products(
    640         &self,
    641         product_ids: &[String],
    642     ) -> Result<(), AppSqliteError> {
    643         for product_id in product_ids {
    644             self.connection
    645                 .execute(
    646                     "DELETE FROM products
    647                      WHERE id = ?1
    648                         AND NOT EXISTS (
    649                             SELECT 1
    650                             FROM local_interop_imports
    651                             WHERE projected_kind = 'listing'
    652                                AND projected_id = ?1
    653                         )",
    654                     params![product_id],
    655                 )
    656                 .map_err(|source| AppSqliteError::Query {
    657                     operation: "delete unreferenced superseded listing product",
    658                     source,
    659                 })?;
    660         }
    661         Ok(())
    662     }
    663 
    664     fn migrate_duplicate_buyer_cart_lines(
    665         &self,
    666         product_ids: &[String],
    667         canonical_product_id: &str,
    668     ) -> Result<(), AppSqliteError> {
    669         for product_id in product_ids {
    670             if product_id == canonical_product_id {
    671                 continue;
    672             }
    673             self.connection
    674                 .execute(
    675                     "INSERT INTO buyer_cart_lines (
    676                         buyer_context_key,
    677                         product_id,
    678                         quantity,
    679                         listing_bin_id,
    680                         quantity_unit_label,
    681                         unit_price_minor_units,
    682                         price_currency,
    683                         farm_key,
    684                         listing_addr,
    685                         listing_event_id,
    686                         seller_pubkey,
    687                         listing_relays_json,
    688                         updated_at
    689                      )
    690                      SELECT
    691                         buyer_context_key,
    692                         ?2,
    693                         quantity,
    694                         listing_bin_id,
    695                         quantity_unit_label,
    696                         unit_price_minor_units,
    697                         price_currency,
    698                         farm_key,
    699                         listing_addr,
    700                         listing_event_id,
    701                         seller_pubkey,
    702                         listing_relays_json,
    703                         strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
    704                      FROM buyer_cart_lines
    705                      WHERE product_id = ?1
    706                      ON CONFLICT(buyer_context_key, product_id) DO UPDATE SET
    707                         quantity = buyer_cart_lines.quantity + excluded.quantity,
    708                         listing_bin_id = coalesce(nullif(buyer_cart_lines.listing_bin_id, ''), excluded.listing_bin_id),
    709                         quantity_unit_label = coalesce(nullif(buyer_cart_lines.quantity_unit_label, ''), excluded.quantity_unit_label),
    710                         unit_price_minor_units = coalesce(buyer_cart_lines.unit_price_minor_units, excluded.unit_price_minor_units),
    711                         price_currency = coalesce(nullif(buyer_cart_lines.price_currency, ''), excluded.price_currency),
    712                         farm_key = coalesce(nullif(buyer_cart_lines.farm_key, ''), excluded.farm_key),
    713                         listing_addr = coalesce(nullif(buyer_cart_lines.listing_addr, ''), excluded.listing_addr),
    714                         listing_event_id = coalesce(nullif(buyer_cart_lines.listing_event_id, ''), excluded.listing_event_id),
    715                         seller_pubkey = coalesce(nullif(buyer_cart_lines.seller_pubkey, ''), excluded.seller_pubkey),
    716                         listing_relays_json = coalesce(nullif(buyer_cart_lines.listing_relays_json, ''), excluded.listing_relays_json),
    717                         updated_at = excluded.updated_at",
    718                     params![product_id, canonical_product_id],
    719                 )
    720                 .map_err(|source| AppSqliteError::Query {
    721                     operation: "migrate duplicate listing buyer cart lines",
    722                     source,
    723                 })?;
    724             self.connection
    725                 .execute(
    726                     "DELETE FROM buyer_cart_lines
    727                      WHERE product_id = ?1",
    728                     params![product_id],
    729                 )
    730                 .map_err(|source| AppSqliteError::Query {
    731                     operation: "delete migrated duplicate listing buyer cart lines",
    732                     source,
    733                 })?;
    734         }
    735         Ok(())
    736     }
    737 
    738     fn import_local_work(
    739         &self,
    740         record: &LocalEventRecord,
    741     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
    742         let Some(payload) = record.local_work_json.as_ref() else {
    743             return Ok(None);
    744         };
    745         match string_at(payload, &["record_kind"]).as_deref() {
    746             Some("farm_config_v1") => self.import_farm_config(record, payload),
    747             Some("listing_draft_v1") => self.import_listing_draft(record, payload),
    748             _ => Ok(None),
    749         }
    750     }
    751 
    752     fn import_signed_event(
    753         &self,
    754         record: &LocalEventRecord,
    755     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
    756         match record.event_kind {
    757             Some(KIND_FARM) => self.import_signed_farm(record),
    758             Some(KIND_LISTING | KIND_LISTING_DRAFT) => self.import_signed_listing(record),
    759             Some(KIND_VALIDATION_RECEIPT) => self.import_signed_validation_receipt(record),
    760             Some(kind) if active_order_event_kind(kind) => self.import_signed_active_order(record),
    761             _ => Ok(Some(ProjectionRecord {
    762                 kind: "signed_event",
    763                 projected_id: record.event_id.clone(),
    764             })),
    765         }
    766     }
    767 
    768     fn import_farm_config(
    769         &self,
    770         record: &LocalEventRecord,
    771         payload: &Value,
    772     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
    773         let Some(document) = payload.get("document") else {
    774             return Ok(None);
    775         };
    776         let Some(farm_key) = record
    777             .farm_id
    778             .clone()
    779             .or_else(|| string_at(document, &["selection", "farm_d_tag"]))
    780             .or_else(|| string_at(document, &["farm", "d_tag"]))
    781         else {
    782             return Ok(None);
    783         };
    784         let owner_pubkey = record.owner_pubkey.clone();
    785         let Some(farm_id) = projected_farm_id(
    786             record.source_runtime,
    787             owner_pubkey.as_deref(),
    788             farm_key.as_str(),
    789         ) else {
    790             return Ok(None);
    791         };
    792         let display_name = string_at(document, &["profile", "display_name"])
    793             .or_else(|| string_at(document, &["profile", "name"]))
    794             .or_else(|| string_at(document, &["farm", "name"]))
    795             .unwrap_or_else(|| "Local farm".to_owned());
    796         let location = string_at(document, &["farm", "location", "primary"])
    797             .or_else(|| string_at(document, &["listing_defaults", "location", "primary"]))
    798             .unwrap_or_default();
    799         let methods = string_at(document, &["listing_defaults", "delivery_method"])
    800             .and_then(|method| farm_order_method(method.as_str()))
    801             .into_iter()
    802             .collect::<Vec<_>>();
    803         let saved_farm = FarmSummary {
    804             farm_id,
    805             display_name: display_name.clone(),
    806             readiness: FarmReadiness::Incomplete,
    807         };
    808         self.upsert_local_work_farm_summary(&saved_farm)?;
    809         let owner_account_id = record
    810             .owner_account_id
    811             .clone()
    812             .or_else(|| string_at(document, &["selection", "account"]));
    813         if let Some(owner_account_id) = owner_account_id.as_deref() {
    814             let projection = FarmSetupProjection::new(
    815                 FarmSetupDraft::new(display_name, location, methods),
    816                 Some(saved_farm),
    817             );
    818             AppFarmSetupRepository::new(self.connection)
    819                 .save_farm_setup(owner_account_id, &projection)?;
    820         }
    821         Ok(Some(ProjectionRecord {
    822             kind: "farm",
    823             projected_id: Some(farm_id.to_string()),
    824         }))
    825     }
    826 
    827     fn import_listing_draft(
    828         &self,
    829         record: &LocalEventRecord,
    830         payload: &Value,
    831     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
    832         let Some(document) = payload.get("document") else {
    833             return Ok(None);
    834         };
    835         let Some(listing_key) =
    836             string_at(document, &["listing", "d_tag"]).or_else(|| listing_id(record))
    837         else {
    838             return Ok(None);
    839         };
    840         let owner_pubkey = record
    841             .owner_pubkey
    842             .clone()
    843             .or_else(|| string_at(document, &["seller_actor", "pubkey"]));
    844         let farm_key = record
    845             .farm_id
    846             .clone()
    847             .or_else(|| string_at(document, &["listing", "farm_d_tag"]));
    848         let Some(farm_key) = farm_key else {
    849             return Ok(None);
    850         };
    851         let Some(farm_id) = projected_farm_id(
    852             record.source_runtime,
    853             owner_pubkey.as_deref(),
    854             farm_key.as_str(),
    855         ) else {
    856             return Ok(None);
    857         };
    858         self.ensure_farm_exists(farm_id)?;
    859         let Some(product_id) = projected_product_id(
    860             record.source_runtime,
    861             owner_pubkey.as_deref(),
    862             listing_key.as_str(),
    863         ) else {
    864             return Ok(None);
    865         };
    866         let title = string_at(document, &["product", "title"])
    867             .or_else(|| string_at(document, &["product", "key"]))
    868             .unwrap_or_else(|| "Local product".to_owned());
    869         let subtitle = string_at(document, &["product", "summary"]).unwrap_or_default();
    870         let unit_label = string_at(document, &["primary_bin", "quantity_unit"])
    871             .or_else(|| string_at(document, &["primary_bin", "price_per_unit"]))
    872             .unwrap_or_default();
    873         let listing_bin_id = string_at(document, &["primary_bin", "bin_id"]);
    874         let price_minor_units = string_at(document, &["primary_bin", "price_amount"])
    875             .and_then(|price| parse_decimal_minor_units(price.as_str()));
    876         let price_currency = string_at(document, &["primary_bin", "price_currency"])
    877             .unwrap_or_else(|| "USD".to_owned());
    878         let stock_count = string_at(document, &["inventory", "available"])
    879             .and_then(|quantity| parse_u32_quantity(quantity.as_str()));
    880         self.upsert_product(ProductProjection {
    881             product_id,
    882             farm_id,
    883             title,
    884             subtitle,
    885             status: ProductStatus::Draft,
    886             unit_label,
    887             price_minor_units,
    888             price_currency,
    889             stock_count,
    890             availability_window_id: None,
    891             listing_bin_id,
    892         })?;
    893         Ok(Some(ProjectionRecord {
    894             kind: "listing",
    895             projected_id: Some(product_id.to_string()),
    896         }))
    897     }
    898 
    899     fn import_signed_farm(
    900         &self,
    901         record: &LocalEventRecord,
    902     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
    903         let Some(content) = record.event_content.as_deref() else {
    904             return Ok(None);
    905         };
    906         let content = parse_json_value(content)?;
    907         let tags = record.event_tags_json.as_ref();
    908         let Some(farm_key) = tag_index_value(tags, "d", 1)
    909             .or_else(|| string_at(&content, &["d_tag"]))
    910             .or_else(|| record.farm_id.clone())
    911         else {
    912             return Ok(None);
    913         };
    914         let owner_pubkey = record
    915             .event_pubkey
    916             .as_deref()
    917             .or(record.owner_pubkey.as_deref());
    918         let Some(farm_id) =
    919             projected_farm_id(record.source_runtime, owner_pubkey, farm_key.as_str())
    920         else {
    921             return Ok(None);
    922         };
    923         let display_name =
    924             string_at(&content, &["name"]).unwrap_or_else(|| "Local farm".to_owned());
    925         let readiness = match signed_farm_readiness(&content, tags) {
    926             Some(readiness) => readiness,
    927             None => self
    928                 .load_farm_readiness(farm_id)?
    929                 .unwrap_or(FarmReadiness::Incomplete),
    930         };
    931         self.upsert_farm_summary(&FarmSummary {
    932             farm_id,
    933             display_name,
    934             readiness,
    935         })?;
    936         Ok(Some(ProjectionRecord {
    937             kind: "farm",
    938             projected_id: Some(farm_id.to_string()),
    939         }))
    940     }
    941 
    942     fn import_signed_listing(
    943         &self,
    944         record: &LocalEventRecord,
    945     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
    946         let content = record
    947             .event_content
    948             .as_deref()
    949             .and_then(parse_json_value_opt);
    950         let tags = record.event_tags_json.as_ref();
    951         let listing_key = content
    952             .as_ref()
    953             .and_then(|content| string_at(content, &["d_tag"]))
    954             .or_else(|| tag_index_value(tags, "d", 1))
    955             .or_else(|| listing_id(record));
    956         let Some(listing_key) = listing_key else {
    957             return Ok(None);
    958         };
    959         let farm_key = content
    960             .as_ref()
    961             .and_then(|content| string_at(content, &["farm", "d_tag"]))
    962             .or_else(|| tag_index_value(tags, "a", 1).and_then(|addr| address_d_tag(&addr)))
    963             .or_else(|| record.farm_id.clone());
    964         let Some(farm_key) = farm_key else {
    965             return Ok(None);
    966         };
    967         let signed_farm_pubkey = content
    968             .as_ref()
    969             .and_then(|content| string_at(content, &["farm", "pubkey"]))
    970             .or_else(|| tag_index_value(tags, "a", 1).and_then(|addr| address_pubkey(&addr)));
    971         let farm_pubkey = signed_farm_pubkey
    972             .as_deref()
    973             .or(record.event_pubkey.as_deref())
    974             .or(record.owner_pubkey.as_deref());
    975         let listing_pubkey = record
    976             .event_pubkey
    977             .as_deref()
    978             .or(signed_farm_pubkey.as_deref())
    979             .or(record.owner_pubkey.as_deref());
    980         let app_shaped_network_listing = record.source_runtime == SourceRuntime::Network
    981             && parse_app_d_tag_uuid(farm_key.as_str()).is_some()
    982             && parse_app_d_tag_uuid(listing_key.as_str()).is_some();
    983         let mut existing_projection = if app_shaped_network_listing {
    984             None
    985         } else {
    986             self.existing_listing_projection(record.listing_addr.as_deref())?
    987         };
    988         if existing_projection.is_none() {
    989             existing_projection = self.existing_app_origin_listing_projection(
    990                 record,
    991                 farm_key.as_str(),
    992                 listing_key.as_str(),
    993                 listing_pubkey,
    994                 tags,
    995             )?;
    996         }
    997         let (farm_id, product_id) = if let Some(existing_projection) = existing_projection {
    998             (existing_projection.farm_id, existing_projection.product_id)
    999         } else {
   1000             let Some(farm_id) =
   1001                 projected_farm_id(record.source_runtime, farm_pubkey, farm_key.as_str())
   1002             else {
   1003                 return Ok(None);
   1004             };
   1005             let Some(product_id) =
   1006                 projected_product_id(record.source_runtime, listing_pubkey, listing_key.as_str())
   1007             else {
   1008                 return Ok(None);
   1009             };
   1010             (farm_id, product_id)
   1011         };
   1012         let projection_record = ProjectionRecord {
   1013             kind: "listing",
   1014             projected_id: Some(product_id.to_string()),
   1015         };
   1016         if !self.signed_listing_is_current(record, listing_key.as_str())? {
   1017             return Ok(Some(projection_record));
   1018         }
   1019         self.ensure_farm_exists(farm_id)?;
   1020         let title = content
   1021             .as_ref()
   1022             .and_then(|content| string_at(content, &["product", "title"]))
   1023             .or_else(|| tag_index_value(tags, "title", 1))
   1024             .or_else(|| {
   1025                 content
   1026                     .as_ref()
   1027                     .and_then(|content| string_at(content, &["product", "key"]))
   1028             })
   1029             .or_else(|| tag_index_value(tags, "key", 1))
   1030             .unwrap_or_else(|| "Local product".to_owned());
   1031         let subtitle = content
   1032             .as_ref()
   1033             .and_then(|content| string_at(content, &["product", "summary"]))
   1034             .or_else(|| tag_index_value(tags, "summary", 1))
   1035             .unwrap_or_default();
   1036         let bin = content.as_ref().and_then(primary_bin);
   1037         let listing_bin_id = bin
   1038             .and_then(|value| string_at(value, &["bin_id"]))
   1039             .or_else(|| tag_index_value(tags, "radroots:bin", 1));
   1040         let unit_label = bin
   1041             .and_then(|value| {
   1042                 string_at(value, &["quantity", "unit"])
   1043                     .or_else(|| string_at(value, &["display_unit"]))
   1044                     .or_else(|| string_at(value, &["display_price_unit"]))
   1045             })
   1046             .or_else(|| tag_index_value(tags, "radroots:bin", 3))
   1047             .unwrap_or_default();
   1048         let price_minor_units = bin
   1049             .and_then(|value| {
   1050                 string_at(value, &["price_per_canonical_unit", "amount", "amount"])
   1051                     .or_else(|| string_at(value, &["display_price", "amount"]))
   1052                     .and_then(|price| parse_decimal_minor_units(price.as_str()))
   1053             })
   1054             .or_else(|| {
   1055                 tag_index_value(tags, "radroots:price", 2)
   1056                     .or_else(|| tag_index_value(tags, "price", 1))
   1057                     .and_then(|price| parse_decimal_minor_units(price.as_str()))
   1058             });
   1059         let price_currency = bin
   1060             .and_then(|value| {
   1061                 string_at(value, &["price_per_canonical_unit", "amount", "currency"])
   1062                     .or_else(|| string_at(value, &["display_price", "currency"]))
   1063             })
   1064             .or_else(|| tag_index_value(tags, "radroots:price", 3))
   1065             .or_else(|| tag_index_value(tags, "price", 2))
   1066             .unwrap_or_else(|| "USD".to_owned());
   1067         let stock_count = content
   1068             .as_ref()
   1069             .and_then(|content| string_at(content, &["inventory_available"]))
   1070             .or_else(|| tag_index_value(tags, "inventory", 1))
   1071             .and_then(|quantity| parse_u32_quantity(quantity.as_str()));
   1072         let Some(status) = signed_listing_product_status(record, content.as_ref(), tags) else {
   1073             return Ok(None);
   1074         };
   1075         let fulfillment_method = signed_listing_fulfillment_method(content.as_ref(), tags);
   1076         let availability_window_id = if status == ProductStatus::Published {
   1077             match fulfillment_method {
   1078                 Some(method) => self.ensure_signed_listing_availability_window(
   1079                     farm_id,
   1080                     listing_key.as_str(),
   1081                     content.as_ref(),
   1082                     tags,
   1083                     method,
   1084                 )?,
   1085                 None => None,
   1086             }
   1087         } else {
   1088             None
   1089         };
   1090         if availability_window_id.is_some()
   1091             && let Some(method) = fulfillment_method
   1092         {
   1093             self.mark_farm_buyer_visible(farm_id, record, method)?;
   1094         }
   1095         self.upsert_product(ProductProjection {
   1096             product_id,
   1097             farm_id,
   1098             title,
   1099             subtitle,
   1100             status,
   1101             unit_label,
   1102             price_minor_units,
   1103             price_currency,
   1104             stock_count,
   1105             availability_window_id,
   1106             listing_bin_id,
   1107         })?;
   1108         Ok(Some(projection_record))
   1109     }
   1110 
   1111     fn import_signed_active_order(
   1112         &self,
   1113         record: &LocalEventRecord,
   1114     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
   1115         if !signed_event_record_is_usable(record) {
   1116             return Ok(Some(signed_event_projection(record)));
   1117         }
   1118         let Some(event) = signed_event_from_record(record)? else {
   1119             return Ok(Some(signed_event_projection(record)));
   1120         };
   1121         let Some(current_evidence) = active_order_evidence_from_event(&event) else {
   1122             return Ok(Some(signed_event_projection(record)));
   1123         };
   1124         self.project_active_order(record, current_evidence)?;
   1125         Ok(Some(signed_event_projection(record)))
   1126     }
   1127 
   1128     fn import_signed_validation_receipt(
   1129         &self,
   1130         record: &LocalEventRecord,
   1131     ) -> Result<Option<ProjectionRecord>, AppSqliteError> {
   1132         if !signed_event_record_is_usable(record) {
   1133             return Ok(Some(signed_event_projection(record)));
   1134         }
   1135         let Some(event) = signed_event_from_record(record)? else {
   1136             return Ok(Some(signed_event_projection(record)));
   1137         };
   1138         let Ok(verified) = validation_receipt_from_event(&event) else {
   1139             return Ok(Some(signed_event_projection(record)));
   1140         };
   1141         self.upsert_validation_receipt_projection(&event, &verified.receipt, &verified.tags)?;
   1142         Ok(Some(ProjectionRecord {
   1143             kind: "validation_receipt",
   1144             projected_id: Some(event.id),
   1145         }))
   1146     }
   1147 
   1148     fn project_active_order(
   1149         &self,
   1150         record: &LocalEventRecord,
   1151         current_evidence: ActiveOrderEvidence,
   1152     ) -> Result<(), AppSqliteError> {
   1153         if let ActiveOrderEvidence::Request(request) = &current_evidence {
   1154             let order_id = self.upsert_order_request(record, &request.payload)?;
   1155             self.attach_validation_receipts_for_request(
   1156                 request.event_id.as_str(),
   1157                 request.payload.order_id.as_str(),
   1158                 order_id,
   1159             )?;
   1160         }
   1161         let mut evidence = self.load_active_order_evidence(current_evidence.order_id())?;
   1162         evidence.push(current_evidence);
   1163         dedupe_active_order_evidence(&mut evidence);
   1164         let Some((raw_order_id, buyer_pubkey)) = evidence
   1165             .first()
   1166             .map(ActiveOrderEvidence::order_projection_identity)
   1167         else {
   1168             return Ok(());
   1169         };
   1170         let raw_order_id = raw_order_id.to_owned();
   1171         let buyer_pubkey = buyer_pubkey.to_owned();
   1172         let order_id = projected_order_id(raw_order_id.as_str(), buyer_pubkey.as_str());
   1173         let buckets = ActiveOrderEvidenceBuckets::from_evidence(evidence);
   1174         let requests = buckets.requests.clone();
   1175         let revision_proposals = buckets.revision_proposals.clone();
   1176         let revision_decisions = buckets.revision_decisions.clone();
   1177         let reducer_order_id =
   1178             raw_order_id
   1179                 .parse::<RadrootsOrderId>()
   1180                 .map_err(|_| AppSqliteError::DecodeId {
   1181                     field: "order_id",
   1182                     value: raw_order_id.clone(),
   1183                 })?;
   1184         let projection = reduce_order_events(
   1185             &reducer_order_id,
   1186             RadrootsOrderReductionInputs {
   1187                 requests: buckets.requests,
   1188                 decisions: buckets.decisions,
   1189                 revision_proposals: buckets.revision_proposals,
   1190                 revision_decisions: buckets.revision_decisions,
   1191                 cancellations: buckets.cancellations,
   1192             },
   1193         );
   1194         let request_payload = projection.request_event_id.as_deref().and_then(|event_id| {
   1195             requests
   1196                 .iter()
   1197                 .find(|request| request.event_id == event_id)
   1198                 .map(|request| &request.payload)
   1199         });
   1200         let revision =
   1201             active_order_revision_status(&projection, &revision_proposals, &revision_decisions);
   1202         let agreement_source = request_payload.map(|request| {
   1203             active_order_agreement_source(
   1204                 request,
   1205                 &projection,
   1206                 &revision_proposals,
   1207                 &revision_decisions,
   1208             )
   1209         });
   1210         self.apply_active_order_projection(
   1211             order_id,
   1212             &projection,
   1213             revision,
   1214             agreement_source.as_ref(),
   1215         )
   1216     }
   1217 
   1218     fn upsert_order_request(
   1219         &self,
   1220         record: &LocalEventRecord,
   1221         payload: &RadrootsOrderRequest,
   1222     ) -> Result<OrderId, AppSqliteError> {
   1223         let existing_listing =
   1224             self.existing_listing_projection(Some(payload.listing_addr.as_str()))?;
   1225         let farm_id = if let Some(existing_listing) = existing_listing.as_ref() {
   1226             existing_listing.farm_id
   1227         } else {
   1228             deterministic_farm_id(
   1229                 Some(payload.seller_pubkey.as_str()),
   1230                 payload.listing_addr.as_str(),
   1231             )
   1232         };
   1233         self.ensure_farm_exists(farm_id)?;
   1234         let order_id = projected_order_id(payload.order_id.as_str(), payload.buyer_pubkey.as_str());
   1235         let order_number = existing_order_number(self.connection, order_id)?
   1236             .unwrap_or_else(|| deterministic_order_number(payload.order_id.as_str()));
   1237         self.connection
   1238             .execute(
   1239                 "INSERT INTO orders (
   1240                     id,
   1241                     farm_id,
   1242                     fulfillment_window_id,
   1243                     order_number,
   1244                     customer_display_name,
   1245                     status,
   1246                     updated_at,
   1247                     buyer_context_key,
   1248                     buyer_email,
   1249                     buyer_phone,
   1250                     buyer_order_note
   1251                  ) VALUES (?1, ?2, null, ?3, ?4, 'needs_action', strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), ?5, '', '', '')
   1252                  ON CONFLICT(id) DO UPDATE SET
   1253                     farm_id = excluded.farm_id,
   1254                     order_number = excluded.order_number,
   1255                     customer_display_name = excluded.customer_display_name,
   1256                     status = excluded.status,
   1257                     buyer_context_key = coalesce(orders.buyer_context_key, excluded.buyer_context_key),
   1258                     updated_at = excluded.updated_at",
   1259                 params![
   1260                     order_id.to_string(),
   1261                     farm_id.to_string(),
   1262                     order_number.as_str(),
   1263                     order_customer_display_name(payload.buyer_pubkey.as_str()),
   1264                     order_buyer_context_key(record, payload.buyer_pubkey.as_str()),
   1265                 ],
   1266             )
   1267             .map_err(|source| AppSqliteError::Query {
   1268                 operation: "upsert local interop order request",
   1269                 source,
   1270             })?;
   1271         self.replace_order_request_lines(order_id, payload, existing_listing.as_ref(), record)?;
   1272         Ok(order_id)
   1273     }
   1274 
   1275     fn apply_active_order_projection(
   1276         &self,
   1277         order_id: OrderId,
   1278         projection: &RadrootsOrderProjection,
   1279         revision: TradeRevisionStatus,
   1280         agreement_source: Option<&ActiveOrderAgreementSource>,
   1281     ) -> Result<(), AppSqliteError> {
   1282         let workflow = TradeWorkflowProjection::from_active_order_projection(
   1283             order_id,
   1284             projection,
   1285             revision,
   1286             TradeProvenanceProjection::from_primary_source(TradeWorkflowSource::LocalEvents),
   1287         );
   1288         let Some(status) = order_status_from_active_order_projection(projection) else {
   1289             return Ok(());
   1290         };
   1291         self.connection
   1292             .execute(
   1293                 "UPDATE orders
   1294                  SET status = ?2,
   1295                      workflow_revision = ?3,
   1296                      workflow_agreement = ?4,
   1297                      workflow_inventory = ?5,
   1298                      workflow_provenance_source = ?6,
   1299                      workflow_provenance_last_event_id = ?7,
   1300                      updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
   1301                  WHERE id = ?1",
   1302                 params![
   1303                     workflow.order_id.to_string(),
   1304                     status.storage_key(),
   1305                     workflow.revision.storage_key(),
   1306                     workflow.agreement.storage_key(),
   1307                     workflow.inventory.storage_key(),
   1308                     workflow.provenance.primary_source.storage_key(),
   1309                     workflow.provenance.last_event_id.as_deref()
   1310                 ],
   1311             )
   1312             .map_err(|source| AppSqliteError::Query {
   1313                 operation: "apply local interop active order projection",
   1314                 source,
   1315             })?;
   1316         if projection.economics.is_some()
   1317             && let Some(agreement_source) = agreement_source
   1318         {
   1319             self.replace_active_order_agreement_lines(workflow.order_id, agreement_source)?;
   1320         }
   1321         Ok(())
   1322     }
   1323 
   1324     fn upsert_validation_receipt_projection(
   1325         &self,
   1326         event: &RadrootsNostrEvent,
   1327         receipt: &RadrootsTradeValidationReceipt,
   1328         tags: &RadrootsValidationReceiptTags,
   1329     ) -> Result<(), AppSqliteError> {
   1330         let order_id = match self.validation_receipt_order_attachment(tags)? {
   1331             ValidationReceiptOrderAttachment::Pending => None,
   1332             ValidationReceiptOrderAttachment::Attached(order_id) => Some(order_id),
   1333             ValidationReceiptOrderAttachment::Rejected => return Ok(()),
   1334         };
   1335         let result = TradeValidationReceiptResult::from_validation_receipt_result(receipt.result);
   1336         let receipt_type =
   1337             TradeValidationReceiptType::from_validation_receipt_type(receipt.receipt_type);
   1338         let proof_system = TradeValidationReceiptProofSystem::from_validation_receipt_proof_system(
   1339             receipt.proof.system,
   1340         );
   1341 
   1342         self.connection
   1343             .execute(
   1344                 "INSERT INTO order_validation_receipts (
   1345                     event_id,
   1346                     order_id,
   1347                     raw_order_id,
   1348                     root_event_id,
   1349                     listing_event_id,
   1350                     target_event_id,
   1351                     receipt_type,
   1352                     result,
   1353                     proof_system,
   1354                     event_set_root,
   1355                     reducer_output_root,
   1356                     public_values_hash,
   1357                     event_created_at
   1358                  ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)
   1359                  ON CONFLICT(event_id) DO UPDATE SET
   1360                     order_id = excluded.order_id,
   1361                     raw_order_id = excluded.raw_order_id,
   1362                     root_event_id = excluded.root_event_id,
   1363                     listing_event_id = excluded.listing_event_id,
   1364                     target_event_id = excluded.target_event_id,
   1365                     receipt_type = excluded.receipt_type,
   1366                     result = excluded.result,
   1367                     proof_system = excluded.proof_system,
   1368                     event_set_root = excluded.event_set_root,
   1369                     reducer_output_root = excluded.reducer_output_root,
   1370                     public_values_hash = excluded.public_values_hash,
   1371                     event_created_at = excluded.event_created_at",
   1372                 params![
   1373                     event.id.as_str(),
   1374                     order_id.map(|order_id| order_id.to_string()),
   1375                     tags.order_id.as_str(),
   1376                     tags.root_event_id.as_str(),
   1377                     tags.listing_event_id.as_str(),
   1378                     tags.target_event_id.as_str(),
   1379                     receipt_type.storage_key(),
   1380                     result.storage_key(),
   1381                     proof_system.storage_key(),
   1382                     tags.event_set_root.as_str(),
   1383                     tags.reducer_output_root.as_str(),
   1384                     tags.public_values_hash.as_str(),
   1385                     i64::from(event.created_at),
   1386                 ],
   1387             )
   1388             .map_err(|source| AppSqliteError::Query {
   1389                 operation: "upsert local interop validation receipt projection",
   1390                 source,
   1391             })?;
   1392         Ok(())
   1393     }
   1394 
   1395     fn validation_receipt_order_attachment(
   1396         &self,
   1397         tags: &RadrootsValidationReceiptTags,
   1398     ) -> Result<ValidationReceiptOrderAttachment, AppSqliteError> {
   1399         let Some(root_event) = self.load_signed_event_by_event_id(tags.root_event_id.as_str())?
   1400         else {
   1401             return Ok(ValidationReceiptOrderAttachment::Pending);
   1402         };
   1403         let Ok(envelope) = order_request_from_event(&root_event) else {
   1404             return Ok(ValidationReceiptOrderAttachment::Rejected);
   1405         };
   1406         if envelope.payload.order_id != tags.order_id {
   1407             return Ok(ValidationReceiptOrderAttachment::Rejected);
   1408         }
   1409 
   1410         Ok(ValidationReceiptOrderAttachment::Attached(
   1411             projected_order_id(
   1412                 envelope.payload.order_id.as_str(),
   1413                 envelope.payload.buyer_pubkey.as_str(),
   1414             ),
   1415         ))
   1416     }
   1417 
   1418     fn attach_validation_receipts_for_request(
   1419         &self,
   1420         root_event_id: &str,
   1421         raw_order_id: &str,
   1422         order_id: OrderId,
   1423     ) -> Result<(), AppSqliteError> {
   1424         self.connection
   1425             .execute(
   1426                 "UPDATE order_validation_receipts
   1427                  SET order_id = ?3
   1428                  WHERE root_event_id = ?1
   1429                     AND raw_order_id = ?2
   1430                     AND order_id IS NULL",
   1431                 params![root_event_id, raw_order_id, order_id.to_string()],
   1432             )
   1433             .map_err(|source| AppSqliteError::Query {
   1434                 operation: "attach local interop validation receipts to request",
   1435                 source,
   1436             })?;
   1437         Ok(())
   1438     }
   1439 
   1440     fn load_active_order_evidence(
   1441         &self,
   1442         order_id: &str,
   1443     ) -> Result<Vec<ActiveOrderEvidence>, AppSqliteError> {
   1444         let mut evidence = Vec::new();
   1445         for kind in ACTIVE_ORDER_EVENT_KINDS {
   1446             for event in self.load_signed_events_by_kind(kind)? {
   1447                 let Some(record) = active_order_evidence_from_event(&event) else {
   1448                     continue;
   1449                 };
   1450                 if record.order_id() == order_id {
   1451                     evidence.push(record);
   1452                 }
   1453             }
   1454         }
   1455         Ok(evidence)
   1456     }
   1457 
   1458     fn replace_order_request_lines(
   1459         &self,
   1460         order_id: OrderId,
   1461         payload: &RadrootsOrderRequest,
   1462         existing_listing: Option<&ExistingListingProjection>,
   1463         record: &LocalEventRecord,
   1464     ) -> Result<(), AppSqliteError> {
   1465         self.connection
   1466             .execute(
   1467                 "DELETE FROM order_lines WHERE order_id = ?1",
   1468                 params![order_id.to_string()],
   1469             )
   1470             .map_err(|source| AppSqliteError::Query {
   1471                 operation: "replace local interop order lines",
   1472                 source,
   1473             })?;
   1474         for (index, item) in payload.items.iter().enumerate() {
   1475             let economics_item = payload
   1476                 .economics
   1477                 .items
   1478                 .iter()
   1479                 .find(|candidate| candidate.bin_id == item.bin_id);
   1480             let unit_label = economics_item
   1481                 .map(|item| item.quantity_unit.to_string())
   1482                 .or_else(|| existing_listing.map(|listing| listing.unit_label.clone()))
   1483                 .unwrap_or_else(|| "item".to_owned());
   1484             let unit_price_minor_units = economics_item.and_then(|item| {
   1485                 parse_decimal_minor_units(item.unit_price_amount.to_string().as_str())
   1486             });
   1487             let price_currency = economics_item
   1488                 .map(|item| item.unit_price_currency.to_string())
   1489                 .unwrap_or_else(|| payload.economics.currency.to_string());
   1490             let title = existing_listing
   1491                 .map(|listing| listing.title.clone())
   1492                 .unwrap_or_else(|| item.bin_id.to_string());
   1493             self.connection
   1494                 .execute(
   1495                     "INSERT INTO order_lines (
   1496                         id,
   1497                         order_id,
   1498                         title,
   1499                         quantity_value,
   1500                         quantity_unit_label,
   1501                         quantity_display,
   1502                         listing_bin_id,
   1503                         unit_price_minor_units,
   1504                         price_currency,
   1505                         farm_key,
   1506                         listing_addr,
   1507                         listing_event_id,
   1508                         listing_relays_json,
   1509                         seller_pubkey,
   1510                         sort_index
   1511                      ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, null, ?13, ?14)",
   1512                     params![
   1513                         format!(
   1514                             "{}:{}",
   1515                             order_id,
   1516                             order_line_product_id(payload, existing_listing, item)
   1517                         ),
   1518                         order_id.to_string(),
   1519                         title.as_str(),
   1520                         i64::from(item.bin_count),
   1521                         unit_label.as_str(),
   1522                         format_quantity_display(item.bin_count, unit_label.as_str()),
   1523                         item.bin_id.as_str(),
   1524                         unit_price_minor_units,
   1525                         price_currency.as_str(),
   1526                         existing_listing.and_then(|listing| listing.farm_key.as_deref()),
   1527                         payload.listing_addr.as_str(),
   1528                         listing_event_id_from_order_record(record).as_deref(),
   1529                         payload.seller_pubkey.as_str(),
   1530                         index as i64,
   1531                     ],
   1532                 )
   1533                 .map_err(|source| AppSqliteError::Query {
   1534                     operation: "insert local interop order line",
   1535                     source,
   1536                 })?;
   1537         }
   1538         Ok(())
   1539     }
   1540 
   1541     fn replace_active_order_agreement_lines(
   1542         &self,
   1543         order_id: OrderId,
   1544         source: &ActiveOrderAgreementSource,
   1545     ) -> Result<(), AppSqliteError> {
   1546         let existing_listing =
   1547             self.existing_listing_projection(Some(source.listing_addr.as_str()))?;
   1548         let metadata = self.existing_order_line_metadata(order_id)?;
   1549         self.connection
   1550             .execute(
   1551                 "DELETE FROM order_lines WHERE order_id = ?1",
   1552                 params![order_id.to_string()],
   1553             )
   1554             .map_err(|source| AppSqliteError::Query {
   1555                 operation: "replace local interop active order agreement lines",
   1556                 source,
   1557             })?;
   1558         for (index, item) in source.items.iter().enumerate() {
   1559             let economics_item = source
   1560                 .economics
   1561                 .items
   1562                 .iter()
   1563                 .find(|candidate| candidate.bin_id == item.bin_id);
   1564             let unit_label = economics_item
   1565                 .map(|item| item.quantity_unit.to_string())
   1566                 .or_else(|| {
   1567                     existing_listing
   1568                         .as_ref()
   1569                         .map(|listing| listing.unit_label.clone())
   1570                 })
   1571                 .unwrap_or_else(|| "item".to_owned());
   1572             let unit_price_minor_units = economics_item.and_then(|item| {
   1573                 parse_decimal_minor_units(item.unit_price_amount.to_string().as_str())
   1574             });
   1575             let price_currency = economics_item
   1576                 .map(|item| item.unit_price_currency.to_string())
   1577                 .unwrap_or_else(|| source.economics.currency.to_string());
   1578             let title = existing_listing
   1579                 .as_ref()
   1580                 .filter(|listing| {
   1581                     listing
   1582                         .listing_bin_id
   1583                         .as_deref()
   1584                         .is_none_or(|listing_bin_id| listing_bin_id == item.bin_id)
   1585                 })
   1586                 .map(|listing| listing.title.clone())
   1587                 .unwrap_or_else(|| item.bin_id.to_string());
   1588             self.connection
   1589                 .execute(
   1590                     "INSERT INTO order_lines (
   1591                         id,
   1592                         order_id,
   1593                         title,
   1594                         quantity_value,
   1595                         quantity_unit_label,
   1596                         quantity_display,
   1597                         listing_bin_id,
   1598                         unit_price_minor_units,
   1599                         price_currency,
   1600                         farm_key,
   1601                         listing_addr,
   1602                         listing_event_id,
   1603                         listing_relays_json,
   1604                         seller_pubkey,
   1605                         sort_index
   1606                      ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)",
   1607                     params![
   1608                         format!(
   1609                             "{}:{}",
   1610                             order_id,
   1611                             order_agreement_line_product_id(
   1612                                 source.listing_addr.as_str(),
   1613                                 source.seller_pubkey.as_str(),
   1614                                 existing_listing.as_ref(),
   1615                                 item,
   1616                             )
   1617                         ),
   1618                         order_id.to_string(),
   1619                         title.as_str(),
   1620                         i64::from(item.bin_count),
   1621                         unit_label.as_str(),
   1622                         format_quantity_display(item.bin_count, unit_label.as_str()),
   1623                         item.bin_id.as_str(),
   1624                         unit_price_minor_units,
   1625                         price_currency.as_str(),
   1626                         existing_listing
   1627                             .as_ref()
   1628                             .and_then(|listing| listing.farm_key.as_deref()),
   1629                         source.listing_addr.as_str(),
   1630                         metadata
   1631                             .as_ref()
   1632                             .and_then(|metadata| metadata.listing_event_id.as_deref()),
   1633                         metadata
   1634                             .as_ref()
   1635                             .and_then(|metadata| metadata.listing_relays_json.as_deref()),
   1636                         source.seller_pubkey.as_str(),
   1637                         index as i64,
   1638                     ],
   1639                 )
   1640                 .map_err(|source| AppSqliteError::Query {
   1641                     operation: "insert local interop active order agreement line",
   1642                     source,
   1643                 })?;
   1644         }
   1645         Ok(())
   1646     }
   1647 
   1648     fn existing_order_line_metadata(
   1649         &self,
   1650         order_id: OrderId,
   1651     ) -> Result<Option<ExistingOrderLineMetadata>, AppSqliteError> {
   1652         self.connection
   1653             .query_row(
   1654                 "SELECT listing_event_id, listing_relays_json
   1655                  FROM order_lines
   1656                  WHERE order_id = ?1
   1657                  ORDER BY sort_index ASC, id ASC
   1658                  LIMIT 1",
   1659                 params![order_id.to_string()],
   1660                 |row| {
   1661                     Ok(ExistingOrderLineMetadata {
   1662                         listing_event_id: row.get::<_, Option<String>>(0)?,
   1663                         listing_relays_json: row.get::<_, Option<String>>(1)?,
   1664                     })
   1665                 },
   1666             )
   1667             .optional()
   1668             .map_err(|source| AppSqliteError::Query {
   1669                 operation: "load existing local interop order line metadata",
   1670                 source,
   1671             })
   1672     }
   1673 
   1674     fn upsert_farm_summary(&self, farm: &FarmSummary) -> Result<(), AppSqliteError> {
   1675         self.connection
   1676             .execute(
   1677                 "INSERT INTO farms (id, display_name, readiness, created_at, updated_at)
   1678                  VALUES (?1, ?2, ?3, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
   1679                  ON CONFLICT(id) DO UPDATE SET
   1680                     display_name = excluded.display_name,
   1681                     readiness = excluded.readiness,
   1682                     updated_at = excluded.updated_at",
   1683                 params![
   1684                     farm.farm_id.to_string(),
   1685                     farm.display_name.as_str(),
   1686                     farm_readiness_storage_key(farm.readiness),
   1687                 ],
   1688             )
   1689             .map_err(|source| AppSqliteError::Query {
   1690                 operation: "upsert local interop farm summary",
   1691                 source,
   1692             })?;
   1693         Ok(())
   1694     }
   1695 
   1696     fn upsert_local_work_farm_summary(&self, farm: &FarmSummary) -> Result<(), AppSqliteError> {
   1697         self.connection
   1698             .execute(
   1699                 "INSERT INTO farms (id, display_name, readiness, created_at, updated_at)
   1700                  VALUES (?1, ?2, ?3, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
   1701                  ON CONFLICT(id) DO UPDATE SET
   1702                     display_name = excluded.display_name,
   1703                     readiness = CASE
   1704                         WHEN farms.readiness = 'ready' AND excluded.readiness = 'incomplete'
   1705                         THEN farms.readiness
   1706                         ELSE excluded.readiness
   1707                     END,
   1708                     updated_at = excluded.updated_at",
   1709                 params![
   1710                     farm.farm_id.to_string(),
   1711                     farm.display_name.as_str(),
   1712                     farm_readiness_storage_key(farm.readiness),
   1713                 ],
   1714             )
   1715             .map_err(|source| AppSqliteError::Query {
   1716                 operation: "upsert local interop local work farm summary",
   1717                 source,
   1718             })?;
   1719         Ok(())
   1720     }
   1721 
   1722     fn mark_farm_buyer_visible(
   1723         &self,
   1724         farm_id: FarmId,
   1725         record: &LocalEventRecord,
   1726         method: FarmOrderMethod,
   1727     ) -> Result<(), AppSqliteError> {
   1728         self.connection
   1729             .execute(
   1730                 "UPDATE farms
   1731                  SET readiness = 'ready',
   1732                      updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
   1733                  WHERE id = ?1",
   1734                 [farm_id.to_string()],
   1735             )
   1736             .map_err(|source| AppSqliteError::Query {
   1737                 operation: "mark local interop farm buyer visible",
   1738                 source,
   1739             })?;
   1740         let Some(account_id) = record
   1741             .owner_account_id
   1742             .as_deref()
   1743             .map(str::trim)
   1744             .filter(|value| !value.is_empty())
   1745         else {
   1746             return Ok(());
   1747         };
   1748         let display_name = self
   1749             .load_farm_display_name(farm_id)?
   1750             .unwrap_or_else(|| "Local farm".to_owned());
   1751         self.connection
   1752             .execute(
   1753                 "INSERT INTO account_farm_setups (
   1754                     account_id,
   1755                     farm_name,
   1756                     location_or_service_area,
   1757                     pickup_enabled,
   1758                     delivery_enabled,
   1759                     shipping_enabled,
   1760                     saved_farm_id,
   1761                     saved_farm_display_name,
   1762                     saved_farm_readiness,
   1763                     updated_at
   1764                  ) VALUES (?1, ?2, '', ?3, ?4, ?5, ?6, ?2, 'ready', strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
   1765                  ON CONFLICT(account_id) DO UPDATE SET
   1766                     farm_name = CASE
   1767                         WHEN trim(account_farm_setups.farm_name) = '' THEN excluded.farm_name
   1768                         ELSE account_farm_setups.farm_name
   1769                     END,
   1770                     pickup_enabled = max(account_farm_setups.pickup_enabled, excluded.pickup_enabled),
   1771                     delivery_enabled = max(account_farm_setups.delivery_enabled, excluded.delivery_enabled),
   1772                     shipping_enabled = max(account_farm_setups.shipping_enabled, excluded.shipping_enabled),
   1773                     saved_farm_id = excluded.saved_farm_id,
   1774                     saved_farm_display_name = excluded.saved_farm_display_name,
   1775                     saved_farm_readiness = excluded.saved_farm_readiness,
   1776                     updated_at = excluded.updated_at",
   1777                 params![
   1778                     account_id,
   1779                     display_name.as_str(),
   1780                     i64::from(method == FarmOrderMethod::Pickup),
   1781                     i64::from(method == FarmOrderMethod::Delivery),
   1782                     i64::from(method == FarmOrderMethod::Shipping),
   1783                     farm_id.to_string(),
   1784                 ],
   1785             )
   1786             .map_err(|source| AppSqliteError::Query {
   1787                 operation: "upsert local interop buyer fulfillment method",
   1788                 source,
   1789             })?;
   1790         Ok(())
   1791     }
   1792 
   1793     fn ensure_farm_exists(&self, farm_id: FarmId) -> Result<(), AppSqliteError> {
   1794         let exists = self
   1795             .connection
   1796             .query_row(
   1797                 "SELECT EXISTS(SELECT 1 FROM farms WHERE id = ?1)",
   1798                 [farm_id.to_string()],
   1799                 |row| row.get::<_, bool>(0),
   1800             )
   1801             .map_err(|source| AppSqliteError::Query {
   1802                 operation: "check local interop farm existence",
   1803                 source,
   1804             })?;
   1805         if !exists {
   1806             self.upsert_farm_summary(&FarmSummary {
   1807                 farm_id,
   1808                 display_name: "Local farm".to_owned(),
   1809                 readiness: FarmReadiness::Incomplete,
   1810             })?;
   1811         }
   1812         Ok(())
   1813     }
   1814 
   1815     fn load_farm_display_name(&self, farm_id: FarmId) -> Result<Option<String>, AppSqliteError> {
   1816         self.connection
   1817             .query_row(
   1818                 "SELECT display_name FROM farms WHERE id = ?1 LIMIT 1",
   1819                 [farm_id.to_string()],
   1820                 |row| row.get::<_, String>(0),
   1821             )
   1822             .optional()
   1823             .map_err(|source| AppSqliteError::Query {
   1824                 operation: "load local interop farm display name",
   1825                 source,
   1826             })
   1827     }
   1828 
   1829     fn load_farm_readiness(
   1830         &self,
   1831         farm_id: FarmId,
   1832     ) -> Result<Option<FarmReadiness>, AppSqliteError> {
   1833         self.connection
   1834             .query_row(
   1835                 "SELECT readiness FROM farms WHERE id = ?1 LIMIT 1",
   1836                 [farm_id.to_string()],
   1837                 |row| row.get::<_, String>(0),
   1838             )
   1839             .optional()
   1840             .map_err(|source| AppSqliteError::Query {
   1841                 operation: "load local interop farm readiness",
   1842                 source,
   1843             })?
   1844             .map(|readiness| farm_readiness_from_storage_key(readiness.as_str()))
   1845             .transpose()
   1846     }
   1847 
   1848     fn ensure_signed_listing_availability_window(
   1849         &self,
   1850         farm_id: FarmId,
   1851         listing_key: &str,
   1852         content: Option<&Value>,
   1853         tags: Option<&Value>,
   1854         method: FarmOrderMethod,
   1855     ) -> Result<Option<FulfillmentWindowId>, AppSqliteError> {
   1856         let Some(window) = signed_listing_availability_window(content, tags) else {
   1857             return Ok(None);
   1858         };
   1859         let starts_at =
   1860             self.unix_epoch_to_utc_timestamp(window.start, "format listing availability start")?;
   1861         let ends_at =
   1862             self.unix_epoch_to_utc_timestamp(window.end, "format listing availability end")?;
   1863         if ends_at <= starts_at {
   1864             return Ok(None);
   1865         }
   1866         let pickup_location_id = if method == FarmOrderMethod::Pickup {
   1867             let Some(location_primary) = signed_listing_location_primary(content, tags) else {
   1868                 return Ok(None);
   1869             };
   1870             Some(self.upsert_signed_listing_pickup_location(farm_id, location_primary.as_str())?)
   1871         } else {
   1872             None
   1873         };
   1874         let farm_id_string = farm_id.to_string();
   1875         let fulfillment_window_id = FulfillmentWindowId::from(deterministic_uuid(
   1876             "radroots-app-local-interop-fulfillment-window",
   1877             Some(farm_id_string.as_str()),
   1878             listing_key,
   1879         ));
   1880         self.connection
   1881             .execute(
   1882                 "INSERT INTO fulfillment_windows (
   1883                     id,
   1884                     farm_id,
   1885                     starts_at,
   1886                     ends_at,
   1887                     capacity_limit,
   1888                     created_at,
   1889                     updated_at,
   1890                     pickup_location_id,
   1891                     label,
   1892                     order_cutoff_at
   1893                  ) VALUES (?1, ?2, ?3, ?4, null, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), ?5, '', ?3)
   1894                  ON CONFLICT(id) DO UPDATE SET
   1895                     farm_id = excluded.farm_id,
   1896                     starts_at = excluded.starts_at,
   1897                     ends_at = excluded.ends_at,
   1898                     pickup_location_id = excluded.pickup_location_id,
   1899                     order_cutoff_at = excluded.order_cutoff_at,
   1900                     updated_at = excluded.updated_at",
   1901                 params![
   1902                     fulfillment_window_id.to_string(),
   1903                     farm_id_string.as_str(),
   1904                     starts_at.as_str(),
   1905                     ends_at.as_str(),
   1906                     pickup_location_id.map(|id| id.to_string()),
   1907                 ],
   1908             )
   1909             .map_err(|source| AppSqliteError::Query {
   1910                 operation: "upsert local interop listing fulfillment window",
   1911                 source,
   1912             })?;
   1913         Ok(Some(fulfillment_window_id))
   1914     }
   1915 
   1916     fn upsert_signed_listing_pickup_location(
   1917         &self,
   1918         farm_id: FarmId,
   1919         location_primary: &str,
   1920     ) -> Result<PickupLocationId, AppSqliteError> {
   1921         let farm_id_string = farm_id.to_string();
   1922         let pickup_location_id = PickupLocationId::from(deterministic_uuid(
   1923             "radroots-app-local-interop-pickup-location",
   1924             Some(farm_id_string.as_str()),
   1925             location_primary,
   1926         ));
   1927         self.connection
   1928             .execute(
   1929                 "INSERT INTO pickup_locations (
   1930                     id,
   1931                     farm_id,
   1932                     label,
   1933                     address_line,
   1934                     directions,
   1935                     is_default,
   1936                     created_at,
   1937                     updated_at
   1938                  ) VALUES (?1, ?2, ?3, ?3, null, 0, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
   1939                  ON CONFLICT(id) DO UPDATE SET
   1940                     farm_id = excluded.farm_id,
   1941                     label = excluded.label,
   1942                     address_line = excluded.address_line,
   1943                     updated_at = excluded.updated_at",
   1944                 params![
   1945                     pickup_location_id.to_string(),
   1946                     farm_id_string.as_str(),
   1947                     location_primary,
   1948                 ],
   1949             )
   1950             .map_err(|source| AppSqliteError::Query {
   1951                 operation: "upsert local interop listing pickup location",
   1952                 source,
   1953             })?;
   1954         Ok(pickup_location_id)
   1955     }
   1956 
   1957     fn unix_epoch_to_utc_timestamp(
   1958         &self,
   1959         seconds: u64,
   1960         operation: &'static str,
   1961     ) -> Result<String, AppSqliteError> {
   1962         let seconds = i64::try_from(seconds).map_err(|_| AppSqliteError::InvalidProjection {
   1963             reason: "listing availability timestamp is out of range",
   1964         })?;
   1965         let timestamp = self
   1966             .connection
   1967             .query_row(
   1968                 "SELECT strftime('%Y-%m-%dT%H:%M:%SZ', ?1, 'unixepoch')",
   1969                 [seconds],
   1970                 |row| row.get::<_, Option<String>>(0),
   1971             )
   1972             .map_err(|source| AppSqliteError::Query { operation, source })?;
   1973         timestamp.ok_or(AppSqliteError::InvalidProjection {
   1974             reason: "listing availability timestamp is invalid",
   1975         })
   1976     }
   1977 
   1978     fn upsert_product(&self, projection: ProductProjection) -> Result<(), AppSqliteError> {
   1979         self.connection
   1980             .execute(
   1981                 "INSERT INTO products (
   1982                     id,
   1983                     farm_id,
   1984                     title,
   1985                     subtitle,
   1986                     status,
   1987                     unit_label,
   1988                     price_minor_units,
   1989                     price_currency,
   1990                     stock_count,
   1991                     availability_window_id,
   1992                     listing_bin_id,
   1993                     updated_at
   1994                  ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
   1995                  ON CONFLICT(id) DO UPDATE SET
   1996                     farm_id = excluded.farm_id,
   1997                     title = excluded.title,
   1998                     subtitle = excluded.subtitle,
   1999                     status = CASE
   2000                         WHEN excluded.status = 'draft'
   2001                             AND products.status IN ('published', 'paused', 'archived')
   2002                         THEN products.status
   2003                         ELSE excluded.status
   2004                     END,
   2005                     unit_label = excluded.unit_label,
   2006                     price_minor_units = excluded.price_minor_units,
   2007                     price_currency = excluded.price_currency,
   2008                     stock_count = excluded.stock_count,
   2009                     availability_window_id = CASE
   2010                         WHEN excluded.status = 'draft'
   2011                             AND products.status IN ('published', 'paused', 'archived')
   2012                         THEN products.availability_window_id
   2013                         ELSE excluded.availability_window_id
   2014                     END,
   2015                     listing_bin_id = coalesce(excluded.listing_bin_id, products.listing_bin_id),
   2016                     updated_at = excluded.updated_at",
   2017                 params![
   2018                     projection.product_id.to_string(),
   2019                     projection.farm_id.to_string(),
   2020                     projection.title.as_str(),
   2021                     projection.subtitle.as_str(),
   2022                     projection.status.storage_key(),
   2023                     projection.unit_label.as_str(),
   2024                     projection.price_minor_units,
   2025                     projection.price_currency.as_str(),
   2026                     projection.stock_count,
   2027                     projection.availability_window_id.map(|id| id.to_string()),
   2028                     projection.listing_bin_id.as_deref(),
   2029                 ],
   2030             )
   2031             .map_err(|source| AppSqliteError::Query {
   2032                 operation: "upsert local interop product",
   2033                 source,
   2034             })?;
   2035         Ok(())
   2036     }
   2037 
   2038     fn existing_listing_projection(
   2039         &self,
   2040         listing_addr: Option<&str>,
   2041     ) -> Result<Option<ExistingListingProjection>, AppSqliteError> {
   2042         let Some(listing_addr) = listing_addr
   2043             .map(str::trim)
   2044             .filter(|listing_addr| !listing_addr.is_empty())
   2045         else {
   2046             return Ok(None);
   2047         };
   2048         let Some((product_id, farm_id, title, unit_label, listing_bin_id, farm_key)) = self
   2049             .connection
   2050             .query_row(
   2051                 "SELECT
   2052                     products.id,
   2053                     products.farm_id,
   2054                     products.title,
   2055                     products.unit_label,
   2056                     products.listing_bin_id,
   2057                     local_interop_imports.farm_key
   2058                  FROM local_interop_imports
   2059                  JOIN products ON products.id = local_interop_imports.projected_id
   2060                  WHERE local_interop_imports.projected_kind = 'listing'
   2061                     AND local_interop_imports.projected_id IS NOT NULL
   2062                     AND local_interop_imports.listing_addr = ?1
   2063                  ORDER BY local_interop_imports.local_seq DESC
   2064                  LIMIT 1",
   2065                 [listing_addr],
   2066                 |row| {
   2067                     Ok((
   2068                         row.get::<_, String>(0)?,
   2069                         row.get::<_, String>(1)?,
   2070                         row.get::<_, String>(2)?,
   2071                         row.get::<_, String>(3)?,
   2072                         row.get::<_, Option<String>>(4)?,
   2073                         row.get::<_, Option<String>>(5)?,
   2074                     ))
   2075                 },
   2076             )
   2077             .optional()
   2078             .map_err(|source| AppSqliteError::Query {
   2079                 operation: "load existing local interop listing projection",
   2080                 source,
   2081             })?
   2082         else {
   2083             return Ok(None);
   2084         };
   2085         Ok(Some(ExistingListingProjection {
   2086             product_id: product_id
   2087                 .parse()
   2088                 .map_err(|_| AppSqliteError::InvalidProjection {
   2089                     reason: "existing listing projection product id must parse",
   2090                 })?,
   2091             farm_id: farm_id
   2092                 .parse()
   2093                 .map_err(|_| AppSqliteError::InvalidProjection {
   2094                     reason: "existing listing projection farm id must parse",
   2095                 })?,
   2096             title,
   2097             unit_label,
   2098             listing_bin_id,
   2099             farm_key,
   2100         }))
   2101     }
   2102 
   2103     fn existing_app_origin_listing_projection(
   2104         &self,
   2105         record: &LocalEventRecord,
   2106         farm_key: &str,
   2107         listing_key: &str,
   2108         listing_pubkey: Option<&str>,
   2109         tags: Option<&Value>,
   2110     ) -> Result<Option<ExistingListingProjection>, AppSqliteError> {
   2111         if record.source_runtime != SourceRuntime::Network {
   2112             return Ok(None);
   2113         }
   2114         let Some(farm_id) = parse_app_d_tag_uuid(farm_key).map(FarmId::from) else {
   2115             return Ok(None);
   2116         };
   2117         let Some(product_id) = parse_app_d_tag_uuid(listing_key).map(ProductId::from) else {
   2118             return Ok(None);
   2119         };
   2120         let Some(listing_addr) = record
   2121             .listing_addr
   2122             .as_deref()
   2123             .map(str::trim)
   2124             .filter(|listing_addr| !listing_addr.is_empty())
   2125         else {
   2126             return Ok(None);
   2127         };
   2128         let Some(listing_addr_parts) = listing_address_parts(listing_addr) else {
   2129             return Ok(None);
   2130         };
   2131         let Some(event_pubkey) = record
   2132             .event_pubkey
   2133             .as_deref()
   2134             .map(str::trim)
   2135             .filter(|event_pubkey| !event_pubkey.is_empty())
   2136         else {
   2137             return Ok(None);
   2138         };
   2139         if listing_addr_parts.kind != KIND_LISTING
   2140             || listing_addr_parts.pubkey != event_pubkey
   2141             || listing_addr_parts.d_tag != listing_key
   2142             || listing_pubkey.map(str::trim) != Some(event_pubkey)
   2143             || !signed_farm_address_matches(tags, farm_key, event_pubkey)
   2144         {
   2145             return Ok(None);
   2146         }
   2147         let Some((product_id, farm_id, title, unit_label, listing_bin_id, evidence_farm_key)) =
   2148             self.connection
   2149                 .query_row(
   2150                     "SELECT
   2151                     products.id,
   2152                     products.farm_id,
   2153                     products.title,
   2154                     products.unit_label,
   2155                     products.listing_bin_id,
   2156                     local_interop_imports.farm_key
   2157                  FROM local_interop_imports
   2158                  JOIN products ON products.id = local_interop_imports.projected_id
   2159                  WHERE local_interop_imports.projected_kind = 'listing'
   2160                     AND local_interop_imports.projected_id = ?1
   2161                     AND local_interop_imports.source_runtime = 'app'
   2162                     AND local_interop_imports.farm_key = ?2
   2163                     AND local_interop_imports.listing_addr = ?3
   2164                     AND local_interop_imports.owner_pubkey = ?4
   2165                     AND products.id = ?1
   2166                     AND products.farm_id = ?5
   2167                  LIMIT 1",
   2168                     params![
   2169                         product_id.to_string(),
   2170                         farm_key,
   2171                         listing_addr,
   2172                         event_pubkey,
   2173                         farm_id.to_string(),
   2174                     ],
   2175                     |row| {
   2176                         Ok((
   2177                             row.get::<_, String>(0)?,
   2178                             row.get::<_, String>(1)?,
   2179                             row.get::<_, String>(2)?,
   2180                             row.get::<_, String>(3)?,
   2181                             row.get::<_, Option<String>>(4)?,
   2182                             row.get::<_, Option<String>>(5)?,
   2183                         ))
   2184                     },
   2185                 )
   2186                 .optional()
   2187                 .map_err(|source| AppSqliteError::Query {
   2188                     operation: "load existing app-origin listing projection",
   2189                     source,
   2190                 })?
   2191         else {
   2192             return Ok(None);
   2193         };
   2194         Ok(Some(ExistingListingProjection {
   2195             product_id: product_id
   2196                 .parse()
   2197                 .map_err(|_| AppSqliteError::InvalidProjection {
   2198                     reason: "existing app-origin listing projection product id must parse",
   2199                 })?,
   2200             farm_id: farm_id
   2201                 .parse()
   2202                 .map_err(|_| AppSqliteError::InvalidProjection {
   2203                     reason: "existing app-origin listing projection farm id must parse",
   2204                 })?,
   2205             title,
   2206             unit_label,
   2207             listing_bin_id,
   2208             farm_key: evidence_farm_key,
   2209         }))
   2210     }
   2211 
   2212     fn signed_listing_is_current(
   2213         &self,
   2214         record: &LocalEventRecord,
   2215         listing_key: &str,
   2216     ) -> Result<bool, AppSqliteError> {
   2217         if !signed_listing_has_public_evidence(record) {
   2218             return Ok(true);
   2219         }
   2220         let Some(incoming_key) = listing_currentness_key(
   2221             record.event_created_at,
   2222             record.event_id.as_deref(),
   2223             signed_event_evidence_precedence(
   2224                 record.source_runtime.as_str(),
   2225                 record.owner_account_id.as_deref(),
   2226                 record.status.as_str(),
   2227                 record.outbox_status.as_str(),
   2228             ),
   2229         ) else {
   2230             return Ok(true);
   2231         };
   2232         let Some(identity) = ListingCurrentnessIdentity::from_record(record, listing_key) else {
   2233             return Ok(true);
   2234         };
   2235         let Some(current_key) = self.current_listing_key(&identity)? else {
   2236             return Ok(true);
   2237         };
   2238         Ok(incoming_key >= current_key)
   2239     }
   2240 
   2241     fn current_listing_key(
   2242         &self,
   2243         identity: &ListingCurrentnessIdentity,
   2244     ) -> Result<Option<ListingCurrentnessKey>, AppSqliteError> {
   2245         let mut keys = Vec::new();
   2246         match identity {
   2247             ListingCurrentnessIdentity::ListingAddress(listing_addr) => {
   2248                 let mut statement = self
   2249                     .connection
   2250                     .prepare(
   2251                         "SELECT
   2252                             event_id,
   2253                             event_created_at,
   2254                             source_runtime,
   2255                             owner_account_id,
   2256                             local_status,
   2257                             outbox_status,
   2258                             relay_delivery_json
   2259                          FROM local_interop_imports
   2260                          WHERE record_family = 'signed_event'
   2261                             AND projected_kind = 'listing'
   2262                             AND listing_addr = ?1",
   2263                     )
   2264                     .map_err(|source| AppSqliteError::Query {
   2265                         operation: "prepare current listing-address evidence query",
   2266                         source,
   2267                     })?;
   2268                 let rows = statement
   2269                     .query_map(params![listing_addr.as_str()], listing_currentness_row)
   2270                     .map_err(|source| AppSqliteError::Query {
   2271                         operation: "query current listing-address evidence",
   2272                         source,
   2273                     })?;
   2274                 for row in rows {
   2275                     let evidence = row.map_err(|source| AppSqliteError::Query {
   2276                         operation: "read current listing-address evidence",
   2277                         source,
   2278                     })?;
   2279                     if let Some(key) = evidence.into_currentness_key() {
   2280                         keys.push(key);
   2281                     }
   2282                 }
   2283             }
   2284             ListingCurrentnessIdentity::KindPubkeyDTag {
   2285                 event_kind,
   2286                 event_pubkey,
   2287                 listing_key,
   2288             } => {
   2289                 let mut statement = self
   2290                     .connection
   2291                     .prepare(
   2292                         "SELECT
   2293                             event_id,
   2294                             event_created_at,
   2295                             source_runtime,
   2296                             owner_account_id,
   2297                             local_status,
   2298                             outbox_status,
   2299                             relay_delivery_json,
   2300                             event_tags_json,
   2301                             event_content,
   2302                             listing_addr
   2303                          FROM local_interop_imports
   2304                          WHERE record_family = 'signed_event'
   2305                             AND projected_kind = 'listing'
   2306                             AND event_kind = ?1
   2307                             AND event_pubkey = ?2",
   2308                     )
   2309                     .map_err(|source| AppSqliteError::Query {
   2310                         operation: "prepare current listing identity evidence query",
   2311                         source,
   2312                     })?;
   2313                 let rows = statement
   2314                     .query_map(
   2315                         params![event_kind, event_pubkey.as_str()],
   2316                         listing_currentness_identity_row,
   2317                     )
   2318                     .map_err(|source| AppSqliteError::Query {
   2319                         operation: "query current listing identity evidence",
   2320                         source,
   2321                     })?;
   2322                 for row in rows {
   2323                     let evidence = row.map_err(|source| AppSqliteError::Query {
   2324                         operation: "read current listing identity evidence",
   2325                         source,
   2326                     })?;
   2327                     if evidence.listing_key().as_deref() == Some(listing_key.as_str())
   2328                         && let Some(key) = evidence.currentness.into_currentness_key()
   2329                     {
   2330                         keys.push(key);
   2331                     }
   2332                 }
   2333             }
   2334         }
   2335         Ok(keys.into_iter().max())
   2336     }
   2337 
   2338     fn record_import(
   2339         &self,
   2340         record: &LocalEventRecord,
   2341         projected_kind: &str,
   2342         projected_id: Option<String>,
   2343     ) -> Result<(), AppSqliteError> {
   2344         let event_tags_json = record
   2345             .event_tags_json
   2346             .as_ref()
   2347             .map(serde_json::to_string)
   2348             .transpose()
   2349             .map_err(|_| AppSqliteError::InvalidProjection {
   2350                 reason: "local interop event tags json must encode",
   2351             })?;
   2352         let raw_event_json = record
   2353             .raw_event_json
   2354             .as_ref()
   2355             .map(serde_json::to_string)
   2356             .transpose()
   2357             .map_err(|_| AppSqliteError::InvalidProjection {
   2358                 reason: "local interop raw event json must encode",
   2359             })?;
   2360         let relay_delivery_json = record
   2361             .relay_delivery_json
   2362             .as_ref()
   2363             .map(serde_json::to_string)
   2364             .transpose()
   2365             .map_err(|_| AppSqliteError::InvalidProjection {
   2366                 reason: "local interop relay delivery json must encode",
   2367             })?;
   2368         self.connection
   2369             .execute(
   2370                 "INSERT INTO local_interop_imports (
   2371                     record_id,
   2372                     local_seq,
   2373                     record_family,
   2374                     local_status,
   2375                     source_runtime,
   2376                     owner_account_id,
   2377                     owner_pubkey,
   2378                     farm_key,
   2379                     listing_addr,
   2380                     projected_kind,
   2381                     projected_id,
   2382                     event_id,
   2383                     event_kind,
   2384                     event_pubkey,
   2385                     event_created_at,
   2386                     event_tags_json,
   2387                     event_content,
   2388                     event_sig,
   2389                     raw_event_json,
   2390                     outbox_status,
   2391                     relay_delivery_json,
   2392                     imported_at
   2393                  ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
   2394                  ON CONFLICT(record_id) DO UPDATE SET
   2395                     local_seq = excluded.local_seq,
   2396                     record_family = excluded.record_family,
   2397                     local_status = excluded.local_status,
   2398                     source_runtime = excluded.source_runtime,
   2399                     owner_account_id = excluded.owner_account_id,
   2400                     owner_pubkey = excluded.owner_pubkey,
   2401                     farm_key = excluded.farm_key,
   2402                     listing_addr = excluded.listing_addr,
   2403                     projected_kind = excluded.projected_kind,
   2404                     projected_id = excluded.projected_id,
   2405                     event_id = excluded.event_id,
   2406                     event_kind = excluded.event_kind,
   2407                     event_pubkey = excluded.event_pubkey,
   2408                     event_created_at = excluded.event_created_at,
   2409                     event_tags_json = excluded.event_tags_json,
   2410                     event_content = excluded.event_content,
   2411                     event_sig = excluded.event_sig,
   2412                     raw_event_json = excluded.raw_event_json,
   2413                     outbox_status = excluded.outbox_status,
   2414                     relay_delivery_json = excluded.relay_delivery_json,
   2415                     imported_at = excluded.imported_at",
   2416                 params![
   2417                     record.record_id.as_str(),
   2418                     record.seq,
   2419                     record.family.as_str(),
   2420                     record.status.as_str(),
   2421                     record.source_runtime.as_str(),
   2422                     record.owner_account_id.as_deref(),
   2423                     record.owner_pubkey.as_deref(),
   2424                     record.farm_id.as_deref(),
   2425                     record.listing_addr.as_deref(),
   2426                     projected_kind,
   2427                     projected_id.as_deref(),
   2428                     record.event_id.as_deref(),
   2429                     record.event_kind,
   2430                     record.event_pubkey.as_deref(),
   2431                     record.event_created_at,
   2432                     event_tags_json.as_deref(),
   2433                     record.event_content.as_deref(),
   2434                     record.event_sig.as_deref(),
   2435                     raw_event_json.as_deref(),
   2436                     record.outbox_status.as_str(),
   2437                     relay_delivery_json.as_deref(),
   2438                 ],
   2439             )
   2440             .map_err(|source| AppSqliteError::Query {
   2441                 operation: "record local interop import",
   2442                 source,
   2443             })?;
   2444         Ok(())
   2445     }
   2446 }
   2447 
   2448 impl AppSqliteStore {
   2449     pub fn local_interop_repository(&self) -> AppLocalInteropRepository<'_> {
   2450         AppLocalInteropRepository::new(&self.connection)
   2451     }
   2452 
   2453     pub fn import_shared_local_events_from_path(
   2454         &self,
   2455         shared_database_path: &Path,
   2456     ) -> Result<AppLocalInteropImportReport, AppSqliteError> {
   2457         self.local_interop_repository()
   2458             .import_from_path(shared_database_path)
   2459     }
   2460 
   2461     pub fn import_shared_local_events_from_store<E>(
   2462         &self,
   2463         store: &LocalEventsStore<E>,
   2464     ) -> Result<AppLocalInteropImportReport, AppSqliteError>
   2465     where
   2466         E: SqlExecutor,
   2467     {
   2468         self.local_interop_repository().import_from_store(store)
   2469     }
   2470 
   2471     pub fn import_local_event_records(
   2472         &self,
   2473         records: &[LocalEventRecord],
   2474     ) -> Result<AppLocalInteropImportReport, AppSqliteError> {
   2475         self.local_interop_repository().import_records(records)
   2476     }
   2477 
   2478     pub fn load_local_interop_records(
   2479         &self,
   2480     ) -> Result<Vec<StoredLocalInteropRecord>, AppSqliteError> {
   2481         self.local_interop_repository().load_records()
   2482     }
   2483 
   2484     pub fn load_local_interop_signed_events_by_kind(
   2485         &self,
   2486         event_kind: i64,
   2487     ) -> Result<Vec<RadrootsNostrEvent>, AppSqliteError> {
   2488         self.local_interop_repository()
   2489             .load_signed_events_by_kind(event_kind)
   2490     }
   2491 }
   2492 
   2493 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
   2494 enum ImportOutcome {
   2495     Imported,
   2496     Skipped,
   2497 }
   2498 
   2499 #[derive(Clone, Debug, Eq, PartialEq)]
   2500 enum DuplicateSignedEventAction {
   2501     Import,
   2502     ReplaceExisting(String),
   2503     Skip,
   2504 }
   2505 
   2506 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
   2507 enum ValidationReceiptOrderAttachment {
   2508     Pending,
   2509     Attached(OrderId),
   2510     Rejected,
   2511 }
   2512 
   2513 #[derive(Clone, Debug, Eq, PartialEq)]
   2514 struct ProjectionRecord {
   2515     kind: &'static str,
   2516     projected_id: Option<String>,
   2517 }
   2518 
   2519 #[derive(Clone, Debug, Eq, PartialEq)]
   2520 struct StoredSignedEventDuplicate {
   2521     source_runtime: String,
   2522     owner_account_id: Option<String>,
   2523     local_status: String,
   2524     outbox_status: String,
   2525 }
   2526 
   2527 #[derive(Clone, Debug, Eq, PartialEq)]
   2528 struct StoredLocalInteropSignedEventEvidence {
   2529     event_id: Option<String>,
   2530     event_kind: Option<i64>,
   2531     local_status: String,
   2532     outbox_status: String,
   2533     relay_delivery_json: Option<String>,
   2534     event_pubkey: Option<String>,
   2535     event_created_at: Option<i64>,
   2536     event_tags_json: Option<String>,
   2537     event_content: Option<String>,
   2538     event_sig: Option<String>,
   2539 }
   2540 
   2541 #[derive(Clone, Debug, Eq, PartialEq)]
   2542 struct StoredListingCurrentnessEvidence {
   2543     event_id: Option<String>,
   2544     event_created_at: Option<i64>,
   2545     source_runtime: String,
   2546     owner_account_id: Option<String>,
   2547     local_status: String,
   2548     outbox_status: String,
   2549     relay_delivery_json: Option<String>,
   2550 }
   2551 
   2552 impl StoredListingCurrentnessEvidence {
   2553     fn into_currentness_key(self) -> Option<ListingCurrentnessKey> {
   2554         if !signed_event_import_has_public_evidence(
   2555             self.local_status.as_str(),
   2556             self.outbox_status.as_str(),
   2557             self.relay_delivery_json.as_deref(),
   2558         ) {
   2559             return None;
   2560         }
   2561         listing_currentness_key(
   2562             self.event_created_at,
   2563             self.event_id.as_deref(),
   2564             signed_event_evidence_precedence(
   2565                 self.source_runtime.as_str(),
   2566                 self.owner_account_id.as_deref(),
   2567                 self.local_status.as_str(),
   2568                 self.outbox_status.as_str(),
   2569             ),
   2570         )
   2571     }
   2572 }
   2573 
   2574 #[derive(Clone, Debug, Eq, PartialEq)]
   2575 struct StoredListingCurrentnessIdentityEvidence {
   2576     currentness: StoredListingCurrentnessEvidence,
   2577     event_tags_json: Option<String>,
   2578     event_content: Option<String>,
   2579     listing_addr: Option<String>,
   2580 }
   2581 
   2582 impl StoredListingCurrentnessIdentityEvidence {
   2583     fn listing_key(&self) -> Option<String> {
   2584         self.event_content
   2585             .as_deref()
   2586             .and_then(parse_json_value_opt)
   2587             .and_then(|content| string_at(&content, &["d_tag"]))
   2588             .or_else(|| {
   2589                 self.event_tags_json
   2590                     .as_deref()
   2591                     .and_then(|raw| serde_json::from_str::<Value>(raw).ok())
   2592                     .and_then(|tags| tag_index_value(Some(&tags), "d", 1))
   2593             })
   2594             .or_else(|| self.listing_addr.as_deref().and_then(address_d_tag))
   2595     }
   2596 }
   2597 
   2598 #[derive(Clone, Debug, Eq, PartialEq)]
   2599 enum ListingCurrentnessIdentity {
   2600     ListingAddress(String),
   2601     KindPubkeyDTag {
   2602         event_kind: i64,
   2603         event_pubkey: String,
   2604         listing_key: String,
   2605     },
   2606 }
   2607 
   2608 impl ListingCurrentnessIdentity {
   2609     fn from_record(record: &LocalEventRecord, listing_key: &str) -> Option<Self> {
   2610         if let Some(listing_addr) = record
   2611             .listing_addr
   2612             .as_deref()
   2613             .map(str::trim)
   2614             .filter(|listing_addr| !listing_addr.is_empty())
   2615         {
   2616             return Some(Self::ListingAddress(listing_addr.to_owned()));
   2617         }
   2618         let event_kind = record.event_kind?;
   2619         let event_pubkey = record
   2620             .event_pubkey
   2621             .as_deref()
   2622             .map(str::trim)
   2623             .filter(|event_pubkey| !event_pubkey.is_empty())?;
   2624         Some(Self::KindPubkeyDTag {
   2625             event_kind,
   2626             event_pubkey: event_pubkey.to_owned(),
   2627             listing_key: listing_key.to_owned(),
   2628         })
   2629     }
   2630 }
   2631 
   2632 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
   2633 struct ListingCurrentnessKey {
   2634     event_created_at: i64,
   2635     evidence_precedence: u8,
   2636     event_id: String,
   2637 }
   2638 
   2639 #[derive(Clone, Debug, Eq, PartialEq)]
   2640 struct ProductProjection {
   2641     product_id: ProductId,
   2642     farm_id: FarmId,
   2643     title: String,
   2644     subtitle: String,
   2645     status: ProductStatus,
   2646     unit_label: String,
   2647     price_minor_units: Option<u32>,
   2648     price_currency: String,
   2649     stock_count: Option<u32>,
   2650     availability_window_id: Option<FulfillmentWindowId>,
   2651     listing_bin_id: Option<String>,
   2652 }
   2653 
   2654 #[derive(Clone, Debug, Eq, PartialEq)]
   2655 struct ExistingListingProjection {
   2656     product_id: ProductId,
   2657     farm_id: FarmId,
   2658     title: String,
   2659     unit_label: String,
   2660     listing_bin_id: Option<String>,
   2661     farm_key: Option<String>,
   2662 }
   2663 
   2664 #[derive(Clone, Debug, Eq, PartialEq)]
   2665 struct ActiveOrderAgreementSource {
   2666     listing_addr: String,
   2667     seller_pubkey: String,
   2668     items: Vec<RadrootsOrderItem>,
   2669     economics: RadrootsOrderEconomics,
   2670 }
   2671 
   2672 #[derive(Clone, Debug, Eq, PartialEq)]
   2673 struct ExistingOrderLineMetadata {
   2674     listing_event_id: Option<String>,
   2675     listing_relays_json: Option<String>,
   2676 }
   2677 
   2678 #[derive(Clone, Debug, Eq, PartialEq)]
   2679 enum ActiveOrderEvidence {
   2680     Request(RadrootsOrderRequestRecord),
   2681     Decision(RadrootsOrderDecisionRecord),
   2682     RevisionProposal(RadrootsOrderRevisionProposalRecord),
   2683     RevisionDecision(RadrootsOrderRevisionDecisionRecord),
   2684     Cancellation(RadrootsOrderCancellationRecord),
   2685 }
   2686 
   2687 impl ActiveOrderEvidence {
   2688     fn event_id(&self) -> &str {
   2689         match self {
   2690             Self::Request(record) => record.event_id.as_str(),
   2691             Self::Decision(record) => record.event_id.as_str(),
   2692             Self::RevisionProposal(record) => record.event_id.as_str(),
   2693             Self::RevisionDecision(record) => record.event_id.as_str(),
   2694             Self::Cancellation(record) => record.event_id.as_str(),
   2695         }
   2696     }
   2697 
   2698     fn order_id(&self) -> &str {
   2699         match self {
   2700             Self::Request(record) => record.payload.order_id.as_str(),
   2701             Self::Decision(record) => record.payload.order_id.as_str(),
   2702             Self::RevisionProposal(record) => record.payload.order_id.as_str(),
   2703             Self::RevisionDecision(record) => record.payload.order_id.as_str(),
   2704             Self::Cancellation(record) => record.payload.order_id.as_str(),
   2705         }
   2706     }
   2707 
   2708     fn order_projection_identity(&self) -> (&str, &str) {
   2709         match self {
   2710             Self::Request(record) => (
   2711                 record.payload.order_id.as_str(),
   2712                 record.payload.buyer_pubkey.as_str(),
   2713             ),
   2714             Self::Decision(record) => (
   2715                 record.payload.order_id.as_str(),
   2716                 record.payload.buyer_pubkey.as_str(),
   2717             ),
   2718             Self::RevisionProposal(record) => (
   2719                 record.payload.order_id.as_str(),
   2720                 record.payload.buyer_pubkey.as_str(),
   2721             ),
   2722             Self::RevisionDecision(record) => (
   2723                 record.payload.order_id.as_str(),
   2724                 record.payload.buyer_pubkey.as_str(),
   2725             ),
   2726             Self::Cancellation(record) => (
   2727                 record.payload.order_id.as_str(),
   2728                 record.payload.buyer_pubkey.as_str(),
   2729             ),
   2730         }
   2731     }
   2732 }
   2733 
   2734 #[derive(Clone, Debug, Default, Eq, PartialEq)]
   2735 struct ActiveOrderEvidenceBuckets {
   2736     requests: Vec<RadrootsOrderRequestRecord>,
   2737     decisions: Vec<RadrootsOrderDecisionRecord>,
   2738     revision_proposals: Vec<RadrootsOrderRevisionProposalRecord>,
   2739     revision_decisions: Vec<RadrootsOrderRevisionDecisionRecord>,
   2740     cancellations: Vec<RadrootsOrderCancellationRecord>,
   2741 }
   2742 
   2743 impl ActiveOrderEvidenceBuckets {
   2744     fn from_evidence(evidence: Vec<ActiveOrderEvidence>) -> Self {
   2745         let mut buckets = Self::default();
   2746         for record in evidence {
   2747             match record {
   2748                 ActiveOrderEvidence::Request(record) => buckets.requests.push(record),
   2749                 ActiveOrderEvidence::Decision(record) => buckets.decisions.push(record),
   2750                 ActiveOrderEvidence::RevisionProposal(record) => {
   2751                     buckets.revision_proposals.push(record);
   2752                 }
   2753                 ActiveOrderEvidence::RevisionDecision(record) => {
   2754                     buckets.revision_decisions.push(record);
   2755                 }
   2756                 ActiveOrderEvidence::Cancellation(record) => buckets.cancellations.push(record),
   2757             }
   2758         }
   2759         buckets
   2760     }
   2761 }
   2762 
   2763 fn listing_currentness_row(
   2764     row: &rusqlite::Row<'_>,
   2765 ) -> rusqlite::Result<StoredListingCurrentnessEvidence> {
   2766     Ok(StoredListingCurrentnessEvidence {
   2767         event_id: row.get(0)?,
   2768         event_created_at: row.get(1)?,
   2769         source_runtime: row.get(2)?,
   2770         owner_account_id: row.get(3)?,
   2771         local_status: row.get(4)?,
   2772         outbox_status: row.get(5)?,
   2773         relay_delivery_json: row.get(6)?,
   2774     })
   2775 }
   2776 
   2777 fn listing_currentness_identity_row(
   2778     row: &rusqlite::Row<'_>,
   2779 ) -> rusqlite::Result<StoredListingCurrentnessIdentityEvidence> {
   2780     Ok(StoredListingCurrentnessIdentityEvidence {
   2781         currentness: StoredListingCurrentnessEvidence {
   2782             event_id: row.get(0)?,
   2783             event_created_at: row.get(1)?,
   2784             source_runtime: row.get(2)?,
   2785             owner_account_id: row.get(3)?,
   2786             local_status: row.get(4)?,
   2787             outbox_status: row.get(5)?,
   2788             relay_delivery_json: row.get(6)?,
   2789         },
   2790         event_tags_json: row.get(7)?,
   2791         event_content: row.get(8)?,
   2792         listing_addr: row.get(9)?,
   2793     })
   2794 }
   2795 
   2796 fn listing_currentness_key(
   2797     event_created_at: Option<i64>,
   2798     event_id: Option<&str>,
   2799     evidence_precedence: u8,
   2800 ) -> Option<ListingCurrentnessKey> {
   2801     Some(ListingCurrentnessKey {
   2802         event_created_at: event_created_at?,
   2803         evidence_precedence,
   2804         event_id: event_id
   2805             .map(str::trim)
   2806             .filter(|event_id| !event_id.is_empty())?
   2807             .to_owned(),
   2808     })
   2809 }
   2810 
   2811 fn signed_event_evidence_precedence(
   2812     source_runtime: &str,
   2813     owner_account_id: Option<&str>,
   2814     local_status: &str,
   2815     outbox_status: &str,
   2816 ) -> u8 {
   2817     let mut precedence = 0;
   2818     if local_status == LocalRecordStatus::Published.as_str() {
   2819         precedence += 1;
   2820     }
   2821     if outbox_status == PublishOutboxStatus::Acknowledged.as_str() {
   2822         precedence += 2;
   2823     }
   2824     if owner_account_id
   2825         .map(str::trim)
   2826         .is_some_and(|owner_account_id| !owner_account_id.is_empty())
   2827     {
   2828         precedence += 4;
   2829     }
   2830     if source_runtime == SourceRuntime::App.as_str() {
   2831         precedence += 8;
   2832     }
   2833     precedence
   2834 }
   2835 
   2836 fn deterministic_farm_id(owner_pubkey: Option<&str>, farm_key: &str) -> FarmId {
   2837     FarmId::from(deterministic_uuid(
   2838         "radroots-cli-farm",
   2839         owner_pubkey,
   2840         farm_key,
   2841     ))
   2842 }
   2843 
   2844 fn deterministic_product_id(owner_pubkey: Option<&str>, listing_key: &str) -> ProductId {
   2845     ProductId::from(deterministic_uuid(
   2846         "radroots-cli-listing",
   2847         owner_pubkey,
   2848         listing_key,
   2849     ))
   2850 }
   2851 
   2852 fn projected_farm_id(
   2853     source_runtime: SourceRuntime,
   2854     owner_pubkey: Option<&str>,
   2855     farm_key: &str,
   2856 ) -> Option<FarmId> {
   2857     match source_runtime {
   2858         SourceRuntime::App => parse_app_d_tag_uuid(farm_key).map(FarmId::from),
   2859         _ => Some(deterministic_farm_id(owner_pubkey, farm_key)),
   2860     }
   2861 }
   2862 
   2863 fn projected_product_id(
   2864     source_runtime: SourceRuntime,
   2865     owner_pubkey: Option<&str>,
   2866     listing_key: &str,
   2867 ) -> Option<ProductId> {
   2868     match source_runtime {
   2869         SourceRuntime::App => parse_app_d_tag_uuid(listing_key).map(ProductId::from),
   2870         _ => Some(deterministic_product_id(owner_pubkey, listing_key)),
   2871     }
   2872 }
   2873 
   2874 fn deterministic_uuid(scope: &str, owner_pubkey: Option<&str>, key: &str) -> Uuid {
   2875     let seed = format!(
   2876         "{scope}:{}:{}",
   2877         owner_pubkey.unwrap_or("unknown-owner"),
   2878         key.trim()
   2879     );
   2880     Uuid::new_v5(&Uuid::NAMESPACE_URL, seed.as_bytes())
   2881 }
   2882 
   2883 fn parse_app_d_tag_uuid(value: &str) -> Option<Uuid> {
   2884     let mut decoded = Vec::with_capacity(16);
   2885     let mut buffer = 0u32;
   2886     let mut bits = 0u8;
   2887     for byte in value.trim().bytes() {
   2888         let digit = base64_url_digit(byte)?;
   2889         buffer = (buffer << 6) | u32::from(digit);
   2890         bits += 6;
   2891         while bits >= 8 {
   2892             bits -= 8;
   2893             decoded.push(((buffer >> bits) & 0xff) as u8);
   2894             buffer &= (1u32 << bits) - 1;
   2895         }
   2896     }
   2897     if bits > 0 && buffer != 0 {
   2898         return None;
   2899     }
   2900     if decoded.len() == 16 {
   2901         Uuid::from_slice(decoded.as_slice()).ok()
   2902     } else {
   2903         None
   2904     }
   2905 }
   2906 
   2907 fn active_order_event_kind(kind: i64) -> bool {
   2908     ACTIVE_ORDER_EVENT_KINDS.contains(&kind)
   2909 }
   2910 
   2911 fn active_event_id(event: &RadrootsNostrEvent) -> Option<RadrootsEventId> {
   2912     event.id.parse().ok()
   2913 }
   2914 
   2915 fn active_author_pubkey(event: &RadrootsNostrEvent) -> Option<RadrootsPublicKey> {
   2916     event.author.parse().ok()
   2917 }
   2918 
   2919 fn active_order_evidence_from_event(event: &RadrootsNostrEvent) -> Option<ActiveOrderEvidence> {
   2920     match i64::from(event.kind) {
   2921         KIND_ORDER_REQUEST => {
   2922             let envelope = order_request_from_event(event).ok()?;
   2923             Some(ActiveOrderEvidence::Request(RadrootsOrderRequestRecord {
   2924                 event_id: active_event_id(event)?,
   2925                 author_pubkey: active_author_pubkey(event)?,
   2926                 payload: envelope.payload,
   2927             }))
   2928         }
   2929         KIND_ORDER_DECISION => {
   2930             let envelope = order_decision_from_event(event).ok()?;
   2931             let context = order_event_context_from_tags(envelope.message_type, &event.tags).ok()?;
   2932             Some(ActiveOrderEvidence::Decision(RadrootsOrderDecisionRecord {
   2933                 event_id: active_event_id(event)?,
   2934                 author_pubkey: active_author_pubkey(event)?,
   2935                 counterparty_pubkey: context.counterparty_pubkey,
   2936                 root_event_id: context.root_event_id?,
   2937                 prev_event_id: context.prev_event_id?,
   2938                 payload: envelope.payload,
   2939             }))
   2940         }
   2941         KIND_ORDER_REVISION => {
   2942             let envelope = order_revision_proposal_from_event(event).ok()?;
   2943             let context = order_event_context_from_tags(envelope.message_type, &event.tags).ok()?;
   2944             Some(ActiveOrderEvidence::RevisionProposal(
   2945                 RadrootsOrderRevisionProposalRecord {
   2946                     event_id: active_event_id(event)?,
   2947                     author_pubkey: active_author_pubkey(event)?,
   2948                     counterparty_pubkey: context.counterparty_pubkey,
   2949                     root_event_id: context.root_event_id?,
   2950                     prev_event_id: context.prev_event_id?,
   2951                     payload: envelope.payload,
   2952                 },
   2953             ))
   2954         }
   2955         KIND_ORDER_REVISION_DECISION => {
   2956             let envelope = order_revision_decision_from_event(event).ok()?;
   2957             let context = order_event_context_from_tags(envelope.message_type, &event.tags).ok()?;
   2958             Some(ActiveOrderEvidence::RevisionDecision(
   2959                 RadrootsOrderRevisionDecisionRecord {
   2960                     event_id: active_event_id(event)?,
   2961                     author_pubkey: active_author_pubkey(event)?,
   2962                     counterparty_pubkey: context.counterparty_pubkey,
   2963                     root_event_id: context.root_event_id?,
   2964                     prev_event_id: context.prev_event_id?,
   2965                     payload: envelope.payload,
   2966                 },
   2967             ))
   2968         }
   2969         KIND_ORDER_CANCEL => {
   2970             let envelope = order_cancellation_from_event(event).ok()?;
   2971             let context = order_event_context_from_tags(envelope.message_type, &event.tags).ok()?;
   2972             Some(ActiveOrderEvidence::Cancellation(
   2973                 RadrootsOrderCancellationRecord {
   2974                     event_id: active_event_id(event)?,
   2975                     author_pubkey: active_author_pubkey(event)?,
   2976                     counterparty_pubkey: context.counterparty_pubkey,
   2977                     root_event_id: context.root_event_id?,
   2978                     prev_event_id: context.prev_event_id?,
   2979                     payload: envelope.payload,
   2980                 },
   2981             ))
   2982         }
   2983         _ => None,
   2984     }
   2985 }
   2986 
   2987 fn dedupe_active_order_evidence(evidence: &mut Vec<ActiveOrderEvidence>) {
   2988     evidence.sort_by(|left, right| left.event_id().cmp(right.event_id()));
   2989     evidence.dedup_by(|left, right| left.event_id() == right.event_id());
   2990 }
   2991 
   2992 fn signed_event_projection(record: &LocalEventRecord) -> ProjectionRecord {
   2993     ProjectionRecord {
   2994         kind: "signed_event",
   2995         projected_id: record.event_id.clone(),
   2996     }
   2997 }
   2998 
   2999 fn signed_event_from_record(
   3000     record: &LocalEventRecord,
   3001 ) -> Result<Option<RadrootsNostrEvent>, AppSqliteError> {
   3002     let Some(id) = record
   3003         .event_id
   3004         .as_deref()
   3005         .map(str::trim)
   3006         .filter(|value| !value.is_empty())
   3007     else {
   3008         return Ok(None);
   3009     };
   3010     let Some(author) = record
   3011         .event_pubkey
   3012         .as_deref()
   3013         .map(str::trim)
   3014         .filter(|value| !value.is_empty())
   3015     else {
   3016         return Ok(None);
   3017     };
   3018     let Some(kind) = record.event_kind.and_then(|kind| u32::try_from(kind).ok()) else {
   3019         return Ok(None);
   3020     };
   3021     let Some(created_at) = record
   3022         .event_created_at
   3023         .and_then(|created_at| u32::try_from(created_at).ok())
   3024     else {
   3025         return Ok(None);
   3026     };
   3027     let Some(sig) = record
   3028         .event_sig
   3029         .as_deref()
   3030         .map(str::trim)
   3031         .filter(|value| !value.is_empty())
   3032     else {
   3033         return Ok(None);
   3034     };
   3035     let Some(tags) = record.event_tags_json.as_ref().and_then(tags_from_json) else {
   3036         return Ok(None);
   3037     };
   3038     Ok(Some(RadrootsNostrEvent {
   3039         id: id.to_owned(),
   3040         author: author.to_owned(),
   3041         created_at,
   3042         kind,
   3043         tags,
   3044         content: record.event_content.clone().unwrap_or_default(),
   3045         sig: sig.to_owned(),
   3046     }))
   3047 }
   3048 
   3049 fn signed_event_record_is_usable(record: &LocalEventRecord) -> bool {
   3050     if record.status != LocalRecordStatus::Published
   3051         || matches!(
   3052             record.outbox_status,
   3053             PublishOutboxStatus::Pending | PublishOutboxStatus::Failed
   3054         )
   3055     {
   3056         return false;
   3057     }
   3058     let Some(relay_delivery_json) = record.relay_delivery_json.as_ref() else {
   3059         return false;
   3060     };
   3061     let Ok(relay_delivery) = RelayDeliveryEvidence::from_json_value(relay_delivery_json) else {
   3062         return false;
   3063     };
   3064     matches!(
   3065         relay_delivery.state,
   3066         RelayDeliveryState::Acknowledged | RelayDeliveryState::Observed
   3067     )
   3068 }
   3069 
   3070 fn signed_event_local_interop_evidence_is_usable(
   3071     evidence: &StoredLocalInteropSignedEventEvidence,
   3072 ) -> bool {
   3073     if evidence.local_status != LocalRecordStatus::Published.as_str()
   3074         || matches!(evidence.outbox_status.as_str(), "pending" | "failed")
   3075     {
   3076         return false;
   3077     }
   3078     let Some(relay_delivery_json) = evidence.relay_delivery_json.as_deref() else {
   3079         return false;
   3080     };
   3081     let Ok(relay_delivery_value) = serde_json::from_str::<Value>(relay_delivery_json) else {
   3082         return false;
   3083     };
   3084     let Ok(relay_delivery) = RelayDeliveryEvidence::from_json_value(&relay_delivery_value) else {
   3085         return false;
   3086     };
   3087     matches!(
   3088         relay_delivery.state,
   3089         RelayDeliveryState::Acknowledged | RelayDeliveryState::Observed
   3090     )
   3091 }
   3092 
   3093 fn signed_event_from_local_interop_evidence(
   3094     evidence: &StoredLocalInteropSignedEventEvidence,
   3095 ) -> Result<Option<RadrootsNostrEvent>, AppSqliteError> {
   3096     let Some(id) = evidence
   3097         .event_id
   3098         .as_deref()
   3099         .map(str::trim)
   3100         .filter(|value| !value.is_empty())
   3101     else {
   3102         return Ok(None);
   3103     };
   3104     let Some(author) = evidence
   3105         .event_pubkey
   3106         .as_deref()
   3107         .map(str::trim)
   3108         .filter(|value| !value.is_empty())
   3109     else {
   3110         return Ok(None);
   3111     };
   3112     let Some(kind) = evidence
   3113         .event_kind
   3114         .and_then(|kind| u32::try_from(kind).ok())
   3115     else {
   3116         return Ok(None);
   3117     };
   3118     let Some(created_at) = evidence
   3119         .event_created_at
   3120         .and_then(|created_at| u32::try_from(created_at).ok())
   3121     else {
   3122         return Ok(None);
   3123     };
   3124     let Some(sig) = evidence
   3125         .event_sig
   3126         .as_deref()
   3127         .map(str::trim)
   3128         .filter(|value| !value.is_empty())
   3129     else {
   3130         return Ok(None);
   3131     };
   3132     let Some(tags_json) = evidence.event_tags_json.as_deref() else {
   3133         return Ok(None);
   3134     };
   3135     let Ok(tags_value) = serde_json::from_str::<Value>(tags_json) else {
   3136         return Ok(None);
   3137     };
   3138     let Some(tags) = tags_from_json(&tags_value) else {
   3139         return Ok(None);
   3140     };
   3141     Ok(Some(RadrootsNostrEvent {
   3142         id: id.to_owned(),
   3143         author: author.to_owned(),
   3144         created_at,
   3145         kind,
   3146         tags,
   3147         content: evidence.event_content.clone().unwrap_or_default(),
   3148         sig: sig.to_owned(),
   3149     }))
   3150 }
   3151 
   3152 fn tags_from_json(value: &Value) -> Option<Vec<Vec<String>>> {
   3153     value.as_array().map(|tags| {
   3154         tags.iter()
   3155             .filter_map(|tag| {
   3156                 tag.as_array().map(|values| {
   3157                     values
   3158                         .iter()
   3159                         .filter_map(|value| value.as_str().map(str::to_owned))
   3160                         .collect::<Vec<_>>()
   3161                 })
   3162             })
   3163             .collect::<Vec<_>>()
   3164     })
   3165 }
   3166 
   3167 pub fn projected_order_id_from_trade_request(order_id: &str, buyer_pubkey: &str) -> OrderId {
   3168     order_id.parse().unwrap_or_else(|_| {
   3169         OrderId::from(deterministic_uuid(
   3170             "radroots-cli-order",
   3171             Some(buyer_pubkey),
   3172             order_id,
   3173         ))
   3174     })
   3175 }
   3176 
   3177 fn projected_order_id(order_id: &str, buyer_pubkey: &str) -> OrderId {
   3178     projected_order_id_from_trade_request(order_id, buyer_pubkey)
   3179 }
   3180 
   3181 fn active_order_revision_status(
   3182     projection: &RadrootsOrderProjection,
   3183     revision_proposals: &[RadrootsOrderRevisionProposalRecord],
   3184     revision_decisions: &[RadrootsOrderRevisionDecisionRecord],
   3185 ) -> TradeRevisionStatus {
   3186     let Some(mut parent_event_id) = projection
   3187         .decision_event_id
   3188         .clone()
   3189         .or_else(|| projection.request_event_id.clone())
   3190     else {
   3191         return TradeRevisionStatus::None;
   3192     };
   3193     let mut status = TradeRevisionStatus::None;
   3194     loop {
   3195         let matching_proposals = revision_proposals
   3196             .iter()
   3197             .filter(|proposal| proposal.prev_event_id == parent_event_id)
   3198             .collect::<Vec<_>>();
   3199         let proposal = match matching_proposals.as_slice() {
   3200             [] => return status,
   3201             [proposal] => *proposal,
   3202             _ => return TradeRevisionStatus::None,
   3203         };
   3204         let matching_decisions = revision_decisions
   3205             .iter()
   3206             .filter(|decision| decision.prev_event_id == proposal.event_id)
   3207             .collect::<Vec<_>>();
   3208         let decision = match matching_decisions.as_slice() {
   3209             [] => return TradeRevisionStatus::ChangeProposed,
   3210             [decision] => *decision,
   3211             _ => return TradeRevisionStatus::None,
   3212         };
   3213         if decision.payload.revision_id != proposal.payload.revision_id {
   3214             return TradeRevisionStatus::None;
   3215         }
   3216         status = match &decision.payload.decision {
   3217             RadrootsOrderRevisionOutcome::Accepted => TradeRevisionStatus::Updated,
   3218             RadrootsOrderRevisionOutcome::Declined { .. } => TradeRevisionStatus::KeptAsPlaced,
   3219         };
   3220         parent_event_id.clone_from(&decision.event_id);
   3221     }
   3222 }
   3223 
   3224 fn active_order_agreement_source(
   3225     request: &RadrootsOrderRequest,
   3226     projection: &RadrootsOrderProjection,
   3227     revision_proposals: &[RadrootsOrderRevisionProposalRecord],
   3228     revision_decisions: &[RadrootsOrderRevisionDecisionRecord],
   3229 ) -> ActiveOrderAgreementSource {
   3230     if let Some(agreement_event_id) = projection.agreement_event_id.as_deref()
   3231         && projection.decision_event_id.as_deref() != Some(agreement_event_id)
   3232         && let Some(revision_decision) = revision_decisions.iter().find(|decision| {
   3233             decision.event_id == agreement_event_id
   3234                 && matches!(
   3235                     &decision.payload.decision,
   3236                     RadrootsOrderRevisionOutcome::Accepted
   3237                 )
   3238         })
   3239         && let Some(revision_proposal) = revision_proposals.iter().find(|proposal| {
   3240             proposal.event_id == revision_decision.prev_event_id
   3241                 && proposal.payload.revision_id == revision_decision.payload.revision_id
   3242         })
   3243     {
   3244         return ActiveOrderAgreementSource {
   3245             listing_addr: revision_proposal.payload.listing_addr.to_string(),
   3246             seller_pubkey: revision_proposal.payload.seller_pubkey.to_string(),
   3247             items: revision_proposal.payload.items.clone(),
   3248             economics: revision_proposal.payload.economics.clone(),
   3249         };
   3250     }
   3251     ActiveOrderAgreementSource {
   3252         listing_addr: request.listing_addr.to_string(),
   3253         seller_pubkey: request.seller_pubkey.to_string(),
   3254         items: request.items.clone(),
   3255         economics: request.economics.clone(),
   3256     }
   3257 }
   3258 
   3259 fn order_line_product_id(
   3260     payload: &RadrootsOrderRequest,
   3261     existing_listing: Option<&ExistingListingProjection>,
   3262     item: &radroots_events::order::RadrootsOrderItem,
   3263 ) -> ProductId {
   3264     order_agreement_line_product_id(
   3265         payload.listing_addr.as_str(),
   3266         payload.seller_pubkey.as_str(),
   3267         existing_listing,
   3268         item,
   3269     )
   3270 }
   3271 
   3272 fn order_agreement_line_product_id(
   3273     listing_addr: &str,
   3274     seller_pubkey: &str,
   3275     existing_listing: Option<&ExistingListingProjection>,
   3276     item: &RadrootsOrderItem,
   3277 ) -> ProductId {
   3278     if let Some(existing_listing) = existing_listing
   3279         && existing_listing
   3280             .listing_bin_id
   3281             .as_deref()
   3282             .is_none_or(|listing_bin_id| listing_bin_id == item.bin_id)
   3283     {
   3284         return existing_listing.product_id;
   3285     }
   3286     let product_key = format!("{listing_addr}:{}", item.bin_id);
   3287     deterministic_product_id(Some(seller_pubkey), product_key.as_str())
   3288 }
   3289 
   3290 fn deterministic_order_number(order_id: &str) -> String {
   3291     let trimmed = order_id.trim();
   3292     let suffix = trimmed
   3293         .chars()
   3294         .filter(|ch| ch.is_ascii_alphanumeric())
   3295         .take(8)
   3296         .collect::<String>();
   3297     if suffix.is_empty() {
   3298         "R-RELAY".to_owned()
   3299     } else {
   3300         format!("R-{suffix}")
   3301     }
   3302 }
   3303 
   3304 fn existing_order_number(
   3305     connection: &Connection,
   3306     order_id: OrderId,
   3307 ) -> Result<Option<String>, AppSqliteError> {
   3308     connection
   3309         .query_row(
   3310             "SELECT order_number FROM orders WHERE id = ?1 LIMIT 1",
   3311             params![order_id.to_string()],
   3312             |row| row.get::<_, String>(0),
   3313         )
   3314         .optional()
   3315         .map_err(|source| AppSqliteError::Query {
   3316             operation: "load existing local interop order number",
   3317             source,
   3318         })
   3319 }
   3320 
   3321 fn order_customer_display_name(buyer_pubkey: &str) -> String {
   3322     let prefix = buyer_pubkey.trim().chars().take(12).collect::<String>();
   3323     if prefix.is_empty() {
   3324         "Relay buyer".to_owned()
   3325     } else {
   3326         format!("Relay buyer {prefix}")
   3327     }
   3328 }
   3329 
   3330 fn order_buyer_context_key(record: &LocalEventRecord, buyer_pubkey: &str) -> String {
   3331     if record.source_runtime == SourceRuntime::App
   3332         && record
   3333             .event_pubkey
   3334             .as_deref()
   3335             .map(str::trim)
   3336             .is_some_and(|event_pubkey| event_pubkey == buyer_pubkey.trim())
   3337         && let Some(owner_account_id) = record
   3338             .owner_account_id
   3339             .as_deref()
   3340             .map(str::trim)
   3341             .filter(|owner_account_id| !owner_account_id.is_empty())
   3342     {
   3343         return format!("account:{owner_account_id}");
   3344     }
   3345     format!("nostr:{}", buyer_pubkey.trim())
   3346 }
   3347 
   3348 fn format_quantity_display(quantity: u32, unit_label: &str) -> String {
   3349     let unit_label = unit_label.trim();
   3350     if unit_label.is_empty() {
   3351         quantity.to_string()
   3352     } else {
   3353         format!("{quantity} {unit_label}")
   3354     }
   3355 }
   3356 
   3357 fn listing_event_id_from_order_record(record: &LocalEventRecord) -> Option<String> {
   3358     record
   3359         .event_tags_json
   3360         .as_ref()
   3361         .and_then(|tags| tag_index_value(Some(tags), "listing_event", 1))
   3362 }
   3363 
   3364 fn base64_url_digit(byte: u8) -> Option<u8> {
   3365     match byte {
   3366         b'A'..=b'Z' => Some(byte - b'A'),
   3367         b'a'..=b'z' => Some(byte - b'a' + 26),
   3368         b'0'..=b'9' => Some(byte - b'0' + 52),
   3369         b'-' => Some(62),
   3370         b'_' => Some(63),
   3371         _ => None,
   3372     }
   3373 }
   3374 
   3375 fn string_at(value: &Value, path: &[&str]) -> Option<String> {
   3376     let mut cursor = value;
   3377     for segment in path {
   3378         cursor = cursor.get(*segment)?;
   3379     }
   3380     match cursor {
   3381         Value::String(value) => {
   3382             let trimmed = value.trim();
   3383             (!trimmed.is_empty()).then(|| trimmed.to_owned())
   3384         }
   3385         Value::Number(number) => Some(number.to_string()),
   3386         _ => None,
   3387     }
   3388 }
   3389 
   3390 fn listing_id(record: &LocalEventRecord) -> Option<String> {
   3391     record
   3392         .listing_addr
   3393         .as_deref()
   3394         .and_then(|addr| addr.rsplit(':').next())
   3395         .map(str::trim)
   3396         .filter(|value| !value.is_empty())
   3397         .map(str::to_owned)
   3398 }
   3399 
   3400 fn farm_order_method(value: &str) -> Option<FarmOrderMethod> {
   3401     match value.trim() {
   3402         "pickup" => Some(FarmOrderMethod::Pickup),
   3403         "delivery" | "local_delivery" => Some(FarmOrderMethod::Delivery),
   3404         "shipping" => Some(FarmOrderMethod::Shipping),
   3405         _ => None,
   3406     }
   3407 }
   3408 
   3409 fn parse_decimal_minor_units(value: &str) -> Option<u32> {
   3410     let value = value.trim();
   3411     if value.is_empty() || value.starts_with('-') {
   3412         return None;
   3413     }
   3414     let (whole, fraction) = value.split_once('.').unwrap_or((value, ""));
   3415     let whole_units = whole.parse::<u32>().ok()?;
   3416     let cents = match fraction.len() {
   3417         0 => 0,
   3418         1 => fraction.parse::<u32>().ok()? * 10,
   3419         _ => fraction.get(0..2)?.parse::<u32>().ok()?,
   3420     };
   3421     whole_units.checked_mul(100)?.checked_add(cents)
   3422 }
   3423 
   3424 fn parse_u32_quantity(value: &str) -> Option<u32> {
   3425     let value = value.trim();
   3426     if value.is_empty() || value.starts_with('-') {
   3427         return None;
   3428     }
   3429     let whole = value.split_once('.').map_or(value, |(whole, _)| whole);
   3430     whole.parse::<u32>().ok()
   3431 }
   3432 
   3433 fn parse_u64_quantity(value: &str) -> Option<u64> {
   3434     let value = value.trim();
   3435     if value.is_empty() || value.starts_with('-') {
   3436         return None;
   3437     }
   3438     let whole = value.split_once('.').map_or(value, |(whole, _)| whole);
   3439     whole.parse::<u64>().ok()
   3440 }
   3441 
   3442 fn signed_listing_product_status(
   3443     record: &LocalEventRecord,
   3444     content: Option<&Value>,
   3445     tags: Option<&Value>,
   3446 ) -> Option<ProductStatus> {
   3447     if !signed_listing_has_public_evidence(record) {
   3448         return Some(ProductStatus::Draft);
   3449     }
   3450     match signed_listing_lifecycle(content, tags)? {
   3451         SignedListingLifecycle::Active | SignedListingLifecycle::Window => {
   3452             Some(ProductStatus::Published)
   3453         }
   3454         SignedListingLifecycle::Archived => Some(ProductStatus::Archived),
   3455         SignedListingLifecycle::Sold => Some(ProductStatus::Paused),
   3456     }
   3457 }
   3458 
   3459 fn signed_listing_has_public_evidence(record: &LocalEventRecord) -> bool {
   3460     if record.status != LocalRecordStatus::Published {
   3461         return false;
   3462     }
   3463     if record.outbox_status == PublishOutboxStatus::Acknowledged {
   3464         return true;
   3465     }
   3466     record
   3467         .relay_delivery_json
   3468         .as_ref()
   3469         .and_then(|delivery| RelayDeliveryEvidence::from_json_value(delivery).ok())
   3470         .is_some_and(|delivery| delivery.state == RelayDeliveryState::Observed)
   3471 }
   3472 
   3473 fn signed_event_import_has_public_evidence(
   3474     local_status: &str,
   3475     outbox_status: &str,
   3476     relay_delivery_json: Option<&str>,
   3477 ) -> bool {
   3478     if local_status != LocalRecordStatus::Published.as_str() {
   3479         return false;
   3480     }
   3481     if outbox_status == PublishOutboxStatus::Acknowledged.as_str() {
   3482         return true;
   3483     }
   3484     relay_delivery_json
   3485         .and_then(|delivery| serde_json::from_str::<Value>(delivery).ok())
   3486         .and_then(|delivery| RelayDeliveryEvidence::from_json_value(&delivery).ok())
   3487         .is_some_and(|delivery| delivery.state == RelayDeliveryState::Observed)
   3488 }
   3489 
   3490 fn signed_farm_readiness(content: &Value, tags: Option<&Value>) -> Option<FarmReadiness> {
   3491     string_at(content, &["readiness"])
   3492         .or_else(|| {
   3493             content
   3494                 .get("tags")?
   3495                 .as_array()?
   3496                 .iter()
   3497                 .filter_map(Value::as_str)
   3498                 .find_map(readiness_tag_value)
   3499         })
   3500         .or_else(|| {
   3501             tags?.as_array()?.iter().find_map(|tag| {
   3502                 let values = tag.as_array()?;
   3503                 (values.first()?.as_str()? == "t")
   3504                     .then(|| values.get(1).and_then(Value::as_str))
   3505                     .flatten()
   3506                     .and_then(readiness_tag_value)
   3507             })
   3508         })
   3509         .and_then(|value| match value.as_str() {
   3510             "ready" => Some(FarmReadiness::Ready),
   3511             "incomplete" => Some(FarmReadiness::Incomplete),
   3512             _ => None,
   3513         })
   3514 }
   3515 
   3516 fn readiness_tag_value(value: &str) -> Option<String> {
   3517     value
   3518         .strip_prefix("radroots:readiness:")
   3519         .map(str::trim)
   3520         .filter(|value| !value.is_empty())
   3521         .map(str::to_owned)
   3522 }
   3523 
   3524 fn signed_listing_fulfillment_method(
   3525     content: Option<&Value>,
   3526     tags: Option<&Value>,
   3527 ) -> Option<FarmOrderMethod> {
   3528     content.and_then(delivery_method_from_content).or_else(|| {
   3529         tag_index_value(tags, "delivery", 1).and_then(|method| farm_order_method(&method))
   3530     })
   3531 }
   3532 
   3533 fn delivery_method_from_content(content: &Value) -> Option<FarmOrderMethod> {
   3534     string_at(content, &["delivery_method", "kind"])
   3535         .or_else(|| string_at(content, &["delivery", "method"]))
   3536         .or_else(|| string_at(content, &["delivery_method"]))
   3537         .and_then(|method| farm_order_method(method.as_str()))
   3538 }
   3539 
   3540 fn signed_listing_availability_window(
   3541     content: Option<&Value>,
   3542     tags: Option<&Value>,
   3543 ) -> Option<ListingAvailabilityWindow> {
   3544     let start = content
   3545         .and_then(|content| string_at(content, &["availability", "amount", "start"]))
   3546         .or_else(|| content.and_then(|content| string_at(content, &["availability", "start"])))
   3547         .or_else(|| tag_index_value(tags, "radroots:availability_start", 1))
   3548         .and_then(|value| parse_u64_quantity(value.as_str()));
   3549     let end = content
   3550         .and_then(|content| string_at(content, &["availability", "amount", "end"]))
   3551         .or_else(|| content.and_then(|content| string_at(content, &["availability", "end"])))
   3552         .or_else(|| tag_index_value(tags, "expires_at", 1))
   3553         .and_then(|value| parse_u64_quantity(value.as_str()));
   3554 
   3555     match (start, end) {
   3556         (Some(start), Some(end)) if end > start => Some(ListingAvailabilityWindow { start, end }),
   3557         _ => None,
   3558     }
   3559 }
   3560 
   3561 fn signed_listing_location_primary(
   3562     content: Option<&Value>,
   3563     tags: Option<&Value>,
   3564 ) -> Option<String> {
   3565     content
   3566         .and_then(|content| string_at(content, &["location", "primary"]))
   3567         .or_else(|| tag_index_value(tags, "location", 1))
   3568 }
   3569 
   3570 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
   3571 struct ListingAvailabilityWindow {
   3572     start: u64,
   3573     end: u64,
   3574 }
   3575 
   3576 fn signed_listing_lifecycle(
   3577     content: Option<&Value>,
   3578     tags: Option<&Value>,
   3579 ) -> Option<SignedListingLifecycle> {
   3580     content
   3581         .and_then(lifecycle_from_content)
   3582         .or_else(|| lifecycle_from_tags(tags))
   3583 }
   3584 
   3585 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
   3586 enum SignedListingLifecycle {
   3587     Active,
   3588     Window,
   3589     Archived,
   3590     Sold,
   3591 }
   3592 
   3593 fn lifecycle_from_content(content: &Value) -> Option<SignedListingLifecycle> {
   3594     string_at(content, &["status"])
   3595         .or_else(|| string_at(content, &["availability", "status"]))
   3596         .or_else(|| string_at(content, &["availability", "amount", "status"]))
   3597         .or_else(|| string_at(content, &["availability", "amount", "kind"]))
   3598         .or_else(|| string_at(content, &["availability", "amount", "value"]))
   3599         .and_then(|status| parse_listing_lifecycle(status.as_str()))
   3600         .or_else(|| {
   3601             matches!(
   3602                 string_at(content, &["availability", "kind"]).as_deref(),
   3603                 Some("window")
   3604             )
   3605             .then_some(SignedListingLifecycle::Window)
   3606         })
   3607 }
   3608 
   3609 fn lifecycle_from_tags(tags: Option<&Value>) -> Option<SignedListingLifecycle> {
   3610     tag_index_value(tags, "status", 1)
   3611         .and_then(|status| parse_listing_lifecycle(status.as_str()))
   3612         .or_else(|| {
   3613             tag_index_value(tags, "radroots:availability_start", 1)
   3614                 .or_else(|| tag_index_value(tags, "expires_at", 1))
   3615                 .map(|_| SignedListingLifecycle::Window)
   3616         })
   3617 }
   3618 
   3619 fn parse_listing_lifecycle(value: &str) -> Option<SignedListingLifecycle> {
   3620     match value.trim().to_ascii_lowercase().as_str() {
   3621         "active" | "available" | "published" => Some(SignedListingLifecycle::Active),
   3622         "window" => Some(SignedListingLifecycle::Window),
   3623         "archived" => Some(SignedListingLifecycle::Archived),
   3624         "sold" => Some(SignedListingLifecycle::Sold),
   3625         _ => None,
   3626     }
   3627 }
   3628 
   3629 fn primary_bin(content: &Value) -> Option<&Value> {
   3630     let bins = content.get("bins")?.as_array()?;
   3631     let primary_bin_id = string_at(content, &["primary_bin_id"]);
   3632     primary_bin_id
   3633         .as_deref()
   3634         .and_then(|primary_bin_id| {
   3635             bins.iter()
   3636                 .find(|bin| string_at(bin, &["bin_id"]).as_deref() == Some(primary_bin_id))
   3637         })
   3638         .or_else(|| bins.first())
   3639 }
   3640 
   3641 fn parse_json_value(raw: &str) -> Result<Value, AppSqliteError> {
   3642     serde_json::from_str(raw).map_err(|_| AppSqliteError::InvalidProjection {
   3643         reason: "shared local signed event content must be json",
   3644     })
   3645 }
   3646 
   3647 fn parse_json_value_opt(raw: &str) -> Option<Value> {
   3648     serde_json::from_str(raw).ok()
   3649 }
   3650 
   3651 fn tag_index_value(tags: Option<&Value>, tag_name: &str, index: usize) -> Option<String> {
   3652     tags?.as_array()?.iter().find_map(|tag| {
   3653         let values = tag.as_array()?;
   3654         (values.first()?.as_str()? == tag_name)
   3655             .then(|| values.get(index).and_then(Value::as_str))
   3656             .flatten()
   3657             .map(str::trim)
   3658             .filter(|value| !value.is_empty())
   3659             .map(str::to_owned)
   3660     })
   3661 }
   3662 
   3663 fn signed_farm_address_matches(tags: Option<&Value>, farm_key: &str, seller_pubkey: &str) -> bool {
   3664     let Some(address) = tag_index_value(tags, "a", 1) else {
   3665         return false;
   3666     };
   3667     address_d_tag(address.as_str()).as_deref() == Some(farm_key)
   3668         && address_pubkey(address.as_str()).as_deref() == Some(seller_pubkey)
   3669 }
   3670 
   3671 #[derive(Clone, Debug, Eq, PartialEq)]
   3672 struct ListingAddressParts<'a> {
   3673     kind: i64,
   3674     pubkey: &'a str,
   3675     d_tag: &'a str,
   3676 }
   3677 
   3678 fn listing_address_parts(address: &str) -> Option<ListingAddressParts<'_>> {
   3679     let mut parts = address.trim().split(':');
   3680     let kind = parts.next()?.parse::<i64>().ok()?;
   3681     let pubkey = parts.next()?.trim();
   3682     let d_tag = parts.next()?.trim();
   3683     if parts.next().is_some() || pubkey.is_empty() || d_tag.is_empty() {
   3684         return None;
   3685     }
   3686     Some(ListingAddressParts {
   3687         kind,
   3688         pubkey,
   3689         d_tag,
   3690     })
   3691 }
   3692 
   3693 fn address_d_tag(address: &str) -> Option<String> {
   3694     address
   3695         .rsplit(':')
   3696         .next()
   3697         .map(str::trim)
   3698         .filter(|value| !value.is_empty())
   3699         .map(str::to_owned)
   3700 }
   3701 
   3702 fn address_pubkey(address: &str) -> Option<String> {
   3703     let mut parts = address.split(':');
   3704     let _kind = parts.next()?;
   3705     parts
   3706         .next()
   3707         .map(str::trim)
   3708         .filter(|value| !value.is_empty())
   3709         .map(str::to_owned)
   3710 }
   3711 
   3712 fn farm_readiness_storage_key(readiness: FarmReadiness) -> &'static str {
   3713     match readiness {
   3714         FarmReadiness::Incomplete => "incomplete",
   3715         FarmReadiness::Ready => "ready",
   3716     }
   3717 }
   3718 
   3719 fn farm_readiness_from_storage_key(readiness: &str) -> Result<FarmReadiness, AppSqliteError> {
   3720     match readiness {
   3721         "incomplete" => Ok(FarmReadiness::Incomplete),
   3722         "ready" => Ok(FarmReadiness::Ready),
   3723         _ => Err(AppSqliteError::InvalidProjection {
   3724             reason: "farm readiness storage key is invalid",
   3725         }),
   3726     }
   3727 }
   3728 
   3729 #[cfg(test)]
   3730 mod tests {
   3731     use std::collections::BTreeSet;
   3732 
   3733     use radroots_app_view::{
   3734         BuyerContext, BuyerOrderStatus, FarmId, FarmOrderMethod, OrderId, OrderStatus,
   3735         OrdersFilter, OrdersScreenQueryState, ProductAvailabilityState, ProductId,
   3736         TradeAgreementStatus, TradeInventoryStatus, TradeRevisionStatus,
   3737         TradeValidationReceiptProofSystem, TradeValidationReceiptResult,
   3738         TradeValidationReceiptType, TradeWorkflowSource,
   3739     };
   3740     use radroots_core::{
   3741         RadrootsCoreCurrency, RadrootsCoreDecimal, RadrootsCoreMoney, RadrootsCoreUnit,
   3742     };
   3743     use radroots_events::{
   3744         RadrootsNostrEvent, RadrootsNostrEventPtr,
   3745         ids::{
   3746             RadrootsEventId, RadrootsInventoryBinId, RadrootsListingAddress, RadrootsOrderId,
   3747             RadrootsOrderQuoteId, RadrootsOrderRevisionId, RadrootsPublicKey,
   3748         },
   3749         order::{
   3750             RadrootsOrderCancellation, RadrootsOrderDecision, RadrootsOrderDecisionOutcome,
   3751             RadrootsOrderEconomicItem, RadrootsOrderEconomicLine, RadrootsOrderEconomics,
   3752             RadrootsOrderInventoryCommitment, RadrootsOrderItem, RadrootsOrderPricingBasis,
   3753             RadrootsOrderRequest, RadrootsOrderRevisionDecision, RadrootsOrderRevisionOutcome,
   3754             RadrootsOrderRevisionProposal,
   3755         },
   3756     };
   3757     use radroots_events_codec::{
   3758         order::{
   3759             order_cancellation_event_build, order_decision_event_build, order_request_event_build,
   3760             order_revision_decision_event_build, order_revision_proposal_event_build,
   3761         },
   3762         wire::WireEventParts,
   3763     };
   3764     use radroots_local_events::{
   3765         LocalEventRecordInput, LocalEventRecordUpdate, LocalEventsStore, LocalRecordFamily,
   3766         LocalRecordStatus, PublishOutboxStatus, RelayDeliveryEvidence, SourceRuntime,
   3767     };
   3768     use radroots_sql_core::SqliteExecutor;
   3769     use radroots_trade::validation_receipt::{
   3770         RadrootsTradeValidationReceipt, RadrootsValidationReceiptProof,
   3771         RadrootsValidationReceiptProofSystem, RadrootsValidationReceiptResult,
   3772         RadrootsValidationReceiptStatement, RadrootsValidationReceiptType,
   3773         VALIDATION_RECEIPT_DOMAIN, VALIDATION_RECEIPT_VERSION, validation_receipt_event_build,
   3774     };
   3775     use rusqlite::params;
   3776     use serde_json::json;
   3777     use uuid::Uuid;
   3778 
   3779     use super::{
   3780         KIND_FARM, KIND_LISTING, KIND_ORDER_REQUEST, KIND_VALIDATION_RECEIPT,
   3781         deterministic_farm_id, deterministic_product_id, projected_farm_id, projected_order_id,
   3782         projected_product_id,
   3783     };
   3784     use crate::{AppSqliteStore, BuyerRepeatDemandApplyOutcome, DatabaseTarget};
   3785 
   3786     fn local_events_store() -> LocalEventsStore<SqliteExecutor> {
   3787         let executor = SqliteExecutor::open_memory().expect("open local events memory db");
   3788         let store = LocalEventsStore::new(executor);
   3789         store.migrate_up().expect("migrate local events store");
   3790         store
   3791     }
   3792 
   3793     fn local_work_record(
   3794         record_id: &str,
   3795         farm_key: &str,
   3796         payload: serde_json::Value,
   3797     ) -> LocalEventRecordInput {
   3798         LocalEventRecordInput {
   3799             record_id: record_id.to_owned(),
   3800             family: LocalRecordFamily::LocalWork,
   3801             status: LocalRecordStatus::LocalSaved,
   3802             source_runtime: SourceRuntime::Cli,
   3803             created_at_ms: 1000,
   3804             inserted_at_ms: 1001,
   3805             owner_account_id: Some("seller-account".to_owned()),
   3806             owner_pubkey: Some("seller-pubkey".to_owned()),
   3807             farm_id: Some(farm_key.to_owned()),
   3808             listing_addr: None,
   3809             local_work_json: Some(payload),
   3810             event_id: None,
   3811             event_kind: None,
   3812             event_pubkey: None,
   3813             event_created_at: None,
   3814             event_tags_json: None,
   3815             event_content: None,
   3816             event_sig: None,
   3817             raw_event_json: None,
   3818             outbox_status: PublishOutboxStatus::None,
   3819             relay_set_fingerprint: None,
   3820             relay_delivery_json: None,
   3821         }
   3822     }
   3823 
   3824     fn signed_farm_record(
   3825         record_id: &str,
   3826         event_id: &str,
   3827         source_runtime: SourceRuntime,
   3828         owner_pubkey: &str,
   3829         farm_key: &str,
   3830         readiness: &str,
   3831         display_name: &str,
   3832     ) -> LocalEventRecordInput {
   3833         LocalEventRecordInput {
   3834             record_id: record_id.to_owned(),
   3835             family: LocalRecordFamily::SignedEvent,
   3836             status: LocalRecordStatus::Published,
   3837             source_runtime,
   3838             created_at_ms: 1100,
   3839             inserted_at_ms: 1101,
   3840             owner_account_id: Some("seller-account".to_owned()),
   3841             owner_pubkey: Some(owner_pubkey.to_owned()),
   3842             farm_id: Some(farm_key.to_owned()),
   3843             listing_addr: None,
   3844             local_work_json: None,
   3845             event_id: Some(event_id.to_owned()),
   3846             event_kind: Some(KIND_FARM),
   3847             event_pubkey: Some(owner_pubkey.to_owned()),
   3848             event_created_at: Some(1100),
   3849             event_tags_json: Some(json!([
   3850                 ["d", farm_key],
   3851                 ["t", format!("radroots:readiness:{readiness}")]
   3852             ])),
   3853             event_content: Some(
   3854                 json!({
   3855                     "d_tag": farm_key,
   3856                     "name": display_name,
   3857                     "tags": [format!("radroots:readiness:{readiness}")]
   3858                 })
   3859                 .to_string(),
   3860             ),
   3861             event_sig: Some("signature".to_owned()),
   3862             raw_event_json: Some(json!({
   3863                 "id": event_id,
   3864                 "kind": KIND_FARM,
   3865                 "pubkey": owner_pubkey,
   3866             })),
   3867             outbox_status: PublishOutboxStatus::Acknowledged,
   3868             relay_set_fingerprint: Some("relay-set".to_owned()),
   3869             relay_delivery_json: Some(json!({
   3870                 "state": "acknowledged",
   3871                 "target_relays": ["ws://127.0.0.1:1234"],
   3872                 "connected_relays": ["ws://127.0.0.1:1234"],
   3873                 "acknowledged_relays": ["ws://127.0.0.1:1234"]
   3874             })),
   3875         }
   3876     }
   3877 
   3878     fn signed_listing_record(
   3879         record_id: &str,
   3880         farm_key: &str,
   3881         listing_key: &str,
   3882         status_tag: &str,
   3883     ) -> LocalEventRecordInput {
   3884         signed_listing_record_with_publish_state(
   3885             record_id,
   3886             farm_key,
   3887             listing_key,
   3888             status_tag,
   3889             LocalRecordStatus::Published,
   3890             PublishOutboxStatus::Acknowledged,
   3891         )
   3892     }
   3893 
   3894     fn signed_listing_record_with_publish_state(
   3895         record_id: &str,
   3896         farm_key: &str,
   3897         listing_key: &str,
   3898         status_tag: &str,
   3899         record_status: LocalRecordStatus,
   3900         outbox_status: PublishOutboxStatus,
   3901     ) -> LocalEventRecordInput {
   3902         let relay_delivery_json = match outbox_status {
   3903             PublishOutboxStatus::Acknowledged => Some(json!({
   3904                 "state": "acknowledged",
   3905                 "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   3906             })),
   3907             PublishOutboxStatus::Failed => Some(json!({
   3908                 "state": "failed",
   3909                 "failed_relays": ["ws://127.0.0.1:1234/"]
   3910             })),
   3911             PublishOutboxStatus::Pending | PublishOutboxStatus::None => None,
   3912         };
   3913         LocalEventRecordInput {
   3914             record_id: record_id.to_owned(),
   3915             family: LocalRecordFamily::SignedEvent,
   3916             status: record_status,
   3917             source_runtime: SourceRuntime::Cli,
   3918             created_at_ms: 1100,
   3919             inserted_at_ms: 1101,
   3920             owner_account_id: Some("seller-account".to_owned()),
   3921             owner_pubkey: Some("seller-pubkey".to_owned()),
   3922             farm_id: Some(farm_key.to_owned()),
   3923             listing_addr: Some(format!("30402:seller-pubkey:{listing_key}")),
   3924             local_work_json: None,
   3925             event_id: Some(format!("event-{record_id}")),
   3926             event_kind: Some(KIND_LISTING),
   3927             event_pubkey: Some("seller-pubkey".to_owned()),
   3928             event_created_at: Some(1100),
   3929             event_tags_json: Some(json!([
   3930                 ["d", listing_key],
   3931                 ["a", format!("30340:seller-pubkey:{farm_key}")],
   3932                 ["key", "eggs"],
   3933                 ["title", "Relay Eggs"],
   3934                 ["summary", "Published eggs"],
   3935                 ["radroots:bin", "bin-1", "1", "each"],
   3936                 ["radroots:price", "bin-1", "8", "USD", "1", "each"],
   3937                 ["inventory", "9"],
   3938                 ["status", status_tag]
   3939             ])),
   3940             event_content: Some("# Relay Eggs\n\nPublished eggs".to_owned()),
   3941             event_sig: Some("signature".to_owned()),
   3942             raw_event_json: Some(json!({
   3943                 "id": format!("event-{record_id}"),
   3944                 "kind": KIND_LISTING,
   3945                 "pubkey": "seller-pubkey",
   3946                 "content": "# Relay Eggs\n\nPublished eggs"
   3947             })),
   3948             outbox_status,
   3949             relay_set_fingerprint: Some("relay-set".to_owned()),
   3950             relay_delivery_json,
   3951         }
   3952     }
   3953 
   3954     fn signed_market_listing_record(
   3955         record_id: &str,
   3956         owner_pubkey: &str,
   3957         farm_key: &str,
   3958         listing_key: &str,
   3959         title: &str,
   3960         inventory_available: &str,
   3961         status_tag: &str,
   3962         delivery_method: &str,
   3963         location_primary: &str,
   3964         availability_start: u64,
   3965         availability_end: u64,
   3966         record_status: LocalRecordStatus,
   3967         outbox_status: PublishOutboxStatus,
   3968     ) -> LocalEventRecordInput {
   3969         let relay_delivery_json = match outbox_status {
   3970             PublishOutboxStatus::Acknowledged => Some(json!({
   3971                 "state": "acknowledged",
   3972                 "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   3973             })),
   3974             PublishOutboxStatus::Failed => Some(json!({
   3975                 "state": "failed",
   3976                 "failed_relays": ["ws://127.0.0.1:1234/"]
   3977             })),
   3978             PublishOutboxStatus::Pending | PublishOutboxStatus::None => None,
   3979         };
   3980         let content = json!({
   3981             "d_tag": listing_key,
   3982             "status": status_tag,
   3983             "farm": {
   3984                 "pubkey": owner_pubkey,
   3985                 "d_tag": farm_key,
   3986             },
   3987             "product": {
   3988                 "key": listing_key,
   3989                 "title": title,
   3990                 "summary": "Published local listing",
   3991             },
   3992             "availability": {
   3993                 "kind": "window",
   3994                 "amount": {
   3995                     "start": availability_start,
   3996                     "end": availability_end,
   3997                 },
   3998             },
   3999             "delivery_method": {
   4000                 "kind": delivery_method,
   4001             },
   4002             "location": {
   4003                 "primary": location_primary,
   4004             },
   4005         });
   4006 
   4007         LocalEventRecordInput {
   4008             record_id: record_id.to_owned(),
   4009             family: LocalRecordFamily::SignedEvent,
   4010             status: record_status,
   4011             source_runtime: SourceRuntime::Cli,
   4012             created_at_ms: 1100,
   4013             inserted_at_ms: 1101,
   4014             owner_account_id: Some("seller-account".to_owned()),
   4015             owner_pubkey: Some(owner_pubkey.to_owned()),
   4016             farm_id: Some(farm_key.to_owned()),
   4017             listing_addr: Some(format!("30402:{owner_pubkey}:{listing_key}")),
   4018             local_work_json: None,
   4019             event_id: Some(format!("event-{record_id}")),
   4020             event_kind: Some(KIND_LISTING),
   4021             event_pubkey: Some(owner_pubkey.to_owned()),
   4022             event_created_at: Some(1100),
   4023             event_tags_json: Some(json!([
   4024                 ["d", listing_key],
   4025                 ["a", format!("30340:{owner_pubkey}:{farm_key}")],
   4026                 ["key", listing_key],
   4027                 ["title", title],
   4028                 ["summary", "Published local listing"],
   4029                 ["radroots:bin", "bin-1", "1", "each"],
   4030                 ["radroots:price", "bin-1", "8", "USD", "1", "each"],
   4031                 ["inventory", inventory_available],
   4032                 ["status", status_tag],
   4033                 [
   4034                     "radroots:availability_start",
   4035                     availability_start.to_string()
   4036                 ],
   4037                 ["expires_at", availability_end.to_string()],
   4038                 ["delivery", delivery_method],
   4039                 ["location", location_primary],
   4040             ])),
   4041             event_content: Some(content.to_string()),
   4042             event_sig: Some("signature".to_owned()),
   4043             raw_event_json: Some(json!({
   4044                 "id": format!("event-{record_id}"),
   4045                 "kind": KIND_LISTING,
   4046                 "pubkey": owner_pubkey,
   4047                 "content": content.to_string(),
   4048             })),
   4049             outbox_status,
   4050             relay_set_fingerprint: Some("relay-set".to_owned()),
   4051             relay_delivery_json,
   4052         }
   4053     }
   4054 
   4055     fn set_listing_event_version(
   4056         record: &mut LocalEventRecordInput,
   4057         event_id: &str,
   4058         created_at: i64,
   4059         title: &str,
   4060         inventory_available: &str,
   4061     ) {
   4062         record.event_id = Some(event_id.to_owned());
   4063         record.event_created_at = Some(created_at);
   4064         record.created_at_ms = created_at * 1_000;
   4065         record.inserted_at_ms = created_at * 1_000 + 1;
   4066         if let Some(content) = record.event_content.as_deref() {
   4067             let mut content: serde_json::Value =
   4068                 serde_json::from_str(content).expect("listing content should parse");
   4069             content["product"]["title"] = json!(title);
   4070             content["inventory_available"] = json!(inventory_available);
   4071             record.event_content = Some(content.to_string());
   4072         }
   4073         if let Some(serde_json::Value::Array(tags)) = record.event_tags_json.as_mut() {
   4074             for tag in tags {
   4075                 let Some(values) = tag.as_array_mut() else {
   4076                     continue;
   4077                 };
   4078                 match values.first().and_then(serde_json::Value::as_str) {
   4079                     Some("title") => {
   4080                         values[1] = json!(title);
   4081                     }
   4082                     Some("inventory") => {
   4083                         values[1] = json!(inventory_available);
   4084                     }
   4085                     _ => {}
   4086                 }
   4087             }
   4088         }
   4089         record.raw_event_json = Some(json!({
   4090             "id": event_id,
   4091             "kind": record.event_kind,
   4092             "pubkey": record.event_pubkey,
   4093             "content": record.event_content,
   4094         }));
   4095     }
   4096 
   4097     fn buyer_listing_titles(app_store: &AppSqliteStore) -> Vec<String> {
   4098         app_store
   4099             .load_buyer_listings("", &BTreeSet::new())
   4100             .expect("buyer listings should load")
   4101             .rows
   4102             .into_iter()
   4103             .map(|row| row.title)
   4104             .collect()
   4105     }
   4106 
   4107     fn app_d_tag_from_uuid(uuid: Uuid) -> String {
   4108         const ALPHABET: &[u8; 64] =
   4109             b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
   4110         let bytes = uuid.as_bytes();
   4111         let mut output = String::with_capacity((bytes.len() * 4).div_ceil(3));
   4112         let mut chunks = bytes.chunks_exact(3);
   4113         for chunk in &mut chunks {
   4114             output.push(ALPHABET[(chunk[0] >> 2) as usize] as char);
   4115             output.push(
   4116                 ALPHABET[(((chunk[0] & 0b0000_0011) << 4) | (chunk[1] >> 4)) as usize] as char,
   4117             );
   4118             output.push(
   4119                 ALPHABET[(((chunk[1] & 0b0000_1111) << 2) | (chunk[2] >> 6)) as usize] as char,
   4120             );
   4121             output.push(ALPHABET[(chunk[2] & 0b0011_1111) as usize] as char);
   4122         }
   4123         match chunks.remainder() {
   4124             [one] => {
   4125                 output.push(ALPHABET[(one >> 2) as usize] as char);
   4126                 output.push(ALPHABET[((one & 0b0000_0011) << 4) as usize] as char);
   4127             }
   4128             [one, two] => {
   4129                 output.push(ALPHABET[(one >> 2) as usize] as char);
   4130                 output.push(ALPHABET[(((one & 0b0000_0011) << 4) | (two >> 4)) as usize] as char);
   4131                 output.push(ALPHABET[((two & 0b0000_1111) << 2) as usize] as char);
   4132             }
   4133             [] => {}
   4134             _ => unreachable!(),
   4135         }
   4136         output
   4137     }
   4138 
   4139     #[test]
   4140     fn app_shaped_keys_use_uuid_projection_only_for_app_runtime() {
   4141         let owner_pubkey = "projection-owner-pubkey";
   4142         let farm_uuid = Uuid::from_u128(0x11111111111141118111111111111111);
   4143         let product_uuid = Uuid::from_u128(0x22222222222242228222222222222222);
   4144         let farm_key = app_d_tag_from_uuid(farm_uuid);
   4145         let listing_key = app_d_tag_from_uuid(product_uuid);
   4146 
   4147         assert_eq!(
   4148             projected_farm_id(SourceRuntime::App, Some(owner_pubkey), farm_key.as_str()),
   4149             Some(FarmId::from(farm_uuid))
   4150         );
   4151         assert_eq!(
   4152             projected_product_id(SourceRuntime::App, Some(owner_pubkey), listing_key.as_str()),
   4153             Some(ProductId::from(product_uuid))
   4154         );
   4155         assert_eq!(
   4156             projected_farm_id(
   4157                 SourceRuntime::Network,
   4158                 Some(owner_pubkey),
   4159                 farm_key.as_str()
   4160             ),
   4161             Some(deterministic_farm_id(Some(owner_pubkey), farm_key.as_str()))
   4162         );
   4163         assert_eq!(
   4164             projected_product_id(
   4165                 SourceRuntime::Network,
   4166                 Some(owner_pubkey),
   4167                 listing_key.as_str()
   4168             ),
   4169             Some(deterministic_product_id(
   4170                 Some(owner_pubkey),
   4171                 listing_key.as_str()
   4172             ))
   4173         );
   4174     }
   4175 
   4176     fn app_local_work_record(
   4177         record_id: &str,
   4178         farm_key: &str,
   4179         payload: serde_json::Value,
   4180     ) -> LocalEventRecordInput {
   4181         let mut record = local_work_record(record_id, farm_key, payload);
   4182         record.source_runtime = SourceRuntime::App;
   4183         record.owner_pubkey = Some("app-seller-pubkey".to_owned());
   4184         record
   4185     }
   4186 
   4187     fn seed_app_projection(app_store: &AppSqliteStore, farm_id: Uuid, product_id: Uuid) {
   4188         app_store
   4189             .connection()
   4190             .execute(
   4191                 "INSERT INTO farms (id, display_name, readiness, created_at, updated_at)
   4192                  VALUES (?1, 'Origin Farm', 'ready', '2026-01-01T00:00:00Z', '2026-01-01T00:00:00Z')",
   4193                 params![farm_id.to_string()],
   4194             )
   4195             .expect("seed origin farm");
   4196         app_store
   4197             .connection()
   4198             .execute(
   4199                 "INSERT INTO products (
   4200                     id,
   4201                     farm_id,
   4202                     title,
   4203                     subtitle,
   4204                     status,
   4205                     unit_label,
   4206                     price_minor_units,
   4207                     price_currency,
   4208                     stock_count,
   4209                     availability_window_id,
   4210                     updated_at
   4211                  ) VALUES (
   4212                     ?1,
   4213                     ?2,
   4214                     'Origin Eggs',
   4215                     'Seeded product',
   4216                     'draft',
   4217                     'each',
   4218                     400,
   4219                     'USD',
   4220                     3,
   4221                     NULL,
   4222                     '2026-01-01T00:00:00Z'
   4223                  )",
   4224                 params![product_id.to_string(), farm_id.to_string()],
   4225             )
   4226             .expect("seed origin product");
   4227     }
   4228 
   4229     fn decimal(raw: &str) -> RadrootsCoreDecimal {
   4230         raw.parse().expect("valid decimal")
   4231     }
   4232 
   4233     fn usd(raw: &str) -> RadrootsCoreMoney {
   4234         RadrootsCoreMoney::new(decimal(raw), RadrootsCoreCurrency::USD)
   4235     }
   4236 
   4237     fn test_pubkey(seed: &str) -> String {
   4238         let left = Uuid::new_v5(&Uuid::NAMESPACE_URL, seed.as_bytes());
   4239         let right_seed = format!("{seed}:right");
   4240         let right = Uuid::new_v5(&Uuid::NAMESPACE_URL, right_seed.as_bytes());
   4241         format!("{}{}", left.simple(), right.simple())
   4242     }
   4243 
   4244     fn test_event_id_seed(seed: &str) -> String {
   4245         test_pubkey(seed)
   4246     }
   4247 
   4248     fn typed_order_id(raw: &str) -> RadrootsOrderId {
   4249         raw.parse().expect("valid order id")
   4250     }
   4251 
   4252     fn typed_revision_id(raw: &str) -> RadrootsOrderRevisionId {
   4253         raw.parse().expect("valid revision id")
   4254     }
   4255 
   4256     fn typed_quote_id(raw: &str) -> RadrootsOrderQuoteId {
   4257         raw.parse().expect("valid quote id")
   4258     }
   4259 
   4260     fn typed_bin_id(raw: &str) -> RadrootsInventoryBinId {
   4261         raw.parse().expect("valid bin id")
   4262     }
   4263 
   4264     fn typed_event_id(raw: &str) -> RadrootsEventId {
   4265         raw.parse().expect("valid event id")
   4266     }
   4267 
   4268     fn typed_pubkey(raw: &str) -> RadrootsPublicKey {
   4269         raw.parse().expect("valid pubkey")
   4270     }
   4271 
   4272     fn typed_listing_addr(raw: &str) -> RadrootsListingAddress {
   4273         raw.parse().expect("valid listing address")
   4274     }
   4275 
   4276     fn listing_event_ptr(event_id: &str) -> RadrootsNostrEventPtr {
   4277         RadrootsNostrEventPtr {
   4278             id: test_event_id_seed(event_id),
   4279             relays: Some("ws://127.0.0.1:1234/".to_owned()),
   4280         }
   4281     }
   4282 
   4283     fn order_request_payload(
   4284         order_id: &str,
   4285         listing_addr: &str,
   4286         buyer_pubkey: &str,
   4287         seller_pubkey: &str,
   4288     ) -> RadrootsOrderRequest {
   4289         RadrootsOrderRequest {
   4290             order_id: typed_order_id(order_id),
   4291             listing_addr: typed_listing_addr(listing_addr),
   4292             buyer_pubkey: typed_pubkey(buyer_pubkey),
   4293             seller_pubkey: typed_pubkey(seller_pubkey),
   4294             items: vec![RadrootsOrderItem {
   4295                 bin_id: typed_bin_id("bin-1"),
   4296                 bin_count: 2,
   4297             }],
   4298             economics: RadrootsOrderEconomics {
   4299                 quote_id: typed_quote_id(format!("quote-{order_id}").as_str()),
   4300                 quote_version: 1,
   4301                 pricing_basis: RadrootsOrderPricingBasis::ListingEvent,
   4302                 currency: RadrootsCoreCurrency::USD,
   4303                 items: vec![RadrootsOrderEconomicItem {
   4304                     bin_id: typed_bin_id("bin-1"),
   4305                     bin_count: 2,
   4306                     quantity_amount: decimal("1"),
   4307                     quantity_unit: RadrootsCoreUnit::Each,
   4308                     unit_price_amount: decimal("8"),
   4309                     unit_price_currency: RadrootsCoreCurrency::USD,
   4310                     line_subtotal: usd("16"),
   4311                 }],
   4312                 discounts: Vec::<RadrootsOrderEconomicLine>::new(),
   4313                 adjustments: Vec::<RadrootsOrderEconomicLine>::new(),
   4314                 subtotal: usd("16"),
   4315                 discount_total: usd("0"),
   4316                 adjustment_total: usd("0"),
   4317                 total: usd("16"),
   4318             },
   4319         }
   4320     }
   4321 
   4322     fn accepted_order_decision_payload(
   4323         order_id: &str,
   4324         listing_addr: &str,
   4325         buyer_pubkey: &str,
   4326         seller_pubkey: &str,
   4327     ) -> RadrootsOrderDecision {
   4328         RadrootsOrderDecision {
   4329             order_id: typed_order_id(order_id),
   4330             listing_addr: typed_listing_addr(listing_addr),
   4331             buyer_pubkey: typed_pubkey(buyer_pubkey),
   4332             seller_pubkey: typed_pubkey(seller_pubkey),
   4333             decision: RadrootsOrderDecisionOutcome::Accepted {
   4334                 inventory_commitments: vec![RadrootsOrderInventoryCommitment {
   4335                     bin_id: typed_bin_id("bin-1"),
   4336                     bin_count: 2,
   4337                 }],
   4338             },
   4339         }
   4340     }
   4341 
   4342     fn declined_order_decision_payload(
   4343         order_id: &str,
   4344         listing_addr: &str,
   4345         buyer_pubkey: &str,
   4346         seller_pubkey: &str,
   4347     ) -> RadrootsOrderDecision {
   4348         RadrootsOrderDecision {
   4349             order_id: typed_order_id(order_id),
   4350             listing_addr: typed_listing_addr(listing_addr),
   4351             buyer_pubkey: typed_pubkey(buyer_pubkey),
   4352             seller_pubkey: typed_pubkey(seller_pubkey),
   4353             decision: RadrootsOrderDecisionOutcome::Declined {
   4354                 reason: "not available for this pickup".to_owned(),
   4355             },
   4356         }
   4357     }
   4358 
   4359     fn revision_proposal_payload(
   4360         revision_id: &str,
   4361         order_id: &str,
   4362         listing_addr: &str,
   4363         buyer_pubkey: &str,
   4364         seller_pubkey: &str,
   4365         root_event_id: &str,
   4366         prev_event_id: &str,
   4367     ) -> RadrootsOrderRevisionProposal {
   4368         let mut request =
   4369             order_request_payload(order_id, listing_addr, buyer_pubkey, seller_pubkey);
   4370         request.items[0].bin_count = 3;
   4371         request.economics.quote_id =
   4372             typed_quote_id(format!("quote-{order_id}-{revision_id}").as_str());
   4373         request.economics.quote_version = 2;
   4374         request.economics.items[0].bin_count = 3;
   4375         request.economics.items[0].line_subtotal = usd("24");
   4376         request.economics.subtotal = usd("24");
   4377         request.economics.total = usd("24");
   4378         RadrootsOrderRevisionProposal {
   4379             revision_id: typed_revision_id(revision_id),
   4380             order_id: typed_order_id(order_id),
   4381             listing_addr: typed_listing_addr(listing_addr),
   4382             buyer_pubkey: typed_pubkey(buyer_pubkey),
   4383             seller_pubkey: typed_pubkey(seller_pubkey),
   4384             root_event_id: typed_event_id(root_event_id),
   4385             prev_event_id: typed_event_id(prev_event_id),
   4386             items: request.items,
   4387             economics: request.economics,
   4388             reason: "seller confirmed updated pickup details".to_owned(),
   4389         }
   4390     }
   4391 
   4392     fn revision_decision_payload(
   4393         revision_id: &str,
   4394         order_id: &str,
   4395         listing_addr: &str,
   4396         buyer_pubkey: &str,
   4397         seller_pubkey: &str,
   4398         root_event_id: &str,
   4399         prev_event_id: &str,
   4400         decision: RadrootsOrderRevisionOutcome,
   4401     ) -> RadrootsOrderRevisionDecision {
   4402         RadrootsOrderRevisionDecision {
   4403             revision_id: typed_revision_id(revision_id),
   4404             order_id: typed_order_id(order_id),
   4405             listing_addr: typed_listing_addr(listing_addr),
   4406             buyer_pubkey: typed_pubkey(buyer_pubkey),
   4407             seller_pubkey: typed_pubkey(seller_pubkey),
   4408             root_event_id: typed_event_id(root_event_id),
   4409             prev_event_id: typed_event_id(prev_event_id),
   4410             decision,
   4411         }
   4412     }
   4413 
   4414     fn order_cancel_payload(
   4415         order_id: &str,
   4416         listing_addr: &str,
   4417         buyer_pubkey: &str,
   4418         seller_pubkey: &str,
   4419     ) -> RadrootsOrderCancellation {
   4420         RadrootsOrderCancellation {
   4421             order_id: typed_order_id(order_id),
   4422             listing_addr: typed_listing_addr(listing_addr),
   4423             buyer_pubkey: typed_pubkey(buyer_pubkey),
   4424             seller_pubkey: typed_pubkey(seller_pubkey),
   4425             reason: "buyer changed pickup plan".to_owned(),
   4426         }
   4427     }
   4428 
   4429     struct ValidationReceiptOrderFixture {
   4430         app_store: AppSqliteStore,
   4431         events: LocalEventsStore<SqliteExecutor>,
   4432         buyer_context: BuyerContext,
   4433         seller_farm_id: FarmId,
   4434         order_id: OrderId,
   4435         order_id_raw: String,
   4436         listing_addr: String,
   4437         buyer_pubkey: String,
   4438         seller_pubkey: String,
   4439         listing_event_id: String,
   4440         request_event_id: String,
   4441         decision_event_id: String,
   4442     }
   4443 
   4444     fn validation_receipt_order_fixture(label: &str) -> ValidationReceiptOrderFixture {
   4445         let app_store =
   4446             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   4447         let events = local_events_store();
   4448         let farm_key = "DDDDDDDDDDDDDDDDDDDDDD";
   4449         let listing_key = "AAAAAAAAAAAAAAAAAAAAAw";
   4450         let seller_pubkey = test_pubkey(format!("{label}-seller").as_str());
   4451         let buyer_pubkey = test_pubkey(format!("{label}-buyer").as_str());
   4452         let order_id_raw = format!("{label}-order");
   4453         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   4454         let listing_event_id = hex_event_id(21);
   4455         let request_event_id = hex_event_id(22);
   4456         let decision_event_id = hex_event_id(23);
   4457         events
   4458             .append_record(&signed_market_listing_record(
   4459                 format!("{label}-listing-record").as_str(),
   4460                 seller_pubkey.as_str(),
   4461                 farm_key,
   4462                 listing_key,
   4463                 "Validation Eggs",
   4464                 "9",
   4465                 "active",
   4466                 "pickup",
   4467                 "North barn pickup",
   4468                 4_102_444_800,
   4469                 4_102_531_200,
   4470                 LocalRecordStatus::Published,
   4471                 PublishOutboxStatus::Acknowledged,
   4472             ))
   4473             .expect("append signed listing");
   4474         app_store
   4475             .import_shared_local_events_from_store(&events)
   4476             .expect("import signed listing");
   4477 
   4478         let request_payload = order_request_payload(
   4479             order_id_raw.as_str(),
   4480             listing_addr.as_str(),
   4481             buyer_pubkey.as_str(),
   4482             seller_pubkey.as_str(),
   4483         );
   4484         let request_parts =
   4485             order_request_event_build(&listing_event_ptr(&listing_event_id), &request_payload)
   4486                 .expect("build validation order request");
   4487         let request_event = event_from_parts_at(
   4488             request_event_id.as_str(),
   4489             buyer_pubkey.as_str(),
   4490             request_parts,
   4491             1_777_665_601,
   4492         );
   4493         events
   4494             .append_record(&signed_order_event_record(
   4495                 format!("app:signed_event:{label}:request").as_str(),
   4496                 &request_event,
   4497                 listing_addr.as_str(),
   4498                 SourceRuntime::App,
   4499                 Some("acct_validation"),
   4500             ))
   4501             .expect("append validation order request");
   4502         app_store
   4503             .import_shared_local_events_from_store(&events)
   4504             .expect("import validation order request");
   4505 
   4506         let decision_payload = accepted_order_decision_payload(
   4507             order_id_raw.as_str(),
   4508             listing_addr.as_str(),
   4509             buyer_pubkey.as_str(),
   4510             seller_pubkey.as_str(),
   4511         );
   4512         let decision_parts = order_decision_event_build(
   4513             &typed_event_id(request_event_id.as_str()),
   4514             &typed_event_id(request_event_id.as_str()),
   4515             &decision_payload,
   4516         )
   4517         .expect("build validation order decision");
   4518         let decision_event = event_from_parts_at(
   4519             decision_event_id.as_str(),
   4520             seller_pubkey.as_str(),
   4521             decision_parts,
   4522             1_777_665_602,
   4523         );
   4524         events
   4525             .append_record(&signed_order_event_record(
   4526                 format!("cli:signed_event:{label}:decision").as_str(),
   4527                 &decision_event,
   4528                 listing_addr.as_str(),
   4529                 SourceRuntime::Cli,
   4530                 None,
   4531             ))
   4532             .expect("append validation order decision");
   4533         app_store
   4534             .import_shared_local_events_from_store(&events)
   4535             .expect("import validation order decision");
   4536 
   4537         ValidationReceiptOrderFixture {
   4538             app_store,
   4539             events,
   4540             buyer_context: BuyerContext::account("acct_validation"),
   4541             seller_farm_id: deterministic_farm_id(Some(seller_pubkey.as_str()), farm_key),
   4542             order_id: projected_order_id(order_id_raw.as_str(), buyer_pubkey.as_str()),
   4543             order_id_raw,
   4544             listing_addr,
   4545             buyer_pubkey,
   4546             seller_pubkey,
   4547             listing_event_id,
   4548             request_event_id,
   4549             decision_event_id,
   4550         }
   4551     }
   4552 
   4553     fn event_from_parts(event_id: &str, author: &str, parts: WireEventParts) -> RadrootsNostrEvent {
   4554         let event_id = event_id
   4555             .parse::<RadrootsEventId>()
   4556             .map(|event_id| event_id.to_string())
   4557             .unwrap_or_else(|_| test_event_id_seed(event_id));
   4558         RadrootsNostrEvent {
   4559             sig: format!("sig-{event_id}"),
   4560             id: event_id,
   4561             author: author.to_owned(),
   4562             created_at: 1_777_665_600,
   4563             kind: parts.kind,
   4564             tags: parts.tags,
   4565             content: parts.content,
   4566         }
   4567     }
   4568 
   4569     fn event_from_parts_at(
   4570         event_id: &str,
   4571         author: &str,
   4572         parts: WireEventParts,
   4573         created_at: u32,
   4574     ) -> RadrootsNostrEvent {
   4575         let mut event = event_from_parts(event_id, author, parts);
   4576         event.created_at = created_at;
   4577         event
   4578     }
   4579 
   4580     fn hex_event_id(seed: u8) -> String {
   4581         format!("{seed:064x}")
   4582     }
   4583 
   4584     fn hash32(seed: u8) -> String {
   4585         format!("0x{seed:064x}")
   4586     }
   4587 
   4588     fn validation_error_bitmap(result: RadrootsValidationReceiptResult) -> String {
   4589         match result {
   4590             RadrootsValidationReceiptResult::Valid => format!("0x{:032x}", 0),
   4591             RadrootsValidationReceiptResult::Invalid => format!("0x{:032x}", 1),
   4592         }
   4593     }
   4594 
   4595     fn validation_receipt_payload(
   4596         listing_event_id: &str,
   4597         root_event_id: &str,
   4598         target_event_id: &str,
   4599         result: RadrootsValidationReceiptResult,
   4600     ) -> RadrootsTradeValidationReceipt {
   4601         RadrootsTradeValidationReceipt {
   4602             changed_records_root: hash32(41),
   4603             domain: VALIDATION_RECEIPT_DOMAIN.to_owned(),
   4604             error_bitmap: validation_error_bitmap(result),
   4605             event_set_root: hash32(42),
   4606             new_state_root: hash32(43),
   4607             previous_state_root: hash32(44),
   4608             proof: RadrootsValidationReceiptProof {
   4609                 inline_proof_base64: None,
   4610                 mode: None,
   4611                 program_hash: None,
   4612                 proof_reference: None,
   4613                 system: RadrootsValidationReceiptProofSystem::None,
   4614                 verifying_key_hash: None,
   4615             },
   4616             public_values_hash: hash32(45),
   4617             receipt_type: RadrootsValidationReceiptType::TradeTransition,
   4618             result,
   4619             statement: RadrootsValidationReceiptStatement {
   4620                 listing_event_id: listing_event_id.to_owned(),
   4621                 root_event_id: root_event_id.to_owned(),
   4622                 target_event_id: target_event_id.to_owned(),
   4623                 statement_type: RadrootsValidationReceiptType::TradeTransition,
   4624             },
   4625             version: VALIDATION_RECEIPT_VERSION,
   4626         }
   4627     }
   4628 
   4629     fn validation_receipt_event(
   4630         event_id: &str,
   4631         author: &str,
   4632         order_id: &str,
   4633         listing_event_id: &str,
   4634         root_event_id: &str,
   4635         target_event_id: &str,
   4636         result: RadrootsValidationReceiptResult,
   4637         created_at: u32,
   4638     ) -> RadrootsNostrEvent {
   4639         let receipt =
   4640             validation_receipt_payload(listing_event_id, root_event_id, target_event_id, result);
   4641         let parts =
   4642             validation_receipt_event_build(order_id, &receipt).expect("validation receipt parts");
   4643         event_from_parts_at(event_id, author, parts, created_at)
   4644     }
   4645 
   4646     fn signed_order_event_record(
   4647         record_id: &str,
   4648         event: &RadrootsNostrEvent,
   4649         listing_addr: &str,
   4650         source_runtime: SourceRuntime,
   4651         owner_account_id: Option<&str>,
   4652     ) -> LocalEventRecordInput {
   4653         let relay_delivery_json = RelayDeliveryEvidence::acknowledged(
   4654             ["ws://127.0.0.1:1234"],
   4655             ["ws://127.0.0.1:1234"],
   4656             ["ws://127.0.0.1:1234"],
   4657             Vec::new(),
   4658         )
   4659         .expect("acknowledged relay evidence")
   4660         .to_json_value()
   4661         .expect("acknowledged relay evidence json");
   4662         LocalEventRecordInput {
   4663             record_id: record_id.to_owned(),
   4664             family: LocalRecordFamily::SignedEvent,
   4665             status: LocalRecordStatus::Published,
   4666             source_runtime,
   4667             created_at_ms: i64::from(event.created_at) * 1_000,
   4668             inserted_at_ms: i64::from(event.created_at) * 1_000 + 1,
   4669             owner_account_id: owner_account_id.map(str::to_owned),
   4670             owner_pubkey: Some(event.author.clone()),
   4671             farm_id: None,
   4672             listing_addr: Some(listing_addr.to_owned()),
   4673             local_work_json: None,
   4674             event_id: Some(event.id.clone()),
   4675             event_kind: Some(i64::from(event.kind)),
   4676             event_pubkey: Some(event.author.clone()),
   4677             event_created_at: Some(i64::from(event.created_at)),
   4678             event_tags_json: Some(json!(event.tags)),
   4679             event_content: Some(event.content.clone()),
   4680             event_sig: Some(event.sig.clone()),
   4681             raw_event_json: Some(json!({
   4682                 "id": event.id,
   4683                 "kind": event.kind,
   4684                 "pubkey": event.author,
   4685                 "created_at": event.created_at,
   4686                 "tags": event.tags,
   4687                 "content": event.content,
   4688                 "sig": event.sig,
   4689             })),
   4690             outbox_status: PublishOutboxStatus::Acknowledged,
   4691             relay_set_fingerprint: Some("relay-set".to_owned()),
   4692             relay_delivery_json: Some(relay_delivery_json),
   4693         }
   4694     }
   4695 
   4696     #[test]
   4697     fn imports_signed_order_request_into_seller_order_projection() {
   4698         let app_store =
   4699             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   4700         let events = local_events_store();
   4701         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   4702         let listing_key = "AAAAAAAAAAAAAAAAAAAAAg";
   4703         let seller_pubkey = test_pubkey("seller-pubkey");
   4704         let seller_pubkey = seller_pubkey.as_str();
   4705         let buyer_pubkey = test_pubkey("buyer-pubkey");
   4706         let buyer_pubkey = buyer_pubkey.as_str();
   4707         let order_id_raw = "relay-order-1";
   4708         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   4709         events
   4710             .append_record(&signed_market_listing_record(
   4711                 "order-visible-listing",
   4712                 seller_pubkey,
   4713                 farm_key,
   4714                 listing_key,
   4715                 "Order Visible Eggs",
   4716                 "9",
   4717                 "active",
   4718                 "pickup",
   4719                 "North barn pickup",
   4720                 4_102_444_800,
   4721                 4_102_531_200,
   4722                 LocalRecordStatus::Published,
   4723                 PublishOutboxStatus::Acknowledged,
   4724             ))
   4725             .expect("append signed listing");
   4726         app_store
   4727             .import_shared_local_events_from_store(&events)
   4728             .expect("import signed listing");
   4729         let payload = order_request_payload(
   4730             order_id_raw,
   4731             listing_addr.as_str(),
   4732             buyer_pubkey,
   4733             seller_pubkey,
   4734         );
   4735         let parts = order_request_event_build(&listing_event_ptr("listing-event-1"), &payload)
   4736             .expect("build order request event");
   4737         let event = event_from_parts("order-request-event-1", buyer_pubkey, parts);
   4738         events
   4739             .append_record(&signed_order_event_record(
   4740                 "cli:signed_event:order-request:1",
   4741                 &event,
   4742                 listing_addr.as_str(),
   4743                 SourceRuntime::Cli,
   4744                 None,
   4745             ))
   4746             .expect("append order request");
   4747 
   4748         let report = app_store
   4749             .import_shared_local_events_from_store(&events)
   4750             .expect("import signed order request");
   4751         let farm_id = deterministic_farm_id(Some(seller_pubkey), farm_key);
   4752         let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   4753         let orders = app_store
   4754             .load_orders_list(
   4755                 farm_id,
   4756                 &OrdersScreenQueryState {
   4757                     filter: OrdersFilter::All,
   4758                     fulfillment_window_id: None,
   4759                 },
   4760             )
   4761             .expect("load seller orders");
   4762         let detail = app_store
   4763             .load_order_detail(farm_id, order_id)
   4764             .expect("load order detail")
   4765             .expect("order detail");
   4766         let imported = app_store
   4767             .load_local_interop_records()
   4768             .expect("load imported records");
   4769         let signed_evidence = app_store
   4770             .load_local_interop_signed_events_by_kind(KIND_ORDER_REQUEST)
   4771             .expect("load signed event evidence");
   4772         let buyer_context_key: String = app_store
   4773             .connection()
   4774             .query_row(
   4775                 "SELECT buyer_context_key FROM orders WHERE id = ?1",
   4776                 [order_id.to_string()],
   4777                 |row| row.get(0),
   4778             )
   4779             .expect("load buyer context key");
   4780 
   4781         assert_eq!(report.imported_records, 1);
   4782         assert!(
   4783             imported
   4784                 .iter()
   4785                 .any(|record| record.projected_kind == "signed_event"
   4786                     && record.event_kind == Some(KIND_ORDER_REQUEST)
   4787                     && record.event_id.as_deref() == Some(event.id.as_str()))
   4788         );
   4789         assert_eq!(signed_evidence, vec![event.clone()]);
   4790         assert_eq!(orders.rows.len(), 1);
   4791         assert_eq!(orders.rows[0].order_id, order_id);
   4792         assert_eq!(orders.rows[0].status, OrderStatus::NeedsAction);
   4793         assert_eq!(
   4794             orders.rows[0].customer_display_name,
   4795             format!("Relay buyer {}", &buyer_pubkey[..12])
   4796         );
   4797         assert_eq!(detail.items.len(), 1);
   4798         assert_eq!(detail.items[0].title, "Order Visible Eggs");
   4799         assert_eq!(detail.items[0].quantity_display, "2 each");
   4800         assert_eq!(buyer_context_key, format!("nostr:{buyer_pubkey}"));
   4801     }
   4802 
   4803     #[test]
   4804     fn local_interop_order_request_evidence_requires_usable_delivery_state() {
   4805         let app_store =
   4806             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   4807         let events = local_events_store();
   4808         let buyer_pubkey = test_pubkey("buyer-pubkey");
   4809         let buyer_pubkey = buyer_pubkey.as_str();
   4810         let seller_pubkey = test_pubkey("seller-pubkey");
   4811         let seller_pubkey = seller_pubkey.as_str();
   4812         let listing_addr = format!("30402:{seller_pubkey}:AAAAAAAAAAAAAAAAAAAAAg");
   4813         let relay_url = "ws://127.0.0.1:1234";
   4814         let build_event = |event_id: &str, order_id_raw: &str| {
   4815             let payload = order_request_payload(
   4816                 order_id_raw,
   4817                 listing_addr.as_str(),
   4818                 buyer_pubkey,
   4819                 seller_pubkey,
   4820             );
   4821             let parts = order_request_event_build(&listing_event_ptr("listing-event-1"), &payload)
   4822                 .expect("build order request event");
   4823             event_from_parts(event_id, buyer_pubkey, parts)
   4824         };
   4825         let acknowledged_event = build_event("order-request-evidence-ack", "usable-ack");
   4826         events
   4827             .append_record(&signed_order_event_record(
   4828                 "cli:signed_event:order-request:evidence-ack",
   4829                 &acknowledged_event,
   4830                 listing_addr.as_str(),
   4831                 SourceRuntime::Cli,
   4832                 None,
   4833             ))
   4834             .expect("append acknowledged order request evidence");
   4835 
   4836         let observed_event = build_event("order-request-evidence-observed", "usable-observed");
   4837         let mut observed_record = signed_order_event_record(
   4838             "cli:signed_event:order-request:evidence-observed",
   4839             &observed_event,
   4840             listing_addr.as_str(),
   4841             SourceRuntime::Cli,
   4842             None,
   4843         );
   4844         observed_record.outbox_status = PublishOutboxStatus::None;
   4845         observed_record.relay_delivery_json = Some(
   4846             RelayDeliveryEvidence::observed([relay_url], [relay_url], [relay_url], Vec::new())
   4847                 .expect("observed relay evidence")
   4848                 .to_json_value()
   4849                 .expect("observed relay evidence json"),
   4850         );
   4851         events
   4852             .append_record(&observed_record)
   4853             .expect("append observed order request evidence");
   4854 
   4855         let pending_event = build_event("order-request-evidence-pending", "pending");
   4856         let mut pending_record = signed_order_event_record(
   4857             "cli:signed_event:order-request:evidence-pending",
   4858             &pending_event,
   4859             listing_addr.as_str(),
   4860             SourceRuntime::Cli,
   4861             None,
   4862         );
   4863         pending_record.status = LocalRecordStatus::PendingPublish;
   4864         pending_record.outbox_status = PublishOutboxStatus::Pending;
   4865         pending_record.relay_delivery_json = Some(
   4866             RelayDeliveryEvidence::pending([relay_url])
   4867                 .expect("pending relay evidence")
   4868                 .to_json_value()
   4869                 .expect("pending relay evidence json"),
   4870         );
   4871         events
   4872             .append_record(&pending_record)
   4873             .expect("append pending order request evidence");
   4874 
   4875         let failed_event = build_event("order-request-evidence-failed", "failed");
   4876         let mut failed_record = signed_order_event_record(
   4877             "cli:signed_event:order-request:evidence-failed",
   4878             &failed_event,
   4879             listing_addr.as_str(),
   4880             SourceRuntime::Cli,
   4881             None,
   4882         );
   4883         failed_record.outbox_status = PublishOutboxStatus::Failed;
   4884         failed_record.relay_delivery_json = Some(json!({
   4885             "state": "failed",
   4886             "target_relays": [relay_url],
   4887             "connected_relays": [relay_url],
   4888             "acknowledged_relays": [],
   4889             "failed_relays": [{"relay_url": relay_url, "error": "relay rejected event"}]
   4890         }));
   4891         events
   4892             .append_record(&failed_record)
   4893             .expect("append failed order request evidence");
   4894 
   4895         let local_only_event = build_event("order-request-evidence-local-only", "local-only");
   4896         let mut local_only_record = signed_order_event_record(
   4897             "cli:signed_event:order-request:evidence-local-only",
   4898             &local_only_event,
   4899             listing_addr.as_str(),
   4900             SourceRuntime::Cli,
   4901             None,
   4902         );
   4903         local_only_record.outbox_status = PublishOutboxStatus::None;
   4904         local_only_record.relay_set_fingerprint = None;
   4905         local_only_record.relay_delivery_json = None;
   4906         events
   4907             .append_record(&local_only_record)
   4908             .expect("append local-only order request evidence");
   4909 
   4910         let malformed_delivery_event = build_event(
   4911             "order-request-evidence-malformed-delivery",
   4912             "malformed-delivery",
   4913         );
   4914         let mut malformed_delivery_record = signed_order_event_record(
   4915             "cli:signed_event:order-request:evidence-malformed-delivery",
   4916             &malformed_delivery_event,
   4917             listing_addr.as_str(),
   4918             SourceRuntime::Cli,
   4919             None,
   4920         );
   4921         malformed_delivery_record.relay_delivery_json = Some(json!({
   4922             "state": "acknowledged"
   4923         }));
   4924         events
   4925             .append_record(&malformed_delivery_record)
   4926             .expect("append malformed delivery order request evidence");
   4927 
   4928         let malformed_event =
   4929             build_event("order-request-evidence-malformed-event", "malformed-event");
   4930         let mut malformed_record = signed_order_event_record(
   4931             "cli:signed_event:order-request:evidence-malformed-event",
   4932             &malformed_event,
   4933             listing_addr.as_str(),
   4934             SourceRuntime::Cli,
   4935             None,
   4936         );
   4937         malformed_record.event_tags_json = Some(json!({"invalid": "tags"}));
   4938         events
   4939             .append_record(&malformed_record)
   4940             .expect("append malformed order request evidence");
   4941 
   4942         app_store
   4943             .import_shared_local_events_from_store(&events)
   4944             .expect("import signed evidence records");
   4945         let signed_evidence = app_store
   4946             .load_local_interop_signed_events_by_kind(KIND_ORDER_REQUEST)
   4947             .expect("load filtered signed event evidence");
   4948 
   4949         assert_eq!(signed_evidence, vec![acknowledged_event, observed_event]);
   4950     }
   4951 
   4952     #[test]
   4953     fn app_origin_signed_order_request_and_decision_project_to_buyer_orders() {
   4954         let app_store =
   4955             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   4956         let events = local_events_store();
   4957         let farm_key = "CCCCCCCCCCCCCCCCCCCCCC";
   4958         let listing_key = "AAAAAAAAAAAAAAAAAAAAAg";
   4959         let seller_pubkey = test_pubkey("seller-pubkey");
   4960         let seller_pubkey = seller_pubkey.as_str();
   4961         let buyer_pubkey = test_pubkey("app-buyer-pubkey");
   4962         let buyer_pubkey = buyer_pubkey.as_str();
   4963         let order_id_raw = "app-relay-order-1";
   4964         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   4965         events
   4966             .append_record(&signed_market_listing_record(
   4967                 "buyer-order-listing",
   4968                 seller_pubkey,
   4969                 farm_key,
   4970                 listing_key,
   4971                 "Buyer Order Eggs",
   4972                 "9",
   4973                 "active",
   4974                 "pickup",
   4975                 "North barn pickup",
   4976                 4_102_444_800,
   4977                 4_102_531_200,
   4978                 LocalRecordStatus::Published,
   4979                 PublishOutboxStatus::Acknowledged,
   4980             ))
   4981             .expect("append signed listing");
   4982         app_store
   4983             .import_shared_local_events_from_store(&events)
   4984             .expect("import signed listing");
   4985         let request_payload = order_request_payload(
   4986             order_id_raw,
   4987             listing_addr.as_str(),
   4988             buyer_pubkey,
   4989             seller_pubkey,
   4990         );
   4991         let request_parts = order_request_event_build(
   4992             &listing_event_ptr("buyer-order-listing-event"),
   4993             &request_payload,
   4994         )
   4995         .expect("build order request event");
   4996         let request_event =
   4997             event_from_parts("buyer-order-request-event", buyer_pubkey, request_parts);
   4998         events
   4999             .append_record(&signed_order_event_record(
   5000                 "app:signed_event:order-request:buyer",
   5001                 &request_event,
   5002                 listing_addr.as_str(),
   5003                 SourceRuntime::App,
   5004                 Some("acct_buyer"),
   5005             ))
   5006             .expect("append app order request");
   5007 
   5008         let request_report = app_store
   5009             .import_shared_local_events_from_store(&events)
   5010             .expect("import app order request");
   5011         let buyer_context = BuyerContext::account("acct_buyer");
   5012         let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   5013         let farm_id = deterministic_farm_id(Some(seller_pubkey), farm_key);
   5014         let buyer_orders = app_store
   5015             .load_buyer_orders(&buyer_context)
   5016             .expect("load buyer orders after request");
   5017 
   5018         assert_eq!(request_report.imported_records, 1);
   5019         assert_eq!(buyer_orders.rows.len(), 1);
   5020         assert_eq!(buyer_orders.rows[0].order_id, order_id);
   5021         assert_eq!(buyer_orders.rows[0].status, BuyerOrderStatus::Placed);
   5022 
   5023         let decision_payload = accepted_order_decision_payload(
   5024             order_id_raw,
   5025             listing_addr.as_str(),
   5026             buyer_pubkey,
   5027             seller_pubkey,
   5028         );
   5029         let decision_parts = order_decision_event_build(
   5030             &typed_event_id(request_event.id.as_str()),
   5031             &typed_event_id(request_event.id.as_str()),
   5032             &decision_payload,
   5033         )
   5034         .expect("build order decision event");
   5035         let decision_event =
   5036             event_from_parts("buyer-order-decision-event", seller_pubkey, decision_parts);
   5037         events
   5038             .append_record(&signed_order_event_record(
   5039                 "cli:signed_event:order-decision:buyer",
   5040                 &decision_event,
   5041                 listing_addr.as_str(),
   5042                 SourceRuntime::Cli,
   5043                 None,
   5044             ))
   5045             .expect("append order decision");
   5046 
   5047         let decision_report = app_store
   5048             .import_shared_local_events_from_store(&events)
   5049             .expect("import order decision");
   5050         let buyer_orders = app_store
   5051             .load_buyer_orders(&buyer_context)
   5052             .expect("load buyer orders after decision");
   5053         let buyer_detail = app_store
   5054             .load_buyer_order_detail(&buyer_context, order_id)
   5055             .expect("load buyer order detail")
   5056             .expect("buyer order detail");
   5057         let seller_orders = app_store
   5058             .load_orders_list(
   5059                 farm_id,
   5060                 &OrdersScreenQueryState {
   5061                     filter: OrdersFilter::All,
   5062                     fulfillment_window_id: None,
   5063                 },
   5064             )
   5065             .expect("load seller orders after decision");
   5066 
   5067         assert_eq!(decision_report.imported_records, 1);
   5068         assert_eq!(buyer_orders.rows.len(), 1);
   5069         assert_eq!(buyer_orders.rows[0].status, BuyerOrderStatus::Scheduled);
   5070         assert_eq!(buyer_detail.status, BuyerOrderStatus::Scheduled);
   5071         assert_eq!(seller_orders.rows[0].status, OrderStatus::Scheduled);
   5072         assert_eq!(buyer_detail.workflow, buyer_orders.rows[0].workflow);
   5073         assert_eq!(
   5074             seller_orders.rows[0].workflow,
   5075             buyer_orders.rows[0].workflow
   5076         );
   5077         assert_eq!(
   5078             buyer_orders.rows[0].workflow.inventory,
   5079             TradeInventoryStatus::Reserved
   5080         );
   5081         assert_eq!(
   5082             buyer_orders.rows[0].workflow.provenance.primary_source,
   5083             TradeWorkflowSource::LocalEvents
   5084         );
   5085         assert_eq!(
   5086             buyer_orders.rows[0]
   5087                 .workflow
   5088                 .provenance
   5089                 .last_event_id
   5090                 .as_deref(),
   5091             Some(decision_event.id.as_str())
   5092         );
   5093         assert_eq!(
   5094             buyer_orders.rows[0].workflow.economics.total_minor_units,
   5095             Some(1600)
   5096         );
   5097     }
   5098 
   5099     #[test]
   5100     fn app_origin_signed_order_request_and_decline_project_to_buyer_orders() {
   5101         let app_store =
   5102             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   5103         let events = local_events_store();
   5104         let farm_key = "CCCCCCCCCCCCCCCCCCCCCC";
   5105         let listing_key = "AAAAAAAAAAAAAAAAAAAAAg";
   5106         let seller_pubkey = test_pubkey("seller-pubkey");
   5107         let seller_pubkey = seller_pubkey.as_str();
   5108         let buyer_pubkey = test_pubkey("app-buyer-pubkey");
   5109         let buyer_pubkey = buyer_pubkey.as_str();
   5110         let order_id_raw = "app-relay-order-declined-1";
   5111         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   5112         events
   5113             .append_record(&signed_market_listing_record(
   5114                 "buyer-order-decline-listing",
   5115                 seller_pubkey,
   5116                 farm_key,
   5117                 listing_key,
   5118                 "Buyer Order Eggs",
   5119                 "9",
   5120                 "active",
   5121                 "pickup",
   5122                 "North barn pickup",
   5123                 4_102_444_800,
   5124                 4_102_531_200,
   5125                 LocalRecordStatus::Published,
   5126                 PublishOutboxStatus::Acknowledged,
   5127             ))
   5128             .expect("append signed listing");
   5129         app_store
   5130             .import_shared_local_events_from_store(&events)
   5131             .expect("import signed listing");
   5132         let request_payload = order_request_payload(
   5133             order_id_raw,
   5134             listing_addr.as_str(),
   5135             buyer_pubkey,
   5136             seller_pubkey,
   5137         );
   5138         let request_parts = order_request_event_build(
   5139             &listing_event_ptr("buyer-order-decline-listing-event"),
   5140             &request_payload,
   5141         )
   5142         .expect("build order request event");
   5143         let request_event = event_from_parts(
   5144             "buyer-order-decline-request-event",
   5145             buyer_pubkey,
   5146             request_parts,
   5147         );
   5148         events
   5149             .append_record(&signed_order_event_record(
   5150                 "app:signed_event:order-request:buyer-declined",
   5151                 &request_event,
   5152                 listing_addr.as_str(),
   5153                 SourceRuntime::App,
   5154                 Some("acct_buyer"),
   5155             ))
   5156             .expect("append app order request");
   5157 
   5158         let request_report = app_store
   5159             .import_shared_local_events_from_store(&events)
   5160             .expect("import app order request");
   5161         let buyer_context = BuyerContext::account("acct_buyer");
   5162         let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   5163         let buyer_orders = app_store
   5164             .load_buyer_orders(&buyer_context)
   5165             .expect("load buyer orders after request");
   5166 
   5167         assert_eq!(request_report.imported_records, 1);
   5168         assert_eq!(buyer_orders.rows.len(), 1);
   5169         assert_eq!(buyer_orders.rows[0].order_id, order_id);
   5170         assert_eq!(buyer_orders.rows[0].status, BuyerOrderStatus::Placed);
   5171 
   5172         let decision_payload = declined_order_decision_payload(
   5173             order_id_raw,
   5174             listing_addr.as_str(),
   5175             buyer_pubkey,
   5176             seller_pubkey,
   5177         );
   5178         let decision_parts = order_decision_event_build(
   5179             &typed_event_id(request_event.id.as_str()),
   5180             &typed_event_id(request_event.id.as_str()),
   5181             &decision_payload,
   5182         )
   5183         .expect("build declined order decision event");
   5184         let decision_event = event_from_parts(
   5185             "buyer-order-decline-decision-event",
   5186             seller_pubkey,
   5187             decision_parts,
   5188         );
   5189         events
   5190             .append_record(&signed_order_event_record(
   5191                 "cli:signed_event:order-decision:buyer-declined",
   5192                 &decision_event,
   5193                 listing_addr.as_str(),
   5194                 SourceRuntime::Cli,
   5195                 None,
   5196             ))
   5197             .expect("append declined order decision");
   5198 
   5199         let decision_report = app_store
   5200             .import_shared_local_events_from_store(&events)
   5201             .expect("import declined order decision");
   5202         let buyer_orders = app_store
   5203             .load_buyer_orders(&buyer_context)
   5204             .expect("load buyer orders after declined decision");
   5205         let buyer_detail = app_store
   5206             .load_buyer_order_detail(&buyer_context, order_id)
   5207             .expect("load buyer order detail")
   5208             .expect("buyer order detail");
   5209         let seller_orders = app_store
   5210             .load_orders_list(
   5211                 deterministic_farm_id(Some(seller_pubkey), farm_key),
   5212                 &OrdersScreenQueryState {
   5213                     filter: OrdersFilter::All,
   5214                     fulfillment_window_id: None,
   5215                 },
   5216             )
   5217             .expect("load seller orders after declined decision");
   5218 
   5219         assert_eq!(decision_report.imported_records, 1);
   5220         assert_eq!(buyer_orders.rows.len(), 1);
   5221         assert_eq!(buyer_orders.rows[0].status, BuyerOrderStatus::Declined);
   5222         assert_eq!(buyer_detail.status, BuyerOrderStatus::Declined);
   5223         assert_eq!(seller_orders.rows[0].status, OrderStatus::Declined);
   5224         assert_eq!(seller_orders.summary.needs_action_orders, 0);
   5225         assert_eq!(seller_orders.summary.scheduled_orders, 0);
   5226         assert_eq!(seller_orders.summary.packed_orders, 0);
   5227         assert!(seller_orders.rows[0].primary_action.is_none());
   5228     }
   5229 
   5230     #[test]
   5231     fn active_order_decision_projects_agreement_state_through_cli_reducer() {
   5232         let app_store =
   5233             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   5234         let events = local_events_store();
   5235         let farm_key = "DDDDDDDDDDDDDDDDDDDDDD";
   5236         let listing_key = "AAAAAAAAAAAAAAAAAAAAAw";
   5237         let seller_pubkey = test_pubkey("seller-pubkey");
   5238         let seller_pubkey = seller_pubkey.as_str();
   5239         let buyer_pubkey = test_pubkey("app-buyer-pubkey");
   5240         let buyer_pubkey = buyer_pubkey.as_str();
   5241         let order_id_raw = "active-lifecycle-order-1";
   5242         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   5243         events
   5244             .append_record(&signed_market_listing_record(
   5245                 "active-lifecycle-listing",
   5246                 seller_pubkey,
   5247                 farm_key,
   5248                 listing_key,
   5249                 "Lifecycle Eggs",
   5250                 "9",
   5251                 "active",
   5252                 "pickup",
   5253                 "North barn pickup",
   5254                 4_102_444_800,
   5255                 4_102_531_200,
   5256                 LocalRecordStatus::Published,
   5257                 PublishOutboxStatus::Acknowledged,
   5258             ))
   5259             .expect("append signed listing");
   5260         app_store
   5261             .import_shared_local_events_from_store(&events)
   5262             .expect("import signed listing");
   5263 
   5264         let request_payload = order_request_payload(
   5265             order_id_raw,
   5266             listing_addr.as_str(),
   5267             buyer_pubkey,
   5268             seller_pubkey,
   5269         );
   5270         let request_parts = order_request_event_build(
   5271             &listing_event_ptr("active-lifecycle-listing-event"),
   5272             &request_payload,
   5273         )
   5274         .expect("build lifecycle order request");
   5275         let request_event = event_from_parts(
   5276             "active-lifecycle-request-event",
   5277             buyer_pubkey,
   5278             request_parts,
   5279         );
   5280         events
   5281             .append_record(&signed_order_event_record(
   5282                 "app:signed_event:active-lifecycle:request",
   5283                 &request_event,
   5284                 listing_addr.as_str(),
   5285                 SourceRuntime::App,
   5286                 Some("acct_lifecycle"),
   5287             ))
   5288             .expect("append lifecycle order request");
   5289         app_store
   5290             .import_shared_local_events_from_store(&events)
   5291             .expect("import lifecycle order request");
   5292 
   5293         let seller_farm_id = deterministic_farm_id(Some(seller_pubkey), farm_key);
   5294         let decision_payload = accepted_order_decision_payload(
   5295             order_id_raw,
   5296             listing_addr.as_str(),
   5297             buyer_pubkey,
   5298             seller_pubkey,
   5299         );
   5300         let decision_parts = order_decision_event_build(
   5301             &typed_event_id(request_event.id.as_str()),
   5302             &typed_event_id(request_event.id.as_str()),
   5303             &decision_payload,
   5304         )
   5305         .expect("build lifecycle order decision");
   5306         let decision_event = event_from_parts(
   5307             "active-lifecycle-decision-event",
   5308             seller_pubkey,
   5309             decision_parts,
   5310         );
   5311         events
   5312             .append_record(&signed_order_event_record(
   5313                 "cli:signed_event:active-lifecycle:decision",
   5314                 &decision_event,
   5315                 listing_addr.as_str(),
   5316                 SourceRuntime::Cli,
   5317                 None,
   5318             ))
   5319             .expect("append lifecycle order decision");
   5320         app_store
   5321             .import_shared_local_events_from_store(&events)
   5322             .expect("import lifecycle order decision");
   5323         let seller_orders = app_store
   5324             .load_orders_list(
   5325                 seller_farm_id,
   5326                 &OrdersScreenQueryState {
   5327                     filter: OrdersFilter::All,
   5328                     fulfillment_window_id: None,
   5329                 },
   5330             )
   5331             .expect("load lifecycle seller orders after decision");
   5332         assert_eq!(seller_orders.rows[0].status, OrderStatus::Scheduled);
   5333         assert_eq!(
   5334             seller_orders.rows[0].workflow.inventory,
   5335             TradeInventoryStatus::Reserved
   5336         );
   5337         assert_eq!(seller_orders.rows[0].primary_action, None);
   5338     }
   5339 
   5340     #[test]
   5341     fn validation_receipts_project_passively_on_buyer_and_seller_order_details() {
   5342         let fixture = validation_receipt_order_fixture("validation-receipt-passive");
   5343         let valid_event = validation_receipt_event(
   5344             hex_event_id(31).as_str(),
   5345             fixture.seller_pubkey.as_str(),
   5346             fixture.order_id_raw.as_str(),
   5347             fixture.listing_event_id.as_str(),
   5348             fixture.request_event_id.as_str(),
   5349             fixture.decision_event_id.as_str(),
   5350             RadrootsValidationReceiptResult::Valid,
   5351             1_777_665_603,
   5352         );
   5353         let invalid_event = validation_receipt_event(
   5354             hex_event_id(32).as_str(),
   5355             fixture.seller_pubkey.as_str(),
   5356             fixture.order_id_raw.as_str(),
   5357             fixture.listing_event_id.as_str(),
   5358             fixture.request_event_id.as_str(),
   5359             fixture.decision_event_id.as_str(),
   5360             RadrootsValidationReceiptResult::Invalid,
   5361             1_777_665_604,
   5362         );
   5363         let duplicate_valid_event = valid_event.clone();
   5364         fixture
   5365             .events
   5366             .append_record(&signed_order_event_record(
   5367                 "cli:signed_event:validation-receipt:valid",
   5368                 &valid_event,
   5369                 fixture.listing_addr.as_str(),
   5370                 SourceRuntime::Cli,
   5371                 None,
   5372             ))
   5373             .expect("append valid validation receipt");
   5374         fixture
   5375             .events
   5376             .append_record(&signed_order_event_record(
   5377                 "cli:signed_event:validation-receipt:invalid",
   5378                 &invalid_event,
   5379                 fixture.listing_addr.as_str(),
   5380                 SourceRuntime::Cli,
   5381                 None,
   5382             ))
   5383             .expect("append invalid validation receipt");
   5384         fixture
   5385             .events
   5386             .append_record(&signed_order_event_record(
   5387                 "cli:signed_event:validation-receipt:valid-duplicate",
   5388                 &duplicate_valid_event,
   5389                 fixture.listing_addr.as_str(),
   5390                 SourceRuntime::Cli,
   5391                 None,
   5392             ))
   5393             .expect("append duplicate validation receipt");
   5394         fixture
   5395             .app_store
   5396             .import_shared_local_events_from_store(&fixture.events)
   5397             .expect("import validation receipts");
   5398 
   5399         let buyer_detail = fixture
   5400             .app_store
   5401             .load_buyer_order_detail(&fixture.buyer_context, fixture.order_id)
   5402             .expect("load buyer validation receipt detail")
   5403             .expect("buyer validation receipt detail");
   5404         let seller_detail = fixture
   5405             .app_store
   5406             .load_order_detail(fixture.seller_farm_id, fixture.order_id)
   5407             .expect("load seller validation receipt detail")
   5408             .expect("seller validation receipt detail");
   5409         let imports = fixture
   5410             .app_store
   5411             .load_local_interop_records()
   5412             .expect("load validation receipt imports");
   5413 
   5414         assert_eq!(buyer_detail.status, BuyerOrderStatus::Scheduled);
   5415         assert_eq!(seller_detail.status, OrderStatus::Scheduled);
   5416         assert_eq!(seller_detail.primary_action, None);
   5417         assert_eq!(buyer_detail.validation_receipts.len(), 2);
   5418         assert_eq!(
   5419             buyer_detail.validation_receipts,
   5420             seller_detail.validation_receipts
   5421         );
   5422         assert_eq!(
   5423             buyer_detail.validation_receipts[0].event_id,
   5424             invalid_event.id
   5425         );
   5426         assert_eq!(
   5427             buyer_detail.validation_receipts[0].result,
   5428             TradeValidationReceiptResult::NeedsReview
   5429         );
   5430         assert_eq!(
   5431             buyer_detail.validation_receipts[0].receipt_type,
   5432             TradeValidationReceiptType::TradeTransition
   5433         );
   5434         assert_eq!(
   5435             buyer_detail.validation_receipts[0].proof_system,
   5436             TradeValidationReceiptProofSystem::None
   5437         );
   5438         assert_eq!(
   5439             buyer_detail.validation_receipts[0].target_event_id,
   5440             fixture.decision_event_id
   5441         );
   5442         assert_eq!(
   5443             buyer_detail.validation_receipts[0].event_set_root,
   5444             hash32(42)
   5445         );
   5446         assert_eq!(
   5447             buyer_detail.validation_receipts[0].reducer_output_root,
   5448             hash32(43)
   5449         );
   5450         assert_eq!(
   5451             buyer_detail.validation_receipts[0].public_values_hash,
   5452             hash32(45)
   5453         );
   5454         assert_eq!(
   5455             buyer_detail.validation_receipts[0].recorded_at,
   5456             1_777_665_604
   5457         );
   5458         assert_eq!(buyer_detail.validation_receipts[1].event_id, valid_event.id);
   5459         assert_eq!(
   5460             buyer_detail.validation_receipts[1].result,
   5461             TradeValidationReceiptResult::Valid
   5462         );
   5463         assert!(
   5464             imports
   5465                 .iter()
   5466                 .any(|record| record.projected_kind == "validation_receipt"
   5467                     && record.event_kind == Some(KIND_VALIDATION_RECEIPT)
   5468                     && record.event_id.as_deref() == Some(invalid_event.id.as_str()))
   5469         );
   5470     }
   5471 
   5472     #[test]
   5473     fn validation_receipt_import_before_order_request_attaches_when_request_arrives() {
   5474         let app_store =
   5475             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   5476         let events = local_events_store();
   5477         let farm_key = "DDDDDDDDDDDDDDDDDDDDDD";
   5478         let listing_key = "AAAAAAAAAAAAAAAAAAAAAw";
   5479         let seller_pubkey = test_pubkey("validation-out-of-order-seller");
   5480         let seller_pubkey = seller_pubkey.as_str();
   5481         let buyer_pubkey = test_pubkey("validation-out-of-order-buyer");
   5482         let buyer_pubkey = buyer_pubkey.as_str();
   5483         let order_id_raw = "validation-out-of-order";
   5484         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   5485         let listing_event_id = hex_event_id(51);
   5486         let request_event_id = hex_event_id(52);
   5487         let target_event_id = hex_event_id(53);
   5488         events
   5489             .append_record(&signed_market_listing_record(
   5490                 "validation-out-of-order-listing",
   5491                 seller_pubkey,
   5492                 farm_key,
   5493                 listing_key,
   5494                 "Validation Eggs",
   5495                 "9",
   5496                 "active",
   5497                 "pickup",
   5498                 "North barn pickup",
   5499                 4_102_444_800,
   5500                 4_102_531_200,
   5501                 LocalRecordStatus::Published,
   5502                 PublishOutboxStatus::Acknowledged,
   5503             ))
   5504             .expect("append out-of-order listing");
   5505         app_store
   5506             .import_shared_local_events_from_store(&events)
   5507             .expect("import out-of-order listing");
   5508 
   5509         let receipt_event = validation_receipt_event(
   5510             hex_event_id(54).as_str(),
   5511             seller_pubkey,
   5512             order_id_raw,
   5513             listing_event_id.as_str(),
   5514             request_event_id.as_str(),
   5515             target_event_id.as_str(),
   5516             RadrootsValidationReceiptResult::Valid,
   5517             1_777_665_603,
   5518         );
   5519         events
   5520             .append_record(&signed_order_event_record(
   5521                 "cli:signed_event:validation-receipt:before-request",
   5522                 &receipt_event,
   5523                 listing_addr.as_str(),
   5524                 SourceRuntime::Cli,
   5525                 None,
   5526             ))
   5527             .expect("append receipt before request");
   5528         app_store
   5529             .import_shared_local_events_from_store(&events)
   5530             .expect("import receipt before request");
   5531 
   5532         let pending_count: i64 = app_store
   5533             .connection()
   5534             .query_row(
   5535                 "SELECT count(*) FROM order_validation_receipts WHERE order_id IS NULL",
   5536                 [],
   5537                 |row| row.get(0),
   5538             )
   5539             .expect("count pending validation receipts");
   5540         assert_eq!(pending_count, 1);
   5541 
   5542         let request_payload = order_request_payload(
   5543             order_id_raw,
   5544             listing_addr.as_str(),
   5545             buyer_pubkey,
   5546             seller_pubkey,
   5547         );
   5548         let request_parts = order_request_event_build(
   5549             &listing_event_ptr(listing_event_id.as_str()),
   5550             &request_payload,
   5551         )
   5552         .expect("build request after validation receipt");
   5553         let request_event = event_from_parts_at(
   5554             request_event_id.as_str(),
   5555             buyer_pubkey,
   5556             request_parts,
   5557             1_777_665_604,
   5558         );
   5559         events
   5560             .append_record(&signed_order_event_record(
   5561                 "app:signed_event:validation-receipt:request-after",
   5562                 &request_event,
   5563                 listing_addr.as_str(),
   5564                 SourceRuntime::App,
   5565                 Some("acct_validation_out_of_order"),
   5566             ))
   5567             .expect("append request after receipt");
   5568         app_store
   5569             .import_shared_local_events_from_store(&events)
   5570             .expect("import request after receipt");
   5571 
   5572         let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   5573         let buyer_context = BuyerContext::account("acct_validation_out_of_order");
   5574         let buyer_detail = app_store
   5575             .load_buyer_order_detail(&buyer_context, order_id)
   5576             .expect("load attached buyer validation receipt detail")
   5577             .expect("attached buyer validation receipt detail");
   5578         let seller_detail = app_store
   5579             .load_order_detail(
   5580                 deterministic_farm_id(Some(seller_pubkey), farm_key),
   5581                 order_id,
   5582             )
   5583             .expect("load attached seller validation receipt detail")
   5584             .expect("attached seller validation receipt detail");
   5585 
   5586         assert_eq!(buyer_detail.validation_receipts.len(), 1);
   5587         assert_eq!(
   5588             buyer_detail.validation_receipts,
   5589             seller_detail.validation_receipts
   5590         );
   5591         assert_eq!(
   5592             buyer_detail.validation_receipts[0].event_id,
   5593             receipt_event.id
   5594         );
   5595         assert_eq!(buyer_detail.status, BuyerOrderStatus::Placed);
   5596         assert_eq!(seller_detail.status, OrderStatus::NeedsAction);
   5597     }
   5598 
   5599     #[test]
   5600     fn validation_receipt_invalid_candidates_do_not_surface_as_order_evidence() {
   5601         let fixture = validation_receipt_order_fixture("validation-receipt-invalid-candidates");
   5602         let mut mismatched_tag_event = validation_receipt_event(
   5603             hex_event_id(61).as_str(),
   5604             fixture.seller_pubkey.as_str(),
   5605             fixture.order_id_raw.as_str(),
   5606             fixture.listing_event_id.as_str(),
   5607             fixture.request_event_id.as_str(),
   5608             fixture.decision_event_id.as_str(),
   5609             RadrootsValidationReceiptResult::Valid,
   5610             1_777_665_603,
   5611         );
   5612         if let Some(tag) = mismatched_tag_event
   5613             .tags
   5614             .iter_mut()
   5615             .find(|tag| tag.first().map(String::as_str) == Some("event_set_root"))
   5616         {
   5617             tag[1] = hash32(99);
   5618         }
   5619         let wrong_order_event = validation_receipt_event(
   5620             hex_event_id(62).as_str(),
   5621             fixture.seller_pubkey.as_str(),
   5622             "wrong-order-id",
   5623             fixture.listing_event_id.as_str(),
   5624             fixture.request_event_id.as_str(),
   5625             fixture.decision_event_id.as_str(),
   5626             RadrootsValidationReceiptResult::Valid,
   5627             1_777_665_604,
   5628         );
   5629         let mut buyer_kind_candidate = validation_receipt_event(
   5630             hex_event_id(63).as_str(),
   5631             fixture.buyer_pubkey.as_str(),
   5632             fixture.order_id_raw.as_str(),
   5633             fixture.listing_event_id.as_str(),
   5634             fixture.request_event_id.as_str(),
   5635             fixture.decision_event_id.as_str(),
   5636             RadrootsValidationReceiptResult::Valid,
   5637             1_777_665_605,
   5638         );
   5639         buyer_kind_candidate.kind = KIND_ORDER_REQUEST as u32;
   5640 
   5641         for (record_id, event) in [
   5642             (
   5643                 "cli:signed_event:validation-receipt:mismatched-tag",
   5644                 &mismatched_tag_event,
   5645             ),
   5646             (
   5647                 "cli:signed_event:validation-receipt:wrong-order",
   5648                 &wrong_order_event,
   5649             ),
   5650             (
   5651                 "cli:signed_event:validation-receipt:buyer-kind",
   5652                 &buyer_kind_candidate,
   5653             ),
   5654         ] {
   5655             fixture
   5656                 .events
   5657                 .append_record(&signed_order_event_record(
   5658                     record_id,
   5659                     event,
   5660                     fixture.listing_addr.as_str(),
   5661                     SourceRuntime::Cli,
   5662                     None,
   5663                 ))
   5664                 .expect("append invalid validation receipt candidate");
   5665         }
   5666         fixture
   5667             .app_store
   5668             .import_shared_local_events_from_store(&fixture.events)
   5669             .expect("import invalid validation receipt candidates");
   5670 
   5671         let buyer_detail = fixture
   5672             .app_store
   5673             .load_buyer_order_detail(&fixture.buyer_context, fixture.order_id)
   5674             .expect("load buyer detail after invalid validation receipt candidates")
   5675             .expect("buyer detail after invalid validation receipt candidates");
   5676         let seller_detail = fixture
   5677             .app_store
   5678             .load_order_detail(fixture.seller_farm_id, fixture.order_id)
   5679             .expect("load seller detail after invalid validation receipt candidates")
   5680             .expect("seller detail after invalid validation receipt candidates");
   5681 
   5682         assert!(buyer_detail.validation_receipts.is_empty());
   5683         assert!(seller_detail.validation_receipts.is_empty());
   5684         assert_eq!(buyer_detail.status, BuyerOrderStatus::Scheduled);
   5685         assert_eq!(seller_detail.status, OrderStatus::Scheduled);
   5686         assert_eq!(seller_detail.primary_action, None);
   5687     }
   5688 
   5689     #[test]
   5690     fn active_order_revision_projects_through_cli_reducer_state() {
   5691         let app_store =
   5692             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   5693         let events = local_events_store();
   5694         let farm_key = "EEEEEEEEEEEEEEEEEEEEEE";
   5695         let listing_key = "AAAAAAAAAAAAAAAAAAAAAw";
   5696         let seller_pubkey = test_pubkey("seller-pubkey");
   5697         let seller_pubkey = seller_pubkey.as_str();
   5698         let buyer_pubkey = test_pubkey("app-buyer-pubkey");
   5699         let buyer_pubkey = buyer_pubkey.as_str();
   5700         let order_id_raw = "active-revision-order-1";
   5701         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   5702         events
   5703             .append_record(&signed_market_listing_record(
   5704                 "active-revision-listing",
   5705                 seller_pubkey,
   5706                 farm_key,
   5707                 listing_key,
   5708                 "Revision Eggs",
   5709                 "9",
   5710                 "active",
   5711                 "pickup",
   5712                 "North barn pickup",
   5713                 4_102_444_800,
   5714                 4_102_531_200,
   5715                 LocalRecordStatus::Published,
   5716                 PublishOutboxStatus::Acknowledged,
   5717             ))
   5718             .expect("append revision listing");
   5719         app_store
   5720             .import_shared_local_events_from_store(&events)
   5721             .expect("import revision listing");
   5722 
   5723         let request_payload = order_request_payload(
   5724             order_id_raw,
   5725             listing_addr.as_str(),
   5726             buyer_pubkey,
   5727             seller_pubkey,
   5728         );
   5729         let request_parts = order_request_event_build(
   5730             &listing_event_ptr("active-revision-listing-event"),
   5731             &request_payload,
   5732         )
   5733         .expect("build revision order request");
   5734         let request_event =
   5735             event_from_parts("active-revision-request-event", buyer_pubkey, request_parts);
   5736         events
   5737             .append_record(&signed_order_event_record(
   5738                 "app:signed_event:active-revision:request",
   5739                 &request_event,
   5740                 listing_addr.as_str(),
   5741                 SourceRuntime::App,
   5742                 Some("acct_revision"),
   5743             ))
   5744             .expect("append revision order request");
   5745         app_store
   5746             .import_shared_local_events_from_store(&events)
   5747             .expect("import revision order request");
   5748 
   5749         let proposal_payload = revision_proposal_payload(
   5750             "revision-1",
   5751             order_id_raw,
   5752             listing_addr.as_str(),
   5753             buyer_pubkey,
   5754             seller_pubkey,
   5755             request_event.id.as_str(),
   5756             request_event.id.as_str(),
   5757         );
   5758         let proposal_parts = order_revision_proposal_event_build(
   5759             &typed_event_id(request_event.id.as_str()),
   5760             &typed_event_id(request_event.id.as_str()),
   5761             &proposal_payload,
   5762         )
   5763         .expect("build revision proposal");
   5764         let proposal_event = event_from_parts(
   5765             "active-revision-proposal-event",
   5766             seller_pubkey,
   5767             proposal_parts,
   5768         );
   5769         events
   5770             .append_record(&signed_order_event_record(
   5771                 "cli:signed_event:active-revision:proposal",
   5772                 &proposal_event,
   5773                 listing_addr.as_str(),
   5774                 SourceRuntime::Cli,
   5775                 None,
   5776             ))
   5777             .expect("append revision proposal");
   5778         app_store
   5779             .import_shared_local_events_from_store(&events)
   5780             .expect("import revision proposal");
   5781 
   5782         let seller_farm_id = deterministic_farm_id(Some(seller_pubkey), farm_key);
   5783         let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   5784         let buyer_context = BuyerContext::account("acct_revision");
   5785         let seller_orders = app_store
   5786             .load_orders_list(
   5787                 seller_farm_id,
   5788                 &OrdersScreenQueryState {
   5789                     filter: OrdersFilter::All,
   5790                     fulfillment_window_id: None,
   5791                 },
   5792             )
   5793             .expect("load revision seller orders after proposal");
   5794         assert_eq!(seller_orders.rows[0].status, OrderStatus::NeedsAction);
   5795         assert_eq!(
   5796             seller_orders.rows[0].workflow.revision,
   5797             TradeRevisionStatus::ChangeProposed
   5798         );
   5799         let buyer_detail = app_store
   5800             .load_buyer_order_detail(&buyer_context, order_id)
   5801             .expect("load revision buyer detail after proposal")
   5802             .expect("revision buyer detail after proposal");
   5803         assert_eq!(
   5804             buyer_detail.workflow.revision,
   5805             TradeRevisionStatus::ChangeProposed
   5806         );
   5807         assert_eq!(buyer_detail.economics.total_minor_units, Some(1600));
   5808 
   5809         let revision_decision_payload = revision_decision_payload(
   5810             "revision-1",
   5811             order_id_raw,
   5812             listing_addr.as_str(),
   5813             buyer_pubkey,
   5814             seller_pubkey,
   5815             request_event.id.as_str(),
   5816             proposal_event.id.as_str(),
   5817             RadrootsOrderRevisionOutcome::Accepted,
   5818         );
   5819         let revision_decision_parts = order_revision_decision_event_build(
   5820             &typed_event_id(request_event.id.as_str()),
   5821             &typed_event_id(proposal_event.id.as_str()),
   5822             &revision_decision_payload,
   5823         )
   5824         .expect("build revision decision");
   5825         let revision_decision_event = event_from_parts(
   5826             "active-revision-decision-response-event",
   5827             buyer_pubkey,
   5828             revision_decision_parts,
   5829         );
   5830         events
   5831             .append_record(&signed_order_event_record(
   5832                 "app:signed_event:active-revision:decision-response",
   5833                 &revision_decision_event,
   5834                 listing_addr.as_str(),
   5835                 SourceRuntime::App,
   5836                 Some("acct_revision"),
   5837             ))
   5838             .expect("append revision decision");
   5839         app_store
   5840             .import_shared_local_events_from_store(&events)
   5841             .expect("import revision decision");
   5842         let seller_orders = app_store
   5843             .load_orders_list(
   5844                 seller_farm_id,
   5845                 &OrdersScreenQueryState {
   5846                     filter: OrdersFilter::All,
   5847                     fulfillment_window_id: None,
   5848                 },
   5849             )
   5850             .expect("load revision seller orders after decision");
   5851         assert_eq!(seller_orders.rows[0].status, OrderStatus::Scheduled);
   5852         assert_eq!(
   5853             seller_orders.rows[0].workflow.revision,
   5854             TradeRevisionStatus::Updated
   5855         );
   5856         let seller_detail = app_store
   5857             .load_order_detail(seller_farm_id, order_id)
   5858             .expect("load revision seller detail after decision")
   5859             .expect("revision seller detail after decision");
   5860         let buyer_detail = app_store
   5861             .load_buyer_order_detail(&buyer_context, order_id)
   5862             .expect("load revision buyer detail after decision")
   5863             .expect("revision buyer detail after decision");
   5864         assert_eq!(
   5865             seller_detail.workflow.revision,
   5866             TradeRevisionStatus::Updated
   5867         );
   5868         assert_eq!(seller_detail.economics.total_minor_units, Some(2400));
   5869         assert_eq!(buyer_detail.workflow.revision, TradeRevisionStatus::Updated);
   5870         assert_eq!(buyer_detail.economics.total_minor_units, Some(2400));
   5871     }
   5872 
   5873     #[test]
   5874     fn active_order_pre_agreement_cancellation_projects_through_cli_reducer_state() {
   5875         let app_store =
   5876             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   5877         let events = local_events_store();
   5878         let farm_key = "EEEEEEEEEEEEEEEEEEEEEE";
   5879         let listing_key = "AAAAAAAAAAAAAAAAAAAAAx";
   5880         let seller_pubkey = test_pubkey("seller-pubkey");
   5881         let seller_pubkey = seller_pubkey.as_str();
   5882         let buyer_pubkey = test_pubkey("app-buyer-pubkey");
   5883         let buyer_pubkey = buyer_pubkey.as_str();
   5884         let order_id_raw = "active-cancel-order-1";
   5885         let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   5886         events
   5887             .append_record(&signed_market_listing_record(
   5888                 "active-cancel-listing",
   5889                 seller_pubkey,
   5890                 farm_key,
   5891                 listing_key,
   5892                 "Cancellation Eggs",
   5893                 "9",
   5894                 "active",
   5895                 "pickup",
   5896                 "North barn pickup",
   5897                 4_102_444_800,
   5898                 4_102_531_200,
   5899                 LocalRecordStatus::Published,
   5900                 PublishOutboxStatus::Acknowledged,
   5901             ))
   5902             .expect("append cancellation listing");
   5903         app_store
   5904             .import_shared_local_events_from_store(&events)
   5905             .expect("import cancellation listing");
   5906 
   5907         let request_payload = order_request_payload(
   5908             order_id_raw,
   5909             listing_addr.as_str(),
   5910             buyer_pubkey,
   5911             seller_pubkey,
   5912         );
   5913         let request_parts = order_request_event_build(
   5914             &listing_event_ptr("active-cancel-listing-event"),
   5915             &request_payload,
   5916         )
   5917         .expect("build cancellation order request");
   5918         let request_event =
   5919             event_from_parts("active-cancel-request-event", buyer_pubkey, request_parts);
   5920         events
   5921             .append_record(&signed_order_event_record(
   5922                 "app:signed_event:active-cancel:request",
   5923                 &request_event,
   5924                 listing_addr.as_str(),
   5925                 SourceRuntime::App,
   5926                 Some("acct_cancel"),
   5927             ))
   5928             .expect("append cancellation order request");
   5929         app_store
   5930             .import_shared_local_events_from_store(&events)
   5931             .expect("import cancellation order request");
   5932 
   5933         let cancel_payload = order_cancel_payload(
   5934             order_id_raw,
   5935             listing_addr.as_str(),
   5936             buyer_pubkey,
   5937             seller_pubkey,
   5938         );
   5939         let cancel_parts = order_cancellation_event_build(
   5940             &typed_event_id(request_event.id.as_str()),
   5941             &typed_event_id(request_event.id.as_str()),
   5942             &cancel_payload,
   5943         )
   5944         .expect("build cancellation");
   5945         let cancel_event = event_from_parts("active-cancel-event", buyer_pubkey, cancel_parts);
   5946         events
   5947             .append_record(&signed_order_event_record(
   5948                 "app:signed_event:active-cancel:cancel",
   5949                 &cancel_event,
   5950                 listing_addr.as_str(),
   5951                 SourceRuntime::App,
   5952                 Some("acct_cancel"),
   5953             ))
   5954             .expect("append cancellation");
   5955         let cancel_report = app_store
   5956             .import_shared_local_events_from_store(&events)
   5957             .expect("import cancellation");
   5958 
   5959         let seller_farm_id = deterministic_farm_id(Some(seller_pubkey), farm_key);
   5960         let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   5961         let buyer_context = BuyerContext::account("acct_cancel");
   5962         let buyer_detail = app_store
   5963             .load_buyer_order_detail(&buyer_context, order_id)
   5964             .expect("load cancellation buyer detail")
   5965             .expect("cancellation buyer detail");
   5966         let seller_orders = app_store
   5967             .load_orders_list(
   5968                 seller_farm_id,
   5969                 &OrdersScreenQueryState {
   5970                     filter: OrdersFilter::All,
   5971                     fulfillment_window_id: None,
   5972                 },
   5973             )
   5974             .expect("load cancellation seller orders");
   5975 
   5976         assert_eq!(cancel_report.imported_records, 1);
   5977         assert_eq!(buyer_detail.status, BuyerOrderStatus::Declined);
   5978         assert_eq!(
   5979             buyer_detail.workflow.agreement,
   5980             TradeAgreementStatus::Cancelled
   5981         );
   5982         assert_eq!(seller_orders.rows[0].status, OrderStatus::Declined);
   5983         assert_eq!(
   5984             seller_orders.rows[0].workflow.agreement,
   5985             TradeAgreementStatus::Cancelled
   5986         );
   5987         assert_eq!(seller_orders.rows[0].primary_action, None);
   5988     }
   5989 
   5990     #[test]
   5991     fn conflicting_order_decisions_project_to_needs_action_deterministically() {
   5992         let run_case = |accepted_first: bool| {
   5993             let app_store =
   5994                 AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   5995             let events = local_events_store();
   5996             let farm_key = "FFFFFFFFFFFFFFFFFFFFFF";
   5997             let listing_key = "AAAAAAAAAAAAAAAAAAAAAw";
   5998             let seller_pubkey = test_pubkey("seller-pubkey");
   5999             let seller_pubkey = seller_pubkey.as_str();
   6000             let buyer_pubkey = test_pubkey("app-buyer-pubkey");
   6001             let buyer_pubkey = buyer_pubkey.as_str();
   6002             let order_id_raw = if accepted_first {
   6003                 "active-conflict-order-accepted-first"
   6004             } else {
   6005                 "active-conflict-order-declined-first"
   6006             };
   6007             let listing_addr = format!("30402:{seller_pubkey}:{listing_key}");
   6008             events
   6009                 .append_record(&signed_market_listing_record(
   6010                     "active-conflict-listing",
   6011                     seller_pubkey,
   6012                     farm_key,
   6013                     listing_key,
   6014                     "Conflict Eggs",
   6015                     "9",
   6016                     "active",
   6017                     "pickup",
   6018                     "North barn pickup",
   6019                     4_102_444_800,
   6020                     4_102_531_200,
   6021                     LocalRecordStatus::Published,
   6022                     PublishOutboxStatus::Acknowledged,
   6023                 ))
   6024                 .expect("append conflict listing");
   6025             let request_payload = order_request_payload(
   6026                 order_id_raw,
   6027                 listing_addr.as_str(),
   6028                 buyer_pubkey,
   6029                 seller_pubkey,
   6030             );
   6031             let request_parts = order_request_event_build(
   6032                 &listing_event_ptr("active-conflict-listing-event"),
   6033                 &request_payload,
   6034             )
   6035             .expect("build conflict request");
   6036             let request_event =
   6037                 event_from_parts("active-conflict-request-event", buyer_pubkey, request_parts);
   6038             events
   6039                 .append_record(&signed_order_event_record(
   6040                     "app:signed_event:active-conflict:request",
   6041                     &request_event,
   6042                     listing_addr.as_str(),
   6043                     SourceRuntime::App,
   6044                     Some("acct_conflict"),
   6045                 ))
   6046                 .expect("append conflict request");
   6047             let accepted_payload = accepted_order_decision_payload(
   6048                 order_id_raw,
   6049                 listing_addr.as_str(),
   6050                 buyer_pubkey,
   6051                 seller_pubkey,
   6052             );
   6053             let accepted_parts = order_decision_event_build(
   6054                 &typed_event_id(request_event.id.as_str()),
   6055                 &typed_event_id(request_event.id.as_str()),
   6056                 &accepted_payload,
   6057             )
   6058             .expect("build accepted conflict decision");
   6059             let accepted_event = event_from_parts(
   6060                 "active-conflict-accepted-event",
   6061                 seller_pubkey,
   6062                 accepted_parts,
   6063             );
   6064             let declined_payload = declined_order_decision_payload(
   6065                 order_id_raw,
   6066                 listing_addr.as_str(),
   6067                 buyer_pubkey,
   6068                 seller_pubkey,
   6069             );
   6070             let declined_parts = order_decision_event_build(
   6071                 &typed_event_id(request_event.id.as_str()),
   6072                 &typed_event_id(request_event.id.as_str()),
   6073                 &declined_payload,
   6074             )
   6075             .expect("build declined conflict decision");
   6076             let declined_event = event_from_parts(
   6077                 "active-conflict-declined-event",
   6078                 seller_pubkey,
   6079                 declined_parts,
   6080             );
   6081             let ordered_events = if accepted_first {
   6082                 [accepted_event, declined_event]
   6083             } else {
   6084                 [declined_event, accepted_event]
   6085             };
   6086             for (index, event) in ordered_events.iter().enumerate() {
   6087                 events
   6088                     .append_record(&signed_order_event_record(
   6089                         &format!("cli:signed_event:active-conflict:decision:{index}"),
   6090                         event,
   6091                         listing_addr.as_str(),
   6092                         SourceRuntime::Cli,
   6093                         None,
   6094                     ))
   6095                     .expect("append conflict decision");
   6096             }
   6097 
   6098             app_store
   6099                 .import_shared_local_events_from_store(&events)
   6100                 .expect("import conflicting decisions");
   6101             let order_id = projected_order_id(order_id_raw, buyer_pubkey);
   6102             let detail = app_store
   6103                 .load_order_detail(
   6104                     deterministic_farm_id(Some(seller_pubkey), farm_key),
   6105                     order_id,
   6106                 )
   6107                 .expect("load conflict order detail")
   6108                 .expect("conflict order detail");
   6109             detail.status
   6110         };
   6111 
   6112         assert_eq!(run_case(true), OrderStatus::NeedsAction);
   6113         assert_eq!(run_case(false), OrderStatus::NeedsAction);
   6114     }
   6115 
   6116     #[test]
   6117     fn malformed_order_event_remains_signed_event_evidence_without_projection() {
   6118         let app_store =
   6119             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6120         let events = local_events_store();
   6121         events
   6122             .append_record(&LocalEventRecordInput {
   6123                 record_id: "cli:signed_event:order-request:malformed".to_owned(),
   6124                 family: LocalRecordFamily::SignedEvent,
   6125                 status: LocalRecordStatus::Published,
   6126                 source_runtime: SourceRuntime::Cli,
   6127                 created_at_ms: 1100,
   6128                 inserted_at_ms: 1101,
   6129                 owner_account_id: None,
   6130                 owner_pubkey: Some("buyer-pubkey".to_owned()),
   6131                 farm_id: None,
   6132                 listing_addr: Some("30402:seller-pubkey:listing-key".to_owned()),
   6133                 local_work_json: None,
   6134                 event_id: Some("malformed-order-event".to_owned()),
   6135                 event_kind: Some(KIND_ORDER_REQUEST),
   6136                 event_pubkey: Some("buyer-pubkey".to_owned()),
   6137                 event_created_at: Some(1100),
   6138                 event_tags_json: Some(json!([["d", "bad-order"]])),
   6139                 event_content: Some("not-json".to_owned()),
   6140                 event_sig: Some("signature".to_owned()),
   6141                 raw_event_json: Some(json!({
   6142                     "id": "malformed-order-event",
   6143                     "kind": KIND_ORDER_REQUEST,
   6144                     "pubkey": "buyer-pubkey",
   6145                     "content": "not-json"
   6146                 })),
   6147                 outbox_status: PublishOutboxStatus::Acknowledged,
   6148                 relay_set_fingerprint: Some("relay-set".to_owned()),
   6149                 relay_delivery_json: Some(json!({
   6150                     "state": "acknowledged",
   6151                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   6152                 })),
   6153             })
   6154             .expect("append malformed order event");
   6155 
   6156         let report = app_store
   6157             .import_shared_local_events_from_store(&events)
   6158             .expect("import malformed order event");
   6159         let imported = app_store
   6160             .load_local_interop_records()
   6161             .expect("load imported records");
   6162         let order_count: i64 = app_store
   6163             .connection()
   6164             .query_row("SELECT COUNT(*) FROM orders", [], |row| row.get(0))
   6165             .expect("load order count");
   6166 
   6167         assert_eq!(report.imported_records, 1);
   6168         assert_eq!(report.skipped_records, 0);
   6169         assert_eq!(imported.len(), 1);
   6170         assert_eq!(imported[0].projected_kind, "signed_event");
   6171         assert_eq!(
   6172             imported[0].event_id.as_deref(),
   6173             Some("malformed-order-event")
   6174         );
   6175         assert_eq!(order_count, 0);
   6176     }
   6177 
   6178     #[test]
   6179     fn imports_cli_local_work_into_app_farm_and_product_projection() {
   6180         let app_store =
   6181             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6182         let events = local_events_store();
   6183         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   6184         let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   6185         events
   6186             .append_record(&local_work_record(
   6187                 "cli:local_work:farm",
   6188                 farm_key,
   6189                 json!({
   6190                     "record_kind": "farm_config_v1",
   6191                     "document": {
   6192                         "selection": {
   6193                             "account": "seller-account",
   6194                             "farm_d_tag": farm_key
   6195                         },
   6196                         "profile": {
   6197                             "name": "Green Farm",
   6198                             "display_name": "Green Farm"
   6199                         },
   6200                         "farm": {
   6201                             "d_tag": farm_key,
   6202                             "name": "Green Farm",
   6203                             "location": {
   6204                                 "primary": "farmstand"
   6205                             }
   6206                         },
   6207                         "listing_defaults": {
   6208                             "delivery_method": "pickup",
   6209                             "location": {
   6210                                 "primary": "farmstand"
   6211                             }
   6212                         }
   6213                     }
   6214                 }),
   6215             ))
   6216             .expect("append farm local work");
   6217         let mut listing = local_work_record(
   6218             "cli:local_work:listing",
   6219             farm_key,
   6220             json!({
   6221                 "record_kind": "listing_draft_v1",
   6222                 "document": {
   6223                     "listing": {
   6224                         "d_tag": listing_key,
   6225                         "farm_d_tag": farm_key
   6226                     },
   6227                     "seller_actor": {
   6228                         "account_id": "seller-account",
   6229                         "pubkey": "seller-pubkey"
   6230                     },
   6231                     "product": {
   6232                         "key": "eggs",
   6233                         "title": "Eggs",
   6234                         "summary": "Fresh eggs"
   6235                     },
   6236                     "primary_bin": {
   6237                         "quantity_unit": "each",
   6238                         "price_amount": "6",
   6239                         "price_currency": "USD"
   6240                     },
   6241                     "inventory": {
   6242                         "available": "10"
   6243                     }
   6244                 }
   6245             }),
   6246         );
   6247         listing.listing_addr = Some(format!("30402:seller-pubkey:{listing_key}"));
   6248         events
   6249             .append_record(&listing)
   6250             .expect("append listing local work");
   6251 
   6252         let report = app_store
   6253             .import_shared_local_events_from_store(&events)
   6254             .expect("import shared local events");
   6255         let second_report = app_store
   6256             .import_shared_local_events_from_store(&events)
   6257             .expect("import shared local events again");
   6258 
   6259         assert_eq!(report.scanned_records, 2);
   6260         assert_eq!(report.imported_records, 2);
   6261         assert!(report.last_change_seq.is_some());
   6262         assert_eq!(second_report.scanned_records, 0);
   6263         assert_eq!(second_report.imported_records, 0);
   6264         assert_eq!(second_report.skipped_records, 0);
   6265         assert_eq!(second_report.self_observed_records, 0);
   6266         assert!(
   6267             events
   6268                 .get_cursor("radroots_app_sqlite_projection_v1")
   6269                 .expect("read shared cursor")
   6270                 .is_none()
   6271         );
   6272         let imported = app_store
   6273             .load_local_interop_records()
   6274             .expect("load imported records");
   6275         assert_eq!(imported.len(), 2);
   6276         assert!(
   6277             imported
   6278                 .iter()
   6279                 .all(|record| record.local_status == "local_saved")
   6280         );
   6281         let farm_setup = app_store
   6282             .load_farm_setup("seller-account")
   6283             .expect("load farm setup");
   6284         let saved_farm = farm_setup.saved_farm.expect("saved farm");
   6285         assert_eq!(saved_farm.display_name, "Green Farm");
   6286         assert_eq!(farm_setup.draft.farm_name, "Green Farm");
   6287         let products = app_store
   6288             .load_products(
   6289                 saved_farm.farm_id,
   6290                 "",
   6291                 Default::default(),
   6292                 Default::default(),
   6293             )
   6294             .expect("load products");
   6295         assert_eq!(products.rows.len(), 1);
   6296         assert_eq!(products.rows[0].title, "Eggs");
   6297         assert_eq!(products.rows[0].subtitle.as_deref(), Some("Fresh eggs"));
   6298         assert_eq!(
   6299             products.rows[0]
   6300                 .price
   6301                 .as_ref()
   6302                 .expect("price")
   6303                 .amount_minor_units,
   6304             600
   6305         );
   6306         assert_eq!(products.rows[0].stock.quantity, Some(10));
   6307         assert_eq!(
   6308             products.rows[0].status,
   6309             radroots_app_view::ProductStatus::Draft
   6310         );
   6311     }
   6312 
   6313     #[test]
   6314     fn fresh_app_store_replays_existing_shared_records_after_another_app_imported_them() {
   6315         let events = local_events_store();
   6316         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   6317         events
   6318             .append_record(&local_work_record(
   6319                 "cli:local_work:farm",
   6320                 farm_key,
   6321                 json!({
   6322                     "record_kind": "farm_config_v1",
   6323                     "document": {
   6324                         "selection": {
   6325                             "account": "seller-account",
   6326                             "farm_d_tag": farm_key
   6327                         },
   6328                         "profile": {
   6329                             "name": "Green Farm",
   6330                             "display_name": "Green Farm"
   6331                         },
   6332                         "farm": {
   6333                             "d_tag": farm_key,
   6334                             "name": "Green Farm",
   6335                             "location": {
   6336                                 "primary": "farmstand"
   6337                             }
   6338                         }
   6339                     }
   6340                 }),
   6341             ))
   6342             .expect("append farm local work");
   6343         let first_store =
   6344             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open first app sqlite store");
   6345         let first_report = first_store
   6346             .import_shared_local_events_from_store(&events)
   6347             .expect("first app imports shared local events");
   6348         let second_same_store_report = first_store
   6349             .import_shared_local_events_from_store(&events)
   6350             .expect("first app imports unchanged shared local events");
   6351         let second_store =
   6352             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open second app sqlite store");
   6353         let fresh_store_report = second_store
   6354             .import_shared_local_events_from_store(&events)
   6355             .expect("fresh app imports shared local events");
   6356 
   6357         assert_eq!(first_report.scanned_records, 1);
   6358         assert_eq!(first_report.imported_records, 1);
   6359         assert_eq!(second_same_store_report.scanned_records, 0);
   6360         assert_eq!(second_same_store_report.imported_records, 0);
   6361         assert_eq!(fresh_store_report.scanned_records, 1);
   6362         assert_eq!(fresh_store_report.imported_records, 1);
   6363         assert!(
   6364             events
   6365                 .get_cursor("radroots_app_sqlite_projection_v1")
   6366                 .expect("read shared cursor")
   6367                 .is_none()
   6368         );
   6369     }
   6370 
   6371     #[test]
   6372     fn imports_signed_listing_tags_into_existing_local_product_projection() {
   6373         let app_store =
   6374             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6375         let events = local_events_store();
   6376         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   6377         let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   6378         events
   6379             .append_record(&local_work_record(
   6380                 "cli:local_work:farm",
   6381                 farm_key,
   6382                 json!({
   6383                     "record_kind": "farm_config_v1",
   6384                     "document": {
   6385                         "selection": {
   6386                             "account": "seller-account",
   6387                             "farm_d_tag": farm_key
   6388                         },
   6389                         "profile": {
   6390                             "name": "Green Farm"
   6391                         },
   6392                         "farm": {
   6393                             "d_tag": farm_key,
   6394                             "name": "Green Farm",
   6395                             "location": {
   6396                                 "primary": "farmstand"
   6397                             }
   6398                         }
   6399                     }
   6400                 }),
   6401             ))
   6402             .expect("append farm local work");
   6403         let mut listing = local_work_record(
   6404             "cli:local_work:listing",
   6405             farm_key,
   6406             json!({
   6407                 "record_kind": "listing_draft_v1",
   6408                 "document": {
   6409                     "listing": {
   6410                         "d_tag": listing_key,
   6411                         "farm_d_tag": farm_key
   6412                     },
   6413                     "seller_actor": {
   6414                         "account_id": "seller-account",
   6415                         "pubkey": "seller-pubkey"
   6416                     },
   6417                     "product": {
   6418                         "key": "eggs",
   6419                         "title": "Eggs",
   6420                         "summary": "Fresh eggs"
   6421                     },
   6422                     "primary_bin": {
   6423                         "quantity_unit": "each",
   6424                         "price_amount": "6",
   6425                         "price_currency": "USD"
   6426                     },
   6427                     "inventory": {
   6428                         "available": "10"
   6429                     }
   6430                 }
   6431             }),
   6432         );
   6433         listing.listing_addr = Some(format!("30402:seller-pubkey:{listing_key}"));
   6434         events
   6435             .append_record(&listing)
   6436             .expect("append listing local work");
   6437         app_store
   6438             .import_shared_local_events_from_store(&events)
   6439             .expect("import local work records");
   6440         events
   6441             .append_record(&LocalEventRecordInput {
   6442                 record_id: "cli:signed_event:listing:event-1".to_owned(),
   6443                 family: LocalRecordFamily::SignedEvent,
   6444                 status: LocalRecordStatus::Published,
   6445                 source_runtime: SourceRuntime::Cli,
   6446                 created_at_ms: 1100,
   6447                 inserted_at_ms: 1101,
   6448                 owner_account_id: Some("seller-account".to_owned()),
   6449                 owner_pubkey: Some("seller-pubkey".to_owned()),
   6450                 farm_id: Some(farm_key.to_owned()),
   6451                 listing_addr: Some(format!("30402:seller-pubkey:{listing_key}")),
   6452                 local_work_json: None,
   6453                 event_id: Some("event-1".to_owned()),
   6454                 event_kind: Some(KIND_LISTING),
   6455                 event_pubkey: Some("seller-pubkey".to_owned()),
   6456                 event_created_at: Some(1100),
   6457                 event_tags_json: Some(json!([
   6458                     ["d", listing_key],
   6459                     ["a", format!("30340:seller-pubkey:{farm_key}")],
   6460                     ["key", "eggs"],
   6461                     ["title", "Relay Eggs"],
   6462                     ["summary", "Published eggs"],
   6463                     ["radroots:bin", "bin-1", "1", "each"],
   6464                     ["radroots:price", "bin-1", "8", "USD", "1", "each"],
   6465                     ["inventory", "9"],
   6466                     ["status", "active"]
   6467                 ])),
   6468                 event_content: Some("# Relay Eggs\n\nPublished eggs".to_owned()),
   6469                 event_sig: Some("signature".to_owned()),
   6470                 raw_event_json: Some(json!({
   6471                     "id": "event-1",
   6472                     "kind": KIND_LISTING,
   6473                     "pubkey": "seller-pubkey",
   6474                     "content": "# Relay Eggs\n\nPublished eggs"
   6475                 })),
   6476                 outbox_status: PublishOutboxStatus::Acknowledged,
   6477                 relay_set_fingerprint: Some("relay-set".to_owned()),
   6478                 relay_delivery_json: Some(json!({
   6479                     "state": "acknowledged",
   6480                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   6481                 })),
   6482             })
   6483             .expect("append signed listing");
   6484 
   6485         app_store
   6486             .import_shared_local_events_from_store(&events)
   6487             .expect("import signed listing");
   6488         let imported = app_store
   6489             .load_local_interop_records()
   6490             .expect("load imported records");
   6491         let listing_records = imported
   6492             .iter()
   6493             .filter(|record| record.projected_kind == "listing")
   6494             .collect::<Vec<_>>();
   6495         assert_eq!(listing_records.len(), 2);
   6496         assert_eq!(
   6497             listing_records[0].projected_id,
   6498             listing_records[1].projected_id
   6499         );
   6500         let product_count: i64 = app_store
   6501             .connection()
   6502             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   6503             .expect("product count");
   6504         let product: (String, String, Option<i64>, Option<i64>) = app_store
   6505             .connection()
   6506             .query_row(
   6507                 "SELECT title, status, price_minor_units, stock_count FROM products",
   6508                 [],
   6509                 |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?)),
   6510             )
   6511             .expect("load product");
   6512         assert_eq!(product_count, 1);
   6513         assert_eq!(product.0, "Relay Eggs");
   6514         assert_eq!(product.1, "published");
   6515         assert_eq!(product.2, Some(800));
   6516         assert_eq!(product.3, Some(9));
   6517     }
   6518 
   6519     #[test]
   6520     fn cli_origin_signed_window_listing_projects_into_buyer_browse_and_search() {
   6521         let app_store =
   6522             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6523         let events = local_events_store();
   6524         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   6525         let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   6526         events
   6527             .append_record(&signed_market_listing_record(
   6528                 "buyer-visible-cli",
   6529                 "seller-pubkey",
   6530                 farm_key,
   6531                 listing_key,
   6532                 "Buyer Visible Eggs",
   6533                 "9",
   6534                 "active",
   6535                 "pickup",
   6536                 "North barn pickup",
   6537                 4_102_444_800,
   6538                 4_102_531_200,
   6539                 LocalRecordStatus::Published,
   6540                 PublishOutboxStatus::Acknowledged,
   6541             ))
   6542             .expect("append signed listing");
   6543 
   6544         let report = app_store
   6545             .import_shared_local_events_from_store(&events)
   6546             .expect("import signed listing");
   6547         let browse = app_store
   6548             .load_buyer_listings("", &BTreeSet::new())
   6549             .expect("buyer browse should load");
   6550         let search = app_store
   6551             .load_buyer_listings("eggs", &BTreeSet::from([FarmOrderMethod::Pickup]))
   6552             .expect("buyer search should load");
   6553         let detail = app_store
   6554             .load_buyer_product_detail(search.rows[0].product_id)
   6555             .expect("buyer detail should load")
   6556             .expect("buyer detail should exist");
   6557 
   6558         assert_eq!(report.imported_records, 1);
   6559         assert_eq!(browse.rows.len(), 1);
   6560         assert_eq!(search.rows.len(), 1);
   6561         assert_eq!(search.rows[0].title, "Buyer Visible Eggs");
   6562         assert_eq!(
   6563             search.rows[0].availability.state,
   6564             ProductAvailabilityState::Scheduled
   6565         );
   6566         assert_eq!(search.rows[0].stock.quantity, Some(9));
   6567         assert_eq!(
   6568             search.rows[0].fulfillment_methods,
   6569             BTreeSet::from([FarmOrderMethod::Pickup])
   6570         );
   6571         assert_eq!(detail.listing.title, "Buyer Visible Eggs");
   6572     }
   6573 
   6574     #[test]
   6575     fn app_origin_signed_window_listing_converges_into_buyer_visibility() {
   6576         let app_store =
   6577             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6578         let events = local_events_store();
   6579         let farm_uuid = Uuid::from_u128(0x55555555555545558555555555555555);
   6580         let product_uuid = Uuid::from_u128(0x66666666666646668666666666666666);
   6581         let farm_key = app_d_tag_from_uuid(farm_uuid);
   6582         let listing_key = app_d_tag_from_uuid(product_uuid);
   6583         let listing_addr = format!("30402:app-seller-pubkey:{listing_key}");
   6584         let app_farm_record = app_local_work_record(
   6585             "app:local_work:farm:buyer-visible",
   6586             farm_key.as_str(),
   6587             json!({
   6588                 "record_kind": "farm_config_v1",
   6589                 "document": {
   6590                     "selection": {
   6591                         "account": "seller-account",
   6592                         "farm_d_tag": farm_key
   6593                     },
   6594                     "profile": {
   6595                         "display_name": "App Farm"
   6596                     },
   6597                     "farm": {
   6598                         "d_tag": farm_key,
   6599                         "name": "App Farm",
   6600                         "location": {
   6601                             "primary": "app farmstand"
   6602                         }
   6603                     }
   6604                 }
   6605             }),
   6606         );
   6607         let mut app_listing_record = app_local_work_record(
   6608             "app:local_work:listing:buyer-visible",
   6609             farm_key.as_str(),
   6610             json!({
   6611                 "record_kind": "listing_draft_v1",
   6612                 "document": {
   6613                     "listing": {
   6614                         "d_tag": listing_key,
   6615                         "farm_d_tag": farm_key
   6616                     },
   6617                     "seller_actor": {
   6618                         "account_id": "seller-account",
   6619                         "pubkey": "app-seller-pubkey"
   6620                     },
   6621                     "product": {
   6622                         "key": listing_key,
   6623                         "title": "App Draft Eggs",
   6624                         "summary": "Fresh app-origin eggs"
   6625                     },
   6626                     "primary_bin": {
   6627                         "quantity_unit": "each",
   6628                         "price_amount": "7",
   6629                         "price_currency": "USD"
   6630                     },
   6631                     "inventory": {
   6632                         "available": "12"
   6633                     }
   6634                 }
   6635             }),
   6636         );
   6637         app_listing_record.listing_addr = Some(listing_addr);
   6638         events
   6639             .append_record(&app_farm_record)
   6640             .expect("append app farm local work");
   6641         events
   6642             .append_record(&app_listing_record)
   6643             .expect("append app listing local work");
   6644         app_store
   6645             .import_shared_local_events_from_store(&events)
   6646             .expect("import app local records");
   6647         events
   6648             .append_record(&signed_market_listing_record(
   6649                 "buyer-visible-app-origin",
   6650                 "app-seller-pubkey",
   6651                 farm_key.as_str(),
   6652                 listing_key.as_str(),
   6653                 "Buyer Visible App Eggs",
   6654                 "11",
   6655                 "active",
   6656                 "pickup",
   6657                 "App farmstand pickup",
   6658                 4_102_444_800,
   6659                 4_102_531_200,
   6660                 LocalRecordStatus::Published,
   6661                 PublishOutboxStatus::Acknowledged,
   6662             ))
   6663             .expect("append signed app-origin listing");
   6664 
   6665         app_store
   6666             .import_shared_local_events_from_store(&events)
   6667             .expect("import signed app-origin listing");
   6668         let buyer_listings = app_store
   6669             .load_buyer_listings("app eggs", &BTreeSet::new())
   6670             .expect("buyer listings should load");
   6671 
   6672         assert_eq!(buyer_listings.rows.len(), 1);
   6673         assert_eq!(buyer_listings.rows[0].product_id.as_uuid(), product_uuid);
   6674         assert_eq!(buyer_listings.rows[0].title, "Buyer Visible App Eggs");
   6675         assert_eq!(buyer_listings.rows[0].stock.quantity, Some(11));
   6676     }
   6677 
   6678     #[test]
   6679     fn network_app_origin_listing_cannot_claim_app_product_without_app_owned_evidence() {
   6680         let app_store =
   6681             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6682         let events = local_events_store();
   6683         let farm_uuid = Uuid::from_u128(0x77777777777747778777777777777777);
   6684         let product_uuid = Uuid::from_u128(0x88888888888848888888888888888888);
   6685         let farm_key = app_d_tag_from_uuid(farm_uuid);
   6686         let listing_key = app_d_tag_from_uuid(product_uuid);
   6687         let listing_addr = format!("30402:app-seller-pubkey:{listing_key}");
   6688         seed_app_projection(&app_store, farm_uuid, product_uuid);
   6689         let mut network_listing = signed_market_listing_record(
   6690             "network-app-origin",
   6691             "app-seller-pubkey",
   6692             farm_key.as_str(),
   6693             listing_key.as_str(),
   6694             "Relay App Eggs",
   6695             "11",
   6696             "active",
   6697             "pickup",
   6698             "App farmstand pickup",
   6699             4_102_444_800,
   6700             4_102_531_200,
   6701             LocalRecordStatus::Published,
   6702             PublishOutboxStatus::Acknowledged,
   6703         );
   6704         network_listing.source_runtime = SourceRuntime::Network;
   6705         network_listing.owner_account_id = None;
   6706         events
   6707             .append_record(&network_listing)
   6708             .expect("append network app-origin listing");
   6709 
   6710         let report = app_store
   6711             .import_shared_local_events_from_store(&events)
   6712             .expect("import network app-origin listing");
   6713         let imported = app_store
   6714             .load_local_interop_records()
   6715             .expect("load imported records");
   6716         let product_count: i64 = app_store
   6717             .connection()
   6718             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   6719             .expect("product count");
   6720         let app_product: (String, Option<i64>) = app_store
   6721             .connection()
   6722             .query_row(
   6723                 "SELECT title, stock_count FROM products WHERE id = ?1",
   6724                 [product_uuid.to_string()],
   6725                 |row| Ok((row.get(0)?, row.get(1)?)),
   6726             )
   6727             .expect("load app product");
   6728         let network_product_id =
   6729             deterministic_product_id(Some("app-seller-pubkey"), listing_key.as_str());
   6730         let network_product: (String, String, String, Option<i64>) = app_store
   6731             .connection()
   6732             .query_row(
   6733                 "SELECT id, farm_id, title, stock_count FROM products WHERE id = ?1",
   6734                 [network_product_id.to_string()],
   6735                 |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?)),
   6736             )
   6737             .expect("load network product");
   6738         let buyer_listings = app_store
   6739             .load_buyer_listings("relay app", &BTreeSet::new())
   6740             .expect("buyer listings should load");
   6741         let listing_import = imported
   6742             .iter()
   6743             .find(|record| record.record_id == "network-app-origin")
   6744             .expect("network app-origin listing import");
   6745 
   6746         assert_eq!(report.imported_records, 1);
   6747         assert_eq!(product_count, 2);
   6748         assert_eq!(app_product.0, "Origin Eggs");
   6749         assert_eq!(app_product.1, Some(3));
   6750         assert_ne!(network_product_id.as_uuid(), product_uuid);
   6751         assert_ne!(network_product.1, farm_uuid.to_string());
   6752         assert_eq!(network_product.2, "Relay App Eggs");
   6753         assert_eq!(network_product.3, Some(11));
   6754         assert_eq!(buyer_listings.rows.len(), 1);
   6755         assert_eq!(
   6756             buyer_listings.rows[0].product_id.as_uuid(),
   6757             network_product_id.as_uuid()
   6758         );
   6759         assert_eq!(
   6760             listing_import.source_runtime,
   6761             SourceRuntime::Network.as_str()
   6762         );
   6763         assert_eq!(
   6764             listing_import.listing_addr.as_deref(),
   6765             Some(listing_addr.as_str())
   6766         );
   6767         assert_eq!(
   6768             listing_import.projected_id.as_deref(),
   6769             Some(network_product_id.to_string().as_str())
   6770         );
   6771     }
   6772 
   6773     #[test]
   6774     fn network_app_origin_listing_reuses_app_product_with_matching_app_owned_evidence() {
   6775         let app_store =
   6776             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6777         let events = local_events_store();
   6778         let farm_uuid = Uuid::from_u128(0x79797979797949799797979797979797);
   6779         let product_uuid = Uuid::from_u128(0x89898989898949898989898989898989);
   6780         let farm_key = app_d_tag_from_uuid(farm_uuid);
   6781         let listing_key = app_d_tag_from_uuid(product_uuid);
   6782         let listing_addr = format!("30402:app-seller-pubkey:{listing_key}");
   6783         let app_farm_record = app_local_work_record(
   6784             "app:local_work:farm:network-claim-gate",
   6785             farm_key.as_str(),
   6786             json!({
   6787                 "record_kind": "farm_config_v1",
   6788                 "document": {
   6789                     "selection": {
   6790                         "account": "seller-account",
   6791                         "farm_d_tag": farm_key
   6792                     },
   6793                     "profile": {
   6794                         "display_name": "App Farm"
   6795                     },
   6796                     "farm": {
   6797                         "d_tag": farm_key,
   6798                         "name": "App Farm"
   6799                     }
   6800                 }
   6801             }),
   6802         );
   6803         let mut app_listing_record = app_local_work_record(
   6804             "app:local_work:listing:network-claim-gate",
   6805             farm_key.as_str(),
   6806             json!({
   6807                 "record_kind": "listing_draft_v1",
   6808                 "document": {
   6809                     "listing": {
   6810                         "d_tag": listing_key,
   6811                         "farm_d_tag": farm_key
   6812                     },
   6813                     "seller_actor": {
   6814                         "account_id": "seller-account",
   6815                         "pubkey": "app-seller-pubkey"
   6816                     },
   6817                     "product": {
   6818                         "key": listing_key,
   6819                         "title": "App Draft Eggs",
   6820                         "summary": "Fresh app-origin eggs"
   6821                     },
   6822                     "primary_bin": {
   6823                         "quantity_unit": "each",
   6824                         "price_amount": "7",
   6825                         "price_currency": "USD"
   6826                     },
   6827                     "inventory": {
   6828                         "available": "12"
   6829                     }
   6830                 }
   6831             }),
   6832         );
   6833         app_listing_record.listing_addr = Some(listing_addr.clone());
   6834         events
   6835             .append_record(&app_farm_record)
   6836             .expect("append app farm local work");
   6837         events
   6838             .append_record(&app_listing_record)
   6839             .expect("append app listing local work");
   6840         app_store
   6841             .import_shared_local_events_from_store(&events)
   6842             .expect("import app local work");
   6843         let mut network_listing = signed_market_listing_record(
   6844             "network-app-origin-matching-evidence",
   6845             "app-seller-pubkey",
   6846             farm_key.as_str(),
   6847             listing_key.as_str(),
   6848             "Relay App Eggs",
   6849             "11",
   6850             "active",
   6851             "pickup",
   6852             "App farmstand pickup",
   6853             4_102_444_800,
   6854             4_102_531_200,
   6855             LocalRecordStatus::Published,
   6856             PublishOutboxStatus::Acknowledged,
   6857         );
   6858         network_listing.source_runtime = SourceRuntime::Network;
   6859         network_listing.owner_account_id = None;
   6860         events
   6861             .append_record(&network_listing)
   6862             .expect("append network app-origin listing");
   6863 
   6864         let report = app_store
   6865             .import_shared_local_events_from_store(&events)
   6866             .expect("import network app-origin listing");
   6867         let product_count: i64 = app_store
   6868             .connection()
   6869             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   6870             .expect("product count");
   6871         let product: (String, String, String, Option<i64>) = app_store
   6872             .connection()
   6873             .query_row(
   6874                 "SELECT id, farm_id, title, stock_count FROM products",
   6875                 [],
   6876                 |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?)),
   6877             )
   6878             .expect("load product");
   6879         let imported = app_store
   6880             .load_local_interop_records()
   6881             .expect("load imported records");
   6882         let listing_import = imported
   6883             .iter()
   6884             .find(|record| record.record_id == "network-app-origin-matching-evidence")
   6885             .expect("network app-origin listing import");
   6886 
   6887         assert_eq!(report.imported_records, 1);
   6888         assert_eq!(product_count, 1);
   6889         assert_eq!(product.0, product_uuid.to_string());
   6890         assert_eq!(product.1, farm_uuid.to_string());
   6891         assert_eq!(product.2, "Relay App Eggs");
   6892         assert_eq!(product.3, Some(11));
   6893         assert_eq!(
   6894             listing_import.source_runtime,
   6895             SourceRuntime::Network.as_str()
   6896         );
   6897         assert_eq!(
   6898             listing_import.projected_id.as_deref(),
   6899             Some(product_uuid.to_string().as_str())
   6900         );
   6901     }
   6902 
   6903     #[test]
   6904     fn network_app_origin_listing_requires_matching_event_pubkey_for_app_product_reuse() {
   6905         let app_store =
   6906             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   6907         let events = local_events_store();
   6908         let farm_uuid = Uuid::from_u128(0x7a7a7a7a7a7a4a7a9a7a7a7a7a7a7a7a);
   6909         let product_uuid = Uuid::from_u128(0x8a8a8a8a8a8a4a8aaa8a8a8a8a8a8a8a);
   6910         let farm_key = app_d_tag_from_uuid(farm_uuid);
   6911         let listing_key = app_d_tag_from_uuid(product_uuid);
   6912         let listing_addr = format!("30402:app-seller-pubkey:{listing_key}");
   6913         let app_farm_record = app_local_work_record(
   6914             "app:local_work:farm:network-foreign-claim",
   6915             farm_key.as_str(),
   6916             json!({
   6917                 "record_kind": "farm_config_v1",
   6918                 "document": {
   6919                     "selection": {
   6920                         "account": "seller-account",
   6921                         "farm_d_tag": farm_key
   6922                     },
   6923                     "profile": {
   6924                         "display_name": "App Farm"
   6925                     },
   6926                     "farm": {
   6927                         "d_tag": farm_key,
   6928                         "name": "App Farm"
   6929                     }
   6930                 }
   6931             }),
   6932         );
   6933         let mut app_listing_record = app_local_work_record(
   6934             "app:local_work:listing:network-foreign-claim",
   6935             farm_key.as_str(),
   6936             json!({
   6937                 "record_kind": "listing_draft_v1",
   6938                 "document": {
   6939                     "listing": {
   6940                         "d_tag": listing_key,
   6941                         "farm_d_tag": farm_key
   6942                     },
   6943                     "seller_actor": {
   6944                         "account_id": "seller-account",
   6945                         "pubkey": "app-seller-pubkey"
   6946                     },
   6947                     "product": {
   6948                         "key": listing_key,
   6949                         "title": "App Draft Eggs",
   6950                         "summary": "Fresh app-origin eggs"
   6951                     },
   6952                     "primary_bin": {
   6953                         "quantity_unit": "each",
   6954                         "price_amount": "7",
   6955                         "price_currency": "USD"
   6956                     },
   6957                     "inventory": {
   6958                         "available": "12"
   6959                     }
   6960                 }
   6961             }),
   6962         );
   6963         app_listing_record.listing_addr = Some(listing_addr.clone());
   6964         events
   6965             .append_record(&app_farm_record)
   6966             .expect("append app farm local work");
   6967         events
   6968             .append_record(&app_listing_record)
   6969             .expect("append app listing local work");
   6970         app_store
   6971             .import_shared_local_events_from_store(&events)
   6972             .expect("import app local work");
   6973         let mut network_listing = signed_market_listing_record(
   6974             "network-app-origin-foreign-event-pubkey",
   6975             "app-seller-pubkey",
   6976             farm_key.as_str(),
   6977             listing_key.as_str(),
   6978             "Foreign Relay App Eggs",
   6979             "11",
   6980             "active",
   6981             "pickup",
   6982             "App farmstand pickup",
   6983             4_102_444_800,
   6984             4_102_531_200,
   6985             LocalRecordStatus::Published,
   6986             PublishOutboxStatus::Acknowledged,
   6987         );
   6988         network_listing.source_runtime = SourceRuntime::Network;
   6989         network_listing.owner_account_id = None;
   6990         network_listing.event_pubkey = Some("foreign-seller-pubkey".to_owned());
   6991         events
   6992             .append_record(&network_listing)
   6993             .expect("append foreign network app-origin listing");
   6994 
   6995         app_store
   6996             .import_shared_local_events_from_store(&events)
   6997             .expect("import network app-origin listing");
   6998         let product_count: i64 = app_store
   6999             .connection()
   7000             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   7001             .expect("product count");
   7002         let app_product: (String, Option<i64>) = app_store
   7003             .connection()
   7004             .query_row(
   7005                 "SELECT title, stock_count FROM products WHERE id = ?1",
   7006                 [product_uuid.to_string()],
   7007                 |row| Ok((row.get(0)?, row.get(1)?)),
   7008             )
   7009             .expect("load app product");
   7010         let foreign_product_id =
   7011             deterministic_product_id(Some("foreign-seller-pubkey"), listing_key.as_str());
   7012         let foreign_product_count: i64 = app_store
   7013             .connection()
   7014             .query_row(
   7015                 "SELECT COUNT(*) FROM products WHERE id = ?1",
   7016                 [foreign_product_id.to_string()],
   7017                 |row| row.get(0),
   7018             )
   7019             .expect("foreign product count");
   7020 
   7021         assert_eq!(product_count, 2);
   7022         assert_eq!(app_product.0, "App Draft Eggs");
   7023         assert_eq!(app_product.1, Some(12));
   7024         assert_eq!(foreign_product_count, 1);
   7025     }
   7026 
   7027     #[test]
   7028     fn app_signed_duplicate_replaces_network_listing_product_projection() {
   7029         let app_store =
   7030             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7031         let events = local_events_store();
   7032         let farm_uuid = Uuid::from_u128(0x99999999999949999999999999999999);
   7033         let product_uuid = Uuid::from_u128(0xaaaaaaaaaaaa4aaaaaaaaaaaaaaaaaaa);
   7034         let farm_key = app_d_tag_from_uuid(farm_uuid);
   7035         let listing_key = app_d_tag_from_uuid(product_uuid);
   7036         let seller_pubkey = "app-seller-pubkey";
   7037         let duplicate_event_id = "duplicate-app-origin-listing-event";
   7038         let mut network_listing = signed_market_listing_record(
   7039             "duplicate-network-app-origin",
   7040             seller_pubkey,
   7041             farm_key.as_str(),
   7042             listing_key.as_str(),
   7043             "Relay App Eggs",
   7044             "11",
   7045             "active",
   7046             "pickup",
   7047             "App farmstand pickup",
   7048             4_102_444_800,
   7049             4_102_531_200,
   7050             LocalRecordStatus::Published,
   7051             PublishOutboxStatus::Acknowledged,
   7052         );
   7053         network_listing.source_runtime = SourceRuntime::Network;
   7054         network_listing.owner_account_id = None;
   7055         network_listing.record_id = "app:relay_event:duplicate-app-origin".to_owned();
   7056         network_listing.event_id = Some(duplicate_event_id.to_owned());
   7057         events
   7058             .append_record(&network_listing)
   7059             .expect("append network app-origin listing");
   7060 
   7061         app_store
   7062             .import_shared_local_events_from_store(&events)
   7063             .expect("import network app-origin listing");
   7064         let network_product_id =
   7065             deterministic_product_id(Some(seller_pubkey), listing_key.as_str());
   7066         let network_product_count: i64 = app_store
   7067             .connection()
   7068             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   7069             .expect("network product count");
   7070         assert_eq!(network_product_count, 1);
   7071         assert_ne!(network_product_id.as_uuid(), product_uuid);
   7072         let buyer_context = BuyerContext::account("acct_buyer");
   7073         let network_listing = app_store
   7074             .load_buyer_product_detail(network_product_id)
   7075             .expect("network buyer detail should load")
   7076             .expect("network listing should exist")
   7077             .listing;
   7078         app_store
   7079             .replace_buyer_cart(
   7080                 &buyer_context,
   7081                 &radroots_app_view::BuyerCartProjection {
   7082                     farm_id: Some(network_listing.farm_id),
   7083                     farm_display_name: Some(network_listing.farm_display_name.clone()),
   7084                     lines: vec![radroots_app_view::BuyerCartLineProjection {
   7085                         product_id: network_listing.product_id,
   7086                         farm_id: network_listing.farm_id,
   7087                         farm_display_name: network_listing.farm_display_name.clone(),
   7088                         title: network_listing.title.clone(),
   7089                         quantity: 2,
   7090                         unit_price: network_listing.price.clone(),
   7091                         line_total_minor_units: 1600,
   7092                         fulfillment_summary: network_listing
   7093                             .next_fulfillment_window_label
   7094                             .clone()
   7095                             .expect("network listing fulfillment summary"),
   7096                     }],
   7097                     subtotal_minor_units: Some(1600),
   7098                     currency_code: Some("USD".to_owned()),
   7099                     replace_confirmation: None,
   7100                 },
   7101             )
   7102             .expect("buyer cart should save");
   7103         app_store
   7104             .save_buyer_order_review_draft(
   7105                 &buyer_context,
   7106                 &radroots_app_view::BuyerOrderReviewDraft {
   7107                     name: "Casey Buyer".to_owned(),
   7108                     email: "casey@example.test".to_owned(),
   7109                     phone: String::new(),
   7110                     order_note: String::new(),
   7111                 },
   7112             )
   7113             .expect("order review draft should save");
   7114         let order_id = app_store
   7115             .place_buyer_order(&buyer_context)
   7116             .expect("buyer order should place");
   7117         app_store
   7118             .replace_buyer_cart(
   7119                 &buyer_context,
   7120                 &radroots_app_view::BuyerCartProjection {
   7121                     farm_id: Some(network_listing.farm_id),
   7122                     farm_display_name: Some(network_listing.farm_display_name.clone()),
   7123                     lines: vec![radroots_app_view::BuyerCartLineProjection {
   7124                         product_id: network_listing.product_id,
   7125                         farm_id: network_listing.farm_id,
   7126                         farm_display_name: network_listing.farm_display_name.clone(),
   7127                         title: network_listing.title.clone(),
   7128                         quantity: 3,
   7129                         unit_price: network_listing.price,
   7130                         line_total_minor_units: 2400,
   7131                         fulfillment_summary: network_listing
   7132                             .next_fulfillment_window_label
   7133                             .expect("network listing fulfillment summary"),
   7134                     }],
   7135                     subtotal_minor_units: Some(2400),
   7136                     currency_code: Some("USD".to_owned()),
   7137                     replace_confirmation: None,
   7138                 },
   7139             )
   7140             .expect("buyer cart should save again");
   7141 
   7142         seed_app_projection(&app_store, farm_uuid, product_uuid);
   7143         let mut app_listing = signed_market_listing_record(
   7144             "duplicate-app-signed-origin",
   7145             seller_pubkey,
   7146             farm_key.as_str(),
   7147             listing_key.as_str(),
   7148             "Relay App Eggs",
   7149             "11",
   7150             "active",
   7151             "pickup",
   7152             "App farmstand pickup",
   7153             4_102_444_800,
   7154             4_102_531_200,
   7155             LocalRecordStatus::Published,
   7156             PublishOutboxStatus::Acknowledged,
   7157         );
   7158         app_listing.source_runtime = SourceRuntime::App;
   7159         app_listing.record_id = "app:signed_event:duplicate-app-origin".to_owned();
   7160         app_listing.event_id = Some(duplicate_event_id.to_owned());
   7161         events
   7162             .append_record(&app_listing)
   7163             .expect("append app signed duplicate listing");
   7164 
   7165         app_store
   7166             .import_shared_local_events_from_store(&events)
   7167             .expect("import app signed duplicate listing");
   7168         let imported = app_store
   7169             .load_local_interop_records()
   7170             .expect("load imported records");
   7171         let product_count: i64 = app_store
   7172             .connection()
   7173             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   7174             .expect("product count");
   7175         let stale_product_count: i64 = app_store
   7176             .connection()
   7177             .query_row(
   7178                 "SELECT COUNT(*) FROM products WHERE id = ?1",
   7179                 [network_product_id.to_string()],
   7180                 |row| row.get(0),
   7181             )
   7182             .expect("stale product count");
   7183         let listing_import = imported
   7184             .iter()
   7185             .find(|record| record.record_id == "app:signed_event:duplicate-app-origin")
   7186             .expect("app signed duplicate listing import");
   7187         let migrated_cart = app_store
   7188             .load_buyer_cart(&buyer_context)
   7189             .expect("buyer cart should load after duplicate convergence");
   7190         let order_line_id: String = app_store
   7191             .connection()
   7192             .query_row(
   7193                 "SELECT id FROM order_lines WHERE order_id = ?1",
   7194                 [order_id.to_string()],
   7195                 |row| row.get(0),
   7196             )
   7197             .expect("order line id should load");
   7198 
   7199         assert_eq!(product_count, 1);
   7200         assert_eq!(stale_product_count, 0);
   7201         assert_eq!(migrated_cart.lines.len(), 1);
   7202         assert_eq!(migrated_cart.lines[0].product_id.as_uuid(), product_uuid);
   7203         assert_eq!(migrated_cart.lines[0].quantity, 3);
   7204         assert!(order_line_id.contains(network_product_id.to_string().as_str()));
   7205         assert_eq!(listing_import.source_runtime, SourceRuntime::App.as_str());
   7206         assert_eq!(
   7207             listing_import.projected_id.as_deref(),
   7208             Some(product_uuid.to_string().as_str())
   7209         );
   7210         assert!(
   7211             imported
   7212                 .iter()
   7213                 .all(|record| record.record_id != "app:relay_event:duplicate-app-origin")
   7214         );
   7215         app_store
   7216             .clear_buyer_cart(&buyer_context)
   7217             .expect("buyer cart should clear");
   7218         assert_eq!(
   7219             app_store
   7220                 .apply_buyer_repeat_demand_to_cart(&buyer_context, order_id, false)
   7221                 .expect("repeat demand should apply"),
   7222             BuyerRepeatDemandApplyOutcome::Applied
   7223         );
   7224         let repeated_cart = app_store
   7225             .load_buyer_cart(&buyer_context)
   7226             .expect("buyer cart should load after repeat demand");
   7227         assert_eq!(repeated_cart.lines.len(), 1);
   7228         assert_eq!(repeated_cart.lines[0].product_id.as_uuid(), product_uuid);
   7229         assert_eq!(repeated_cart.lines[0].quantity, 2);
   7230     }
   7231 
   7232     #[test]
   7233     fn failed_duplicate_listing_replacement_rolls_back_prior_visible_state() {
   7234         let app_store =
   7235             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7236         let events = local_events_store();
   7237         let farm_uuid = Uuid::from_u128(0x9b9b9b9b9b9b4b9bbb9b9b9b9b9b9b9b);
   7238         let product_uuid = Uuid::from_u128(0xabababababab4abababababababababa);
   7239         let farm_key = app_d_tag_from_uuid(farm_uuid);
   7240         let listing_key = app_d_tag_from_uuid(product_uuid);
   7241         let seller_pubkey = "app-seller-pubkey";
   7242         let duplicate_event_id = "duplicate-app-origin-rollback-event";
   7243         let mut network_listing = signed_market_listing_record(
   7244             "rollback-network-app-origin",
   7245             seller_pubkey,
   7246             farm_key.as_str(),
   7247             listing_key.as_str(),
   7248             "Rollback Relay Eggs",
   7249             "11",
   7250             "active",
   7251             "pickup",
   7252             "App farmstand pickup",
   7253             4_102_444_800,
   7254             4_102_531_200,
   7255             LocalRecordStatus::Published,
   7256             PublishOutboxStatus::Acknowledged,
   7257         );
   7258         network_listing.source_runtime = SourceRuntime::Network;
   7259         network_listing.owner_account_id = None;
   7260         network_listing.record_id = "app:relay_event:rollback-app-origin".to_owned();
   7261         network_listing.event_id = Some(duplicate_event_id.to_owned());
   7262         events
   7263             .append_record(&network_listing)
   7264             .expect("append network app-origin listing");
   7265         app_store
   7266             .import_shared_local_events_from_store(&events)
   7267             .expect("import network app-origin listing");
   7268 
   7269         let network_product_id =
   7270             deterministic_product_id(Some(seller_pubkey), listing_key.as_str());
   7271         let network_farm_id = deterministic_farm_id(Some(seller_pubkey), farm_key.as_str());
   7272         seed_app_projection(&app_store, farm_uuid, product_uuid);
   7273         app_store
   7274             .connection()
   7275             .execute(
   7276                 "INSERT INTO buyer_carts (
   7277                     buyer_context_key,
   7278                     farm_id,
   7279                      updated_at
   7280                  ) VALUES ('account:acct_buyer', ?1, '2026-01-01T00:00:00Z')",
   7281                 [network_farm_id.to_string()],
   7282             )
   7283             .expect("insert buyer cart header");
   7284         app_store
   7285             .connection()
   7286             .execute(
   7287                 "INSERT INTO buyer_cart_lines (
   7288                     buyer_context_key,
   7289                     product_id,
   7290                     quantity,
   7291                     updated_at
   7292                  ) VALUES ('account:acct_buyer', ?1, 2, '2026-01-01T00:00:00Z')",
   7293                 [network_product_id.to_string()],
   7294             )
   7295             .expect("insert stale buyer cart line");
   7296         app_store
   7297             .connection()
   7298             .execute_batch(
   7299                 format!(
   7300                     "CREATE TEMP TRIGGER fail_duplicate_cart_delete
   7301                      BEFORE DELETE ON buyer_cart_lines
   7302                      WHEN old.product_id = '{}'
   7303                      BEGIN
   7304                         SELECT RAISE(ABORT, 'forced duplicate cart migration failure');
   7305                      END;",
   7306                     network_product_id
   7307                 )
   7308                 .as_str(),
   7309             )
   7310             .expect("create failure trigger");
   7311 
   7312         let mut app_listing = signed_market_listing_record(
   7313             "rollback-app-signed-origin",
   7314             seller_pubkey,
   7315             farm_key.as_str(),
   7316             listing_key.as_str(),
   7317             "Rollback App Eggs",
   7318             "9",
   7319             "active",
   7320             "pickup",
   7321             "App farmstand pickup",
   7322             4_102_444_800,
   7323             4_102_531_200,
   7324             LocalRecordStatus::Published,
   7325             PublishOutboxStatus::Acknowledged,
   7326         );
   7327         app_listing.source_runtime = SourceRuntime::App;
   7328         app_listing.record_id = "app:signed_event:rollback-app-origin".to_owned();
   7329         app_listing.event_id = Some(duplicate_event_id.to_owned());
   7330         events
   7331             .append_record(&app_listing)
   7332             .expect("append app signed duplicate listing");
   7333 
   7334         app_store
   7335             .import_shared_local_events_from_store(&events)
   7336             .expect_err("duplicate replacement should roll back on cart migration failure");
   7337         let imported = app_store
   7338             .load_local_interop_records()
   7339             .expect("load imported records");
   7340         let product_count: i64 = app_store
   7341             .connection()
   7342             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   7343             .expect("product count");
   7344         let stale_cart_quantity: i64 = app_store
   7345             .connection()
   7346             .query_row(
   7347                 "SELECT quantity FROM buyer_cart_lines WHERE product_id = ?1",
   7348                 [network_product_id.to_string()],
   7349                 |row| row.get(0),
   7350             )
   7351             .expect("stale cart quantity");
   7352         let canonical_cart_count: i64 = app_store
   7353             .connection()
   7354             .query_row(
   7355                 "SELECT COUNT(*) FROM buyer_cart_lines WHERE product_id = ?1",
   7356                 [product_uuid.to_string()],
   7357                 |row| row.get(0),
   7358             )
   7359             .expect("canonical cart count");
   7360         let network_product_title: String = app_store
   7361             .connection()
   7362             .query_row(
   7363                 "SELECT title FROM products WHERE id = ?1",
   7364                 [network_product_id.to_string()],
   7365                 |row| row.get(0),
   7366             )
   7367             .expect("network product title");
   7368 
   7369         assert_eq!(product_count, 2);
   7370         assert_eq!(stale_cart_quantity, 2);
   7371         assert_eq!(canonical_cart_count, 0);
   7372         assert_eq!(network_product_title, "Rollback Relay Eggs");
   7373         assert!(
   7374             imported
   7375                 .iter()
   7376                 .any(|record| record.record_id == "app:relay_event:rollback-app-origin")
   7377         );
   7378         assert!(
   7379             imported
   7380                 .iter()
   7381                 .all(|record| record.record_id != "app:signed_event:rollback-app-origin")
   7382         );
   7383     }
   7384 
   7385     #[test]
   7386     fn buyer_visibility_rejects_incomplete_unpublished_stale_and_unsupported_records() {
   7387         for record in [
   7388             signed_market_listing_record(
   7389                 "pending-window",
   7390                 "seller-pubkey",
   7391                 "AAAAAAAAAAAAAAAAAAAAAA",
   7392                 "BBBBBBBBBBBBBBBBBBBBBB",
   7393                 "Pending Eggs",
   7394                 "8",
   7395                 "active",
   7396                 "pickup",
   7397                 "Pending barn pickup",
   7398                 4_102_444_800,
   7399                 4_102_531_200,
   7400                 LocalRecordStatus::PendingPublish,
   7401                 PublishOutboxStatus::Pending,
   7402             ),
   7403             signed_market_listing_record(
   7404                 "sold-out-window",
   7405                 "seller-pubkey",
   7406                 "CCCCCCCCCCCCCCCCCCCCCC",
   7407                 "DDDDDDDDDDDDDDDDDDDDDD",
   7408                 "Sold Out Eggs",
   7409                 "0",
   7410                 "active",
   7411                 "pickup",
   7412                 "South barn pickup",
   7413                 4_102_444_800,
   7414                 4_102_531_200,
   7415                 LocalRecordStatus::Published,
   7416                 PublishOutboxStatus::Acknowledged,
   7417             ),
   7418             signed_market_listing_record(
   7419                 "expired-window",
   7420                 "seller-pubkey",
   7421                 "EEEEEEEEEEEEEEEEEEEEEE",
   7422                 "FFFFFFFFFFFFFFFFFFFFFF",
   7423                 "Expired Eggs",
   7424                 "8",
   7425                 "active",
   7426                 "pickup",
   7427                 "East barn pickup",
   7428                 946_684_800,
   7429                 946_771_200,
   7430                 LocalRecordStatus::Published,
   7431                 PublishOutboxStatus::Acknowledged,
   7432             ),
   7433             signed_market_listing_record(
   7434                 "unsupported-fulfillment",
   7435                 "seller-pubkey",
   7436                 "GGGGGGGGGGGGGGGGGGGGGG",
   7437                 "HHHHHHHHHHHHHHHHHHHHHH",
   7438                 "Unsupported Eggs",
   7439                 "8",
   7440                 "active",
   7441                 "other",
   7442                 "Unknown exchange point",
   7443                 4_102_444_800,
   7444                 4_102_531_200,
   7445                 LocalRecordStatus::Published,
   7446                 PublishOutboxStatus::Acknowledged,
   7447             ),
   7448             signed_listing_record(
   7449                 "status-only",
   7450                 "IIIIIIIIIIIIIIIIIIIIII",
   7451                 "JJJJJJJJJJJJJJJJJJJJJJ",
   7452                 "active",
   7453             ),
   7454         ] {
   7455             let app_store =
   7456                 AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7457             let events = local_events_store();
   7458             events.append_record(&record).expect("append record");
   7459 
   7460             app_store
   7461                 .import_shared_local_events_from_store(&events)
   7462                 .expect("import hidden listing record");
   7463 
   7464             assert!(buyer_listing_titles(&app_store).is_empty());
   7465         }
   7466 
   7467         let app_store =
   7468             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7469         let events = local_events_store();
   7470         let farm_key = "KKKKKKKKKKKKKKKKKKKKKK";
   7471         let listing_key = "LLLLLLLLLLLLLLLLLLLLLL";
   7472         events
   7473             .append_record(&local_work_record(
   7474                 "local-only-listing",
   7475                 farm_key,
   7476                 json!({
   7477                     "record_kind": "listing_draft_v1",
   7478                     "document": {
   7479                         "listing": {
   7480                             "d_tag": listing_key,
   7481                             "farm_d_tag": farm_key
   7482                         },
   7483                         "product": {
   7484                             "title": "Local Only Eggs"
   7485                         },
   7486                         "primary_bin": {
   7487                             "quantity_unit": "each",
   7488                             "price_amount": "7",
   7489                             "price_currency": "USD"
   7490                         },
   7491                         "inventory": {
   7492                             "available": "7"
   7493                         }
   7494                     }
   7495                 }),
   7496             ))
   7497             .expect("append local-only listing");
   7498         app_store
   7499             .import_shared_local_events_from_store(&events)
   7500             .expect("import local-only listing");
   7501         assert!(buyer_listing_titles(&app_store).is_empty());
   7502 
   7503         let app_store =
   7504             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7505         let events = local_events_store();
   7506         events
   7507             .append_record(&signed_market_listing_record(
   7508                 "current-active-window",
   7509                 "seller-pubkey",
   7510                 farm_key,
   7511                 listing_key,
   7512                 "Current Eggs",
   7513                 "8",
   7514                 "active",
   7515                 "pickup",
   7516                 "West barn pickup",
   7517                 4_102_444_800,
   7518                 4_102_531_200,
   7519                 LocalRecordStatus::Published,
   7520                 PublishOutboxStatus::Acknowledged,
   7521             ))
   7522             .expect("append active listing");
   7523         app_store
   7524             .import_shared_local_events_from_store(&events)
   7525             .expect("import active listing");
   7526         assert_eq!(buyer_listing_titles(&app_store), vec!["Current Eggs"]);
   7527         events
   7528             .append_record(&signed_market_listing_record(
   7529                 "newer-archived-window",
   7530                 "seller-pubkey",
   7531                 farm_key,
   7532                 listing_key,
   7533                 "Archived Eggs",
   7534                 "8",
   7535                 "archived",
   7536                 "pickup",
   7537                 "West barn pickup",
   7538                 4_102_444_800,
   7539                 4_102_531_200,
   7540                 LocalRecordStatus::Published,
   7541                 PublishOutboxStatus::Acknowledged,
   7542             ))
   7543             .expect("append archived listing");
   7544         app_store
   7545             .import_shared_local_events_from_store(&events)
   7546             .expect("import archived listing");
   7547         assert!(buyer_listing_titles(&app_store).is_empty());
   7548     }
   7549 
   7550     #[test]
   7551     fn older_signed_listing_import_does_not_roll_back_current_product_state() {
   7552         let app_store =
   7553             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7554         let events = local_events_store();
   7555         let farm_key = "CURRENTFARMAAAAAAAAAA";
   7556         let listing_key = "CURRENTLISTINGBBBBBB";
   7557         let mut newer = signed_market_listing_record(
   7558             "listing-current-newer",
   7559             "seller-pubkey",
   7560             farm_key,
   7561             listing_key,
   7562             "New Eggs",
   7563             "12",
   7564             "active",
   7565             "pickup",
   7566             "North barn pickup",
   7567             4_102_444_800,
   7568             4_102_531_200,
   7569             LocalRecordStatus::Published,
   7570             PublishOutboxStatus::Acknowledged,
   7571         );
   7572         set_listing_event_version(
   7573             &mut newer,
   7574             "event-listing-current-newer",
   7575             2_000,
   7576             "New Eggs",
   7577             "12",
   7578         );
   7579         events.append_record(&newer).expect("append newer listing");
   7580         app_store
   7581             .import_shared_local_events_from_store(&events)
   7582             .expect("import newer listing");
   7583 
   7584         let mut older = signed_market_listing_record(
   7585             "listing-current-older",
   7586             "seller-pubkey",
   7587             farm_key,
   7588             listing_key,
   7589             "Old Eggs",
   7590             "3",
   7591             "active",
   7592             "pickup",
   7593             "North barn pickup",
   7594             4_102_444_800,
   7595             4_102_531_200,
   7596             LocalRecordStatus::Published,
   7597             PublishOutboxStatus::Acknowledged,
   7598         );
   7599         set_listing_event_version(
   7600             &mut older,
   7601             "event-listing-current-older",
   7602             1_000,
   7603             "Old Eggs",
   7604             "3",
   7605         );
   7606         events.append_record(&older).expect("append older listing");
   7607 
   7608         let report = app_store
   7609             .import_shared_local_events_from_store(&events)
   7610             .expect("import older listing");
   7611         let product: (String, Option<i64>) = app_store
   7612             .connection()
   7613             .query_row("SELECT title, stock_count FROM products", [], |row| {
   7614                 Ok((row.get(0)?, row.get(1)?))
   7615             })
   7616             .expect("load product");
   7617         let imported = app_store
   7618             .load_local_interop_records()
   7619             .expect("load imported records");
   7620 
   7621         assert_eq!(report.imported_records, 1);
   7622         assert_eq!(product.0, "New Eggs");
   7623         assert_eq!(product.1, Some(12));
   7624         assert_eq!(
   7625             imported
   7626                 .iter()
   7627                 .filter(|record| record.projected_kind == "listing")
   7628                 .count(),
   7629             2
   7630         );
   7631     }
   7632 
   7633     #[test]
   7634     fn equal_timestamp_signed_listing_currentness_uses_event_id_tie_breaker() {
   7635         let app_store =
   7636             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7637         let events = local_events_store();
   7638         let farm_key = "TIEFARMAAAAAAAAAAAAAA";
   7639         let listing_key = "TIELISTINGBBBBBBBBBB";
   7640         let mut winning = signed_market_listing_record(
   7641             "listing-tie-winning",
   7642             "seller-pubkey",
   7643             farm_key,
   7644             listing_key,
   7645             "Tie Winner Eggs",
   7646             "10",
   7647             "active",
   7648             "pickup",
   7649             "North barn pickup",
   7650             4_102_444_800,
   7651             4_102_531_200,
   7652             LocalRecordStatus::Published,
   7653             PublishOutboxStatus::Acknowledged,
   7654         );
   7655         set_listing_event_version(
   7656             &mut winning,
   7657             "event-z-winning",
   7658             3_000,
   7659             "Tie Winner Eggs",
   7660             "10",
   7661         );
   7662         events
   7663             .append_record(&winning)
   7664             .expect("append winning listing");
   7665         app_store
   7666             .import_shared_local_events_from_store(&events)
   7667             .expect("import winning listing");
   7668 
   7669         let mut losing = signed_market_listing_record(
   7670             "listing-tie-losing",
   7671             "seller-pubkey",
   7672             farm_key,
   7673             listing_key,
   7674             "Tie Loser Eggs",
   7675             "1",
   7676             "active",
   7677             "pickup",
   7678             "North barn pickup",
   7679             4_102_444_800,
   7680             4_102_531_200,
   7681             LocalRecordStatus::Published,
   7682             PublishOutboxStatus::Acknowledged,
   7683         );
   7684         set_listing_event_version(&mut losing, "event-a-losing", 3_000, "Tie Loser Eggs", "1");
   7685         events
   7686             .append_record(&losing)
   7687             .expect("append losing listing");
   7688 
   7689         app_store
   7690             .import_shared_local_events_from_store(&events)
   7691             .expect("import losing listing");
   7692         let product: (String, Option<i64>) = app_store
   7693             .connection()
   7694             .query_row("SELECT title, stock_count FROM products", [], |row| {
   7695                 Ok((row.get(0)?, row.get(1)?))
   7696             })
   7697             .expect("load product");
   7698 
   7699         assert_eq!(product.0, "Tie Winner Eggs");
   7700         assert_eq!(product.1, Some(10));
   7701     }
   7702 
   7703     #[test]
   7704     fn signed_farm_import_prefers_event_identity_over_local_owner_metadata() {
   7705         let app_store =
   7706             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7707         let events = local_events_store();
   7708         let signed_farm_key = "SIGNEDFARMAAAAAAAAAAAA";
   7709         let expected_farm_id = deterministic_farm_id(Some("event-pubkey"), signed_farm_key);
   7710         events
   7711             .append_record(&LocalEventRecordInput {
   7712                 record_id: "cli:signed_event:farm:event-identity".to_owned(),
   7713                 family: LocalRecordFamily::SignedEvent,
   7714                 status: LocalRecordStatus::Published,
   7715                 source_runtime: SourceRuntime::Cli,
   7716                 created_at_ms: 1100,
   7717                 inserted_at_ms: 1101,
   7718                 owner_account_id: Some("seller-account".to_owned()),
   7719                 owner_pubkey: Some("stale-owner-pubkey".to_owned()),
   7720                 farm_id: Some("STALEFARMTAG".to_owned()),
   7721                 listing_addr: None,
   7722                 local_work_json: None,
   7723                 event_id: Some("event-farm-identity".to_owned()),
   7724                 event_kind: Some(KIND_FARM),
   7725                 event_pubkey: Some("event-pubkey".to_owned()),
   7726                 event_created_at: Some(1100),
   7727                 event_tags_json: Some(json!([["d", signed_farm_key]])),
   7728                 event_content: Some(
   7729                     json!({
   7730                         "d_tag": signed_farm_key,
   7731                         "name": "Signed Farm"
   7732                     })
   7733                     .to_string(),
   7734                 ),
   7735                 event_sig: Some("signature".to_owned()),
   7736                 raw_event_json: Some(json!({
   7737                     "id": "event-farm-identity",
   7738                     "kind": KIND_FARM,
   7739                     "pubkey": "event-pubkey"
   7740                 })),
   7741                 outbox_status: PublishOutboxStatus::Acknowledged,
   7742                 relay_set_fingerprint: Some("relay-set".to_owned()),
   7743                 relay_delivery_json: Some(json!({
   7744                     "state": "acknowledged",
   7745                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   7746                 })),
   7747             })
   7748             .expect("append signed farm");
   7749 
   7750         let report = app_store
   7751             .import_shared_local_events_from_store(&events)
   7752             .expect("import signed farm");
   7753         let imported = app_store
   7754             .load_local_interop_records()
   7755             .expect("load imported records");
   7756         let stored_farm: (String, String) = app_store
   7757             .connection()
   7758             .query_row("SELECT id, display_name FROM farms", [], |row| {
   7759                 Ok((row.get(0)?, row.get(1)?))
   7760             })
   7761             .expect("load farm");
   7762 
   7763         assert_eq!(report.imported_records, 1);
   7764         assert_eq!(imported[0].projected_kind, "farm");
   7765         assert_eq!(
   7766             imported[0].projected_id.as_deref(),
   7767             Some(expected_farm_id.to_string().as_str())
   7768         );
   7769         assert_eq!(stored_farm.0, expected_farm_id.to_string());
   7770         assert_eq!(stored_farm.1, "Signed Farm");
   7771     }
   7772 
   7773     #[test]
   7774     fn cli_signed_listing_import_uses_cli_identity_for_app_shaped_keys() {
   7775         let app_store =
   7776             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7777         let events = local_events_store();
   7778         let signed_farm_key =
   7779             app_d_tag_from_uuid(Uuid::from_u128(0x77777777777747778777777777777777));
   7780         let signed_listing_key =
   7781             app_d_tag_from_uuid(Uuid::from_u128(0x88888888888848888888888888888888));
   7782         let expected_farm_id =
   7783             deterministic_farm_id(Some("farm-tag-pubkey"), signed_farm_key.as_str());
   7784         let expected_product_id =
   7785             deterministic_product_id(Some("listing-event-pubkey"), signed_listing_key.as_str());
   7786         events
   7787             .append_record(&LocalEventRecordInput {
   7788                 record_id: "cli:signed_event:listing:event-identity".to_owned(),
   7789                 family: LocalRecordFamily::SignedEvent,
   7790                 status: LocalRecordStatus::Published,
   7791                 source_runtime: SourceRuntime::Cli,
   7792                 created_at_ms: 1100,
   7793                 inserted_at_ms: 1101,
   7794                 owner_account_id: Some("seller-account".to_owned()),
   7795                 owner_pubkey: Some("stale-owner-pubkey".to_owned()),
   7796                 farm_id: Some("STALEFARMTAG".to_owned()),
   7797                 listing_addr: Some("30402:stale-owner-pubkey:STALELISTING".to_owned()),
   7798                 local_work_json: None,
   7799                 event_id: Some("event-listing-identity".to_owned()),
   7800                 event_kind: Some(KIND_LISTING),
   7801                 event_pubkey: Some("listing-event-pubkey".to_owned()),
   7802                 event_created_at: Some(1100),
   7803                 event_tags_json: Some(json!([
   7804                     ["d", signed_listing_key],
   7805                     ["a", format!("30340:farm-tag-pubkey:{signed_farm_key}")],
   7806                     ["title", "Signed Event Eggs"],
   7807                     ["summary", "Signed event summary"],
   7808                     ["radroots:bin", "bin-1", "1", "each"],
   7809                     ["radroots:price", "bin-1", "8", "USD", "1", "each"],
   7810                     ["inventory", "9"],
   7811                     ["status", "active"]
   7812                 ])),
   7813                 event_content: Some(
   7814                     json!({
   7815                         "product": {
   7816                             "title": "Signed Event Eggs",
   7817                             "summary": "Signed event summary"
   7818                         }
   7819                     })
   7820                     .to_string(),
   7821                 ),
   7822                 event_sig: Some("signature".to_owned()),
   7823                 raw_event_json: Some(json!({
   7824                     "id": "event-listing-identity",
   7825                     "kind": KIND_LISTING,
   7826                     "pubkey": "listing-event-pubkey"
   7827                 })),
   7828                 outbox_status: PublishOutboxStatus::Acknowledged,
   7829                 relay_set_fingerprint: Some("relay-set".to_owned()),
   7830                 relay_delivery_json: Some(json!({
   7831                     "state": "acknowledged",
   7832                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   7833                 })),
   7834             })
   7835             .expect("append signed listing");
   7836 
   7837         let report = app_store
   7838             .import_shared_local_events_from_store(&events)
   7839             .expect("import signed listing");
   7840         let imported = app_store
   7841             .load_local_interop_records()
   7842             .expect("load imported records");
   7843         let product: (String, String) = app_store
   7844             .connection()
   7845             .query_row("SELECT id, farm_id FROM products", [], |row| {
   7846                 Ok((row.get(0)?, row.get(1)?))
   7847             })
   7848             .expect("load product");
   7849 
   7850         assert_eq!(report.imported_records, 1);
   7851         assert_eq!(imported[0].projected_kind, "listing");
   7852         assert_eq!(
   7853             imported[0].projected_id.as_deref(),
   7854             Some(expected_product_id.to_string().as_str())
   7855         );
   7856         assert_eq!(product.0, expected_product_id.to_string());
   7857         assert_eq!(product.1, expected_farm_id.to_string());
   7858     }
   7859 
   7860     #[test]
   7861     fn direct_record_import_dedupes_signed_events_by_event_id() {
   7862         let app_store =
   7863             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7864         let events = local_events_store();
   7865         let farm_key = "SIGNEDFARMAAAAAAAAAAAA";
   7866         let listing_key = "SIGNEDLISTINGBBBBBBBB";
   7867         let first = events
   7868             .append_record(&signed_listing_record(
   7869                 "shared-record",
   7870                 farm_key,
   7871                 listing_key,
   7872                 "active",
   7873             ))
   7874             .expect("append shared signed listing");
   7875         let mut duplicate = signed_listing_record("relay-record", farm_key, listing_key, "active");
   7876         duplicate.event_id = first.event_id.clone();
   7877         let duplicate = events
   7878             .append_record(&duplicate)
   7879             .expect("append relay signed listing");
   7880 
   7881         let report = app_store
   7882             .import_local_event_records(&[first, duplicate])
   7883             .expect("direct records should import");
   7884         let imported = app_store
   7885             .load_local_interop_records()
   7886             .expect("load imported records");
   7887 
   7888         assert_eq!(report.scanned_records, 2);
   7889         assert_eq!(report.imported_records, 1);
   7890         assert_eq!(report.skipped_records, 1);
   7891         assert_eq!(
   7892             imported
   7893                 .iter()
   7894                 .filter(|record| record.projected_kind == "listing")
   7895                 .count(),
   7896             1
   7897         );
   7898     }
   7899 
   7900     #[test]
   7901     fn app_order_request_receipt_replaces_prior_relay_duplicate() {
   7902         let app_store =
   7903             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7904         let events = local_events_store();
   7905         let seller_pubkey = test_pubkey("seller-pubkey");
   7906         let seller_pubkey = seller_pubkey.as_str();
   7907         let buyer_pubkey = test_pubkey("buyer-pubkey");
   7908         let buyer_pubkey = buyer_pubkey.as_str();
   7909         let listing_addr = format!("30402:{seller_pubkey}:app-order-listing");
   7910         let payload = order_request_payload(
   7911             "app-order-receipt-replaces-relay",
   7912             listing_addr.as_str(),
   7913             buyer_pubkey,
   7914             seller_pubkey,
   7915         );
   7916         let parts = order_request_event_build(&listing_event_ptr("listing-event"), &payload)
   7917             .expect("build order request event");
   7918         let event = event_from_parts("app-order-request-event", buyer_pubkey, parts);
   7919         let mut relay_record = signed_order_event_record(
   7920             "app:relay_event:order-request:duplicate",
   7921             &event,
   7922             listing_addr.as_str(),
   7923             SourceRuntime::Cli,
   7924             None,
   7925         );
   7926         relay_record.outbox_status = PublishOutboxStatus::None;
   7927         relay_record.relay_delivery_json = Some(json!({
   7928             "state": "observed",
   7929             "observed_relays": ["ws://127.0.0.1:1234/"]
   7930         }));
   7931         let relay_record = events
   7932             .append_record(&relay_record)
   7933             .expect("append relay order request");
   7934         let app_record = events
   7935             .append_record(&signed_order_event_record(
   7936                 "app:signed_event:order-request:duplicate",
   7937                 &event,
   7938                 listing_addr.as_str(),
   7939                 SourceRuntime::App,
   7940                 Some("acct_buyer"),
   7941             ))
   7942             .expect("append app order request receipt");
   7943 
   7944         let report = app_store
   7945             .import_local_event_records(&[relay_record, app_record])
   7946             .expect("import duplicate order request records");
   7947         let imported = app_store
   7948             .load_local_interop_records()
   7949             .expect("load imported records");
   7950         let stored = imported
   7951             .iter()
   7952             .find(|record| record.event_id.as_deref() == Some(event.id.as_str()))
   7953             .expect("app order request evidence");
   7954 
   7955         assert_eq!(report.imported_records, 2);
   7956         assert_eq!(report.skipped_records, 0);
   7957         assert_eq!(
   7958             imported
   7959                 .iter()
   7960                 .filter(|record| record.event_id.as_deref() == Some(event.id.as_str()))
   7961                 .count(),
   7962             1
   7963         );
   7964         assert_eq!(stored.record_id, "app:signed_event:order-request:duplicate");
   7965         assert_eq!(stored.source_runtime, SourceRuntime::App.as_str());
   7966         assert_eq!(stored.owner_account_id.as_deref(), Some("acct_buyer"));
   7967         assert_eq!(
   7968             stored.outbox_status,
   7969             PublishOutboxStatus::Acknowledged.as_str()
   7970         );
   7971         assert_eq!(stored.listing_addr.as_deref(), Some(listing_addr.as_str()));
   7972     }
   7973 
   7974     #[test]
   7975     fn relay_order_decision_duplicate_does_not_downgrade_app_receipt() {
   7976         let app_store =
   7977             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   7978         let events = local_events_store();
   7979         let seller_pubkey = test_pubkey("seller-pubkey");
   7980         let seller_pubkey = seller_pubkey.as_str();
   7981         let buyer_pubkey = test_pubkey("buyer-pubkey");
   7982         let buyer_pubkey = buyer_pubkey.as_str();
   7983         let listing_addr = format!("30402:{seller_pubkey}:app-decision-listing");
   7984         let request_payload = order_request_payload(
   7985             "app-decision-receipt",
   7986             listing_addr.as_str(),
   7987             buyer_pubkey,
   7988             seller_pubkey,
   7989         );
   7990         let request_parts =
   7991             order_request_event_build(&listing_event_ptr("listing-event"), &request_payload)
   7992                 .expect("build order request event");
   7993         let request_event =
   7994             event_from_parts("app-decision-request-event", buyer_pubkey, request_parts);
   7995         let decision_payload = accepted_order_decision_payload(
   7996             "app-decision-receipt",
   7997             listing_addr.as_str(),
   7998             buyer_pubkey,
   7999             seller_pubkey,
   8000         );
   8001         let decision_parts = order_decision_event_build(
   8002             &typed_event_id(request_event.id.as_str()),
   8003             &typed_event_id(request_event.id.as_str()),
   8004             &decision_payload,
   8005         )
   8006         .expect("build order decision event");
   8007         let decision_event =
   8008             event_from_parts("app-order-decision-event", seller_pubkey, decision_parts);
   8009         let app_record = events
   8010             .append_record(&signed_order_event_record(
   8011                 "app:signed_event:order-decision:duplicate",
   8012                 &decision_event,
   8013                 listing_addr.as_str(),
   8014                 SourceRuntime::App,
   8015                 Some("acct_seller"),
   8016             ))
   8017             .expect("append app order decision receipt");
   8018         let mut relay_record = signed_order_event_record(
   8019             "app:relay_event:order-decision:duplicate",
   8020             &decision_event,
   8021             listing_addr.as_str(),
   8022             SourceRuntime::Cli,
   8023             None,
   8024         );
   8025         relay_record.outbox_status = PublishOutboxStatus::None;
   8026         relay_record.relay_delivery_json = Some(json!({
   8027             "state": "observed",
   8028             "observed_relays": ["ws://127.0.0.1:1234/"]
   8029         }));
   8030         let relay_record = events
   8031             .append_record(&relay_record)
   8032             .expect("append relay order decision");
   8033 
   8034         let report = app_store
   8035             .import_local_event_records(&[app_record, relay_record])
   8036             .expect("import duplicate order decision records");
   8037         let imported = app_store
   8038             .load_local_interop_records()
   8039             .expect("load imported records");
   8040         let stored = imported
   8041             .iter()
   8042             .find(|record| record.event_id.as_deref() == Some(decision_event.id.as_str()))
   8043             .expect("app order decision evidence");
   8044 
   8045         assert_eq!(report.imported_records, 1);
   8046         assert_eq!(report.skipped_records, 1);
   8047         assert_eq!(
   8048             imported
   8049                 .iter()
   8050                 .filter(|record| record.event_id.as_deref() == Some(decision_event.id.as_str()))
   8051                 .count(),
   8052             1
   8053         );
   8054         assert_eq!(
   8055             stored.record_id,
   8056             "app:signed_event:order-decision:duplicate"
   8057         );
   8058         assert_eq!(stored.source_runtime, SourceRuntime::App.as_str());
   8059         assert_eq!(stored.owner_account_id.as_deref(), Some("acct_seller"));
   8060         assert_eq!(
   8061             stored.outbox_status,
   8062             PublishOutboxStatus::Acknowledged.as_str()
   8063         );
   8064         assert_eq!(stored.listing_addr.as_deref(), Some(listing_addr.as_str()));
   8065     }
   8066 
   8067     #[test]
   8068     fn local_work_farm_import_preserves_duplicate_relay_signed_ready_farm() {
   8069         let app_store =
   8070             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8071         let relay_events = local_events_store();
   8072         let shared_events = local_events_store();
   8073         let farm_uuid = Uuid::from_u128(0x55555555555545558555555555555555);
   8074         let farm_key = app_d_tag_from_uuid(farm_uuid);
   8075         let signed_event_id = "event-app-relay-ready-farm";
   8076         let relay_record = relay_events
   8077             .append_record(&signed_farm_record(
   8078                 "app:relay_event:farm-ready",
   8079                 signed_event_id,
   8080                 SourceRuntime::App,
   8081                 "app-seller-pubkey",
   8082                 farm_key.as_str(),
   8083                 "ready",
   8084                 "Relay Ready Farm",
   8085             ))
   8086             .expect("append relay farm");
   8087         let direct_report = app_store
   8088             .import_local_event_records(&[relay_record])
   8089             .expect("direct relay import");
   8090         let local_farm_record = app_local_work_record(
   8091             "app:local_work:farm:ready-preserve",
   8092             farm_key.as_str(),
   8093             json!({
   8094                 "record_kind": "farm_config_v1",
   8095                 "document": {
   8096                     "selection": {
   8097                         "account": "seller-account",
   8098                         "farm_d_tag": farm_key
   8099                     },
   8100                     "profile": {
   8101                         "display_name": "Draft Farm"
   8102                     },
   8103                     "farm": {
   8104                         "d_tag": farm_key,
   8105                         "name": "Draft Farm"
   8106                     }
   8107                 }
   8108             }),
   8109         );
   8110         shared_events
   8111             .append_record(&local_farm_record)
   8112             .expect("append local farm work");
   8113         shared_events
   8114             .append_record(&signed_farm_record(
   8115                 "app:signed_event:farm-ready",
   8116                 signed_event_id,
   8117                 SourceRuntime::App,
   8118                 "app-seller-pubkey",
   8119                 farm_key.as_str(),
   8120                 "ready",
   8121                 "Relay Ready Farm",
   8122             ))
   8123             .expect("append duplicate signed farm");
   8124 
   8125         let shared_report = app_store
   8126             .import_shared_local_events_from_store(&shared_events)
   8127             .expect("import shared local work after relay");
   8128         let stored_farm: (String, String, String) = app_store
   8129             .connection()
   8130             .query_row("SELECT id, display_name, readiness FROM farms", [], |row| {
   8131                 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
   8132             })
   8133             .expect("load farm");
   8134 
   8135         assert_eq!(direct_report.imported_records, 1);
   8136         assert_eq!(shared_report.imported_records, 1);
   8137         assert_eq!(shared_report.skipped_records, 1);
   8138         assert_eq!(stored_farm.0, farm_uuid.to_string());
   8139         assert_eq!(stored_farm.1, "Draft Farm");
   8140         assert_eq!(stored_farm.2, "ready");
   8141     }
   8142 
   8143     #[test]
   8144     fn signed_farm_without_readiness_preserves_listing_visible_farm() {
   8145         let app_store =
   8146             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8147         let events = local_events_store();
   8148         let farm_key = "SIGNEDFARMAAAAAAAAAAAA";
   8149         let listing_key = "SIGNEDLISTINGBBBBBBBB";
   8150         let expected_farm_id = deterministic_farm_id(Some("seller-pubkey"), farm_key);
   8151         events
   8152             .append_record(&signed_market_listing_record(
   8153                 "visible-listing",
   8154                 "seller-pubkey",
   8155                 farm_key,
   8156                 listing_key,
   8157                 "Relay Ready Eggs",
   8158                 "8",
   8159                 "active",
   8160                 "pickup",
   8161                 "West barn pickup",
   8162                 4_102_444_800,
   8163                 4_102_531_200,
   8164                 LocalRecordStatus::Published,
   8165                 PublishOutboxStatus::Acknowledged,
   8166             ))
   8167             .expect("append visible listing");
   8168         events
   8169             .append_record(&LocalEventRecordInput {
   8170                 record_id: "cli:signed_event:farm:no-readiness".to_owned(),
   8171                 family: LocalRecordFamily::SignedEvent,
   8172                 status: LocalRecordStatus::Published,
   8173                 source_runtime: SourceRuntime::Cli,
   8174                 created_at_ms: 1200,
   8175                 inserted_at_ms: 1201,
   8176                 owner_account_id: Some("seller-account".to_owned()),
   8177                 owner_pubkey: Some("seller-pubkey".to_owned()),
   8178                 farm_id: Some(farm_key.to_owned()),
   8179                 listing_addr: None,
   8180                 local_work_json: None,
   8181                 event_id: Some("event-farm-no-readiness".to_owned()),
   8182                 event_kind: Some(KIND_FARM),
   8183                 event_pubkey: Some("seller-pubkey".to_owned()),
   8184                 event_created_at: Some(1200),
   8185                 event_tags_json: Some(json!([["d", farm_key]])),
   8186                 event_content: Some(
   8187                     json!({
   8188                         "d_tag": farm_key,
   8189                         "name": "Relay Ready Farm"
   8190                     })
   8191                     .to_string(),
   8192                 ),
   8193                 event_sig: Some("signature".to_owned()),
   8194                 raw_event_json: Some(json!({
   8195                     "id": "event-farm-no-readiness",
   8196                     "kind": KIND_FARM,
   8197                     "pubkey": "seller-pubkey"
   8198                 })),
   8199                 outbox_status: PublishOutboxStatus::Acknowledged,
   8200                 relay_set_fingerprint: Some("relay-set".to_owned()),
   8201                 relay_delivery_json: Some(json!({
   8202                     "state": "acknowledged",
   8203                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   8204                 })),
   8205             })
   8206             .expect("append farm without readiness");
   8207 
   8208         let report = app_store
   8209             .import_shared_local_events_from_store(&events)
   8210             .expect("import listing and farm");
   8211         let stored_farm: (String, String, String) = app_store
   8212             .connection()
   8213             .query_row("SELECT id, display_name, readiness FROM farms", [], |row| {
   8214                 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
   8215             })
   8216             .expect("load farm");
   8217 
   8218         assert_eq!(report.imported_records, 2);
   8219         assert_eq!(stored_farm.0, expected_farm_id.to_string());
   8220         assert_eq!(stored_farm.1, "Relay Ready Farm");
   8221         assert_eq!(stored_farm.2, "ready");
   8222         assert_eq!(buyer_listing_titles(&app_store), vec!["Relay Ready Eggs"]);
   8223     }
   8224 
   8225     #[test]
   8226     fn maps_acknowledged_signed_listing_lifecycle_statuses() {
   8227         for (status_tag, expected_product_status) in [
   8228             ("active", "published"),
   8229             ("window", "published"),
   8230             ("archived", "archived"),
   8231             ("sold", "paused"),
   8232         ] {
   8233             let app_store =
   8234                 AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8235             let events = local_events_store();
   8236             let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   8237             let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   8238             events
   8239                 .append_record(&signed_listing_record(
   8240                     status_tag,
   8241                     farm_key,
   8242                     listing_key,
   8243                     status_tag,
   8244                 ))
   8245                 .expect("append signed listing");
   8246 
   8247             let report = app_store
   8248                 .import_shared_local_events_from_store(&events)
   8249                 .expect("import signed listing");
   8250             let product_status: String = app_store
   8251                 .connection()
   8252                 .query_row("SELECT status FROM products", [], |row| row.get(0))
   8253                 .expect("load product status");
   8254 
   8255             assert_eq!(report.imported_records, 1);
   8256             assert_eq!(report.skipped_records, 0);
   8257             assert_eq!(product_status, expected_product_status);
   8258         }
   8259     }
   8260 
   8261     #[test]
   8262     fn maps_observed_signed_listing_as_published_without_outbox_acknowledgement() {
   8263         let app_store =
   8264             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8265         let events = local_events_store();
   8266         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   8267         let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   8268         let mut record = signed_listing_record_with_publish_state(
   8269             "observed-listing",
   8270             farm_key,
   8271             listing_key,
   8272             "active",
   8273             LocalRecordStatus::Published,
   8274             PublishOutboxStatus::None,
   8275         );
   8276         record.relay_delivery_json = Some(json!({
   8277             "state": "observed",
   8278             "target_relays": ["ws://127.0.0.1:1234"],
   8279             "connected_relays": ["ws://127.0.0.1:1234"],
   8280             "acknowledged_relays": [],
   8281             "observed_relays": ["ws://127.0.0.1:1234"],
   8282             "failed_relays": []
   8283         }));
   8284         events
   8285             .append_record(&record)
   8286             .expect("append observed signed listing");
   8287 
   8288         let report = app_store
   8289             .import_shared_local_events_from_store(&events)
   8290             .expect("import observed signed listing");
   8291         let product_status: String = app_store
   8292             .connection()
   8293             .query_row("SELECT status FROM products", [], |row| row.get(0))
   8294             .expect("load product status");
   8295 
   8296         assert_eq!(report.imported_records, 1);
   8297         assert_eq!(report.skipped_records, 0);
   8298         assert_eq!(product_status, "published");
   8299     }
   8300 
   8301     #[test]
   8302     fn unknown_acknowledged_signed_listing_status_is_not_published() {
   8303         let app_store =
   8304             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8305         let events = local_events_store();
   8306         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   8307         let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   8308         events
   8309             .append_record(&signed_listing_record(
   8310                 "unknown-status",
   8311                 farm_key,
   8312                 listing_key,
   8313                 "unknown-status",
   8314             ))
   8315             .expect("append signed listing");
   8316 
   8317         let report = app_store
   8318             .import_shared_local_events_from_store(&events)
   8319             .expect("import signed listing");
   8320         let imported = app_store
   8321             .load_local_interop_records()
   8322             .expect("load imported records");
   8323         let product_count: i64 = app_store
   8324             .connection()
   8325             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   8326             .expect("product count");
   8327 
   8328         assert_eq!(report.imported_records, 0);
   8329         assert_eq!(report.skipped_records, 1);
   8330         assert_eq!(imported[0].projected_kind, "unsupported");
   8331         assert_eq!(product_count, 0);
   8332     }
   8333 
   8334     #[test]
   8335     fn pending_or_failed_signed_listing_records_do_not_downgrade_published_product() {
   8336         for (record_status, outbox_status) in [
   8337             (
   8338                 LocalRecordStatus::PendingPublish,
   8339                 PublishOutboxStatus::Pending,
   8340             ),
   8341             (LocalRecordStatus::Failed, PublishOutboxStatus::Failed),
   8342         ] {
   8343             let app_store =
   8344                 AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8345             let events = local_events_store();
   8346             let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   8347             let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   8348             events
   8349                 .append_record(&signed_listing_record(
   8350                     "confirmed",
   8351                     farm_key,
   8352                     listing_key,
   8353                     "active",
   8354                 ))
   8355                 .expect("append confirmed signed listing");
   8356             app_store
   8357                 .import_shared_local_events_from_store(&events)
   8358                 .expect("import confirmed signed listing");
   8359             events
   8360                 .append_record(&signed_listing_record_with_publish_state(
   8361                     record_status.as_str(),
   8362                     farm_key,
   8363                     listing_key,
   8364                     "active",
   8365                     record_status,
   8366                     outbox_status,
   8367                 ))
   8368                 .expect("append unconfirmed signed listing");
   8369 
   8370             app_store
   8371                 .import_shared_local_events_from_store(&events)
   8372                 .expect("import unconfirmed signed listing");
   8373             let product_status: String = app_store
   8374                 .connection()
   8375                 .query_row("SELECT status FROM products", [], |row| row.get(0))
   8376                 .expect("load product status");
   8377             let imported = app_store
   8378                 .load_local_interop_records()
   8379                 .expect("load imported records");
   8380 
   8381             assert_eq!(product_status, "published");
   8382             assert!(imported.iter().any(|record| {
   8383                 record.local_status == record_status.as_str()
   8384                     && record.outbox_status == outbox_status.as_str()
   8385             }));
   8386         }
   8387     }
   8388 
   8389     #[test]
   8390     fn observes_outbox_updates_after_first_import_without_replaying_unchanged_rows() {
   8391         let app_store =
   8392             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8393         let events = local_events_store();
   8394         let farm_key = "AAAAAAAAAAAAAAAAAAAAAA";
   8395         let listing_key = "BBBBBBBBBBBBBBBBBBBBBB";
   8396         events
   8397             .append_record(&signed_listing_record_with_publish_state(
   8398                 "pending-listing",
   8399                 farm_key,
   8400                 listing_key,
   8401                 "active",
   8402                 LocalRecordStatus::PendingPublish,
   8403                 PublishOutboxStatus::Pending,
   8404             ))
   8405             .expect("append pending signed listing");
   8406         let first_report = app_store
   8407             .import_shared_local_events_from_store(&events)
   8408             .expect("import pending listing");
   8409         let unchanged_report = app_store
   8410             .import_shared_local_events_from_store(&events)
   8411             .expect("import unchanged listing");
   8412 
   8413         assert_eq!(first_report.scanned_records, 1);
   8414         assert_eq!(first_report.imported_records, 1);
   8415         assert_eq!(unchanged_report.scanned_records, 0);
   8416 
   8417         events
   8418             .update_outbox(&LocalEventRecordUpdate {
   8419                 record_id: "pending-listing".to_owned(),
   8420                 status: LocalRecordStatus::Published,
   8421                 outbox_status: PublishOutboxStatus::Acknowledged,
   8422                 relay_set_fingerprint: Some("relay-set".to_owned()),
   8423                 relay_delivery_json: Some(json!({
   8424                     "state": "acknowledged",
   8425                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   8426                 })),
   8427                 updated_at_ms: 1200,
   8428             })
   8429             .expect("update listing outbox");
   8430         let changed_report = app_store
   8431             .import_shared_local_events_from_store(&events)
   8432             .expect("import updated listing");
   8433         let product_status: String = app_store
   8434             .connection()
   8435             .query_row("SELECT status FROM products", [], |row| row.get(0))
   8436             .expect("load product status");
   8437         let imported = app_store
   8438             .load_local_interop_records()
   8439             .expect("load imported records");
   8440 
   8441         assert_eq!(changed_report.scanned_records, 1);
   8442         assert_eq!(changed_report.imported_records, 1);
   8443         assert_eq!(product_status, "published");
   8444         assert_eq!(imported.len(), 1);
   8445         assert_eq!(imported[0].local_status, "published");
   8446         assert_eq!(imported[0].outbox_status, "acknowledged");
   8447     }
   8448 
   8449     #[test]
   8450     fn app_authored_shared_records_replay_into_fresh_store_without_origin_duplicates() {
   8451         let events = local_events_store();
   8452         let farm_uuid = Uuid::from_u128(0x11111111111111111111111111111111);
   8453         let product_uuid = Uuid::from_u128(0x22222222222222222222222222222222);
   8454         let farm_key = app_d_tag_from_uuid(farm_uuid);
   8455         let listing_key = app_d_tag_from_uuid(product_uuid);
   8456         let app_farm_record = app_local_work_record(
   8457             "app:local_work:farm",
   8458             farm_key.as_str(),
   8459             json!({
   8460                 "record_kind": "farm_config_v1",
   8461                 "document": {
   8462                     "selection": {
   8463                         "account": "seller-account",
   8464                         "farm_d_tag": farm_key
   8465                     },
   8466                     "profile": {
   8467                         "display_name": "App Farm"
   8468                     },
   8469                     "farm": {
   8470                         "d_tag": farm_key,
   8471                         "name": "App Farm",
   8472                         "location": {
   8473                             "primary": "app farmstand"
   8474                         }
   8475                     },
   8476                     "listing_defaults": {
   8477                         "delivery_method": "pickup",
   8478                         "location": {
   8479                             "primary": "app farmstand"
   8480                         }
   8481                     }
   8482                 }
   8483             }),
   8484         );
   8485         let mut app_listing_record = app_local_work_record(
   8486             "app:local_work:listing",
   8487             farm_key.as_str(),
   8488             json!({
   8489                 "record_kind": "listing_draft_v1",
   8490                 "document": {
   8491                     "listing": {
   8492                         "d_tag": listing_key,
   8493                         "farm_d_tag": farm_key
   8494                     },
   8495                     "seller_actor": {
   8496                         "account_id": "seller-account",
   8497                         "pubkey": "app-seller-pubkey"
   8498                     },
   8499                     "product": {
   8500                         "key": listing_key,
   8501                         "title": "App Eggs",
   8502                         "summary": "Fresh app-origin eggs"
   8503                     },
   8504                     "primary_bin": {
   8505                         "quantity_unit": "each",
   8506                         "price_amount": "7",
   8507                         "price_currency": "USD"
   8508                     },
   8509                     "inventory": {
   8510                         "available": "12"
   8511                     }
   8512                 }
   8513             }),
   8514         );
   8515         app_listing_record.listing_addr = Some(format!("30402:app-seller-pubkey:{listing_key}"));
   8516         events
   8517             .append_record(&app_farm_record)
   8518             .expect("append app farm local work");
   8519         events
   8520             .append_record(&app_listing_record)
   8521             .expect("append app listing local work");
   8522 
   8523         let origin_store =
   8524             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open origin app sqlite store");
   8525         seed_app_projection(&origin_store, farm_uuid, product_uuid);
   8526         let origin_report = origin_store
   8527             .import_shared_local_events_from_store(&events)
   8528             .expect("import shared local events into origin store");
   8529         let origin_second_report = origin_store
   8530             .import_shared_local_events_from_store(&events)
   8531             .expect("import unchanged shared local events into origin store");
   8532         let origin_product_count: i64 = origin_store
   8533             .connection()
   8534             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   8535             .expect("origin product count");
   8536         let origin_product: (String, String, String, Option<i64>, Option<i64>) = origin_store
   8537             .connection()
   8538             .query_row(
   8539                 "SELECT id, farm_id, title, price_minor_units, stock_count FROM products",
   8540                 [],
   8541                 |row| {
   8542                     Ok((
   8543                         row.get(0)?,
   8544                         row.get(1)?,
   8545                         row.get(2)?,
   8546                         row.get(3)?,
   8547                         row.get(4)?,
   8548                     ))
   8549                 },
   8550             )
   8551             .expect("load origin product");
   8552         let origin_imports = origin_store
   8553             .load_local_interop_records()
   8554             .expect("load origin imported records");
   8555 
   8556         assert_eq!(origin_report.scanned_records, 2);
   8557         assert_eq!(origin_report.imported_records, 2);
   8558         assert_eq!(origin_report.skipped_records, 0);
   8559         assert_eq!(origin_report.self_observed_records, 0);
   8560         assert_eq!(origin_second_report.scanned_records, 0);
   8561         assert_eq!(origin_product_count, 1);
   8562         assert_eq!(origin_product.0, product_uuid.to_string());
   8563         assert_eq!(origin_product.1, farm_uuid.to_string());
   8564         assert_eq!(origin_product.2, "App Eggs");
   8565         assert_eq!(origin_product.3, Some(700));
   8566         assert_eq!(origin_product.4, Some(12));
   8567         assert_eq!(origin_imports.len(), 2);
   8568 
   8569         let fresh_store =
   8570             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open fresh app sqlite store");
   8571         let fresh_report = fresh_store
   8572             .import_shared_local_events_from_store(&events)
   8573             .expect("import shared local events into fresh store");
   8574         let fresh_product_count: i64 = fresh_store
   8575             .connection()
   8576             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   8577             .expect("fresh product count");
   8578         let fresh_product: (String, String, String) = fresh_store
   8579             .connection()
   8580             .query_row("SELECT id, farm_id, title FROM products", [], |row| {
   8581                 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
   8582             })
   8583             .expect("load fresh product");
   8584         let fresh_imports = fresh_store
   8585             .load_local_interop_records()
   8586             .expect("load fresh imported records");
   8587 
   8588         assert_eq!(fresh_report.scanned_records, 2);
   8589         assert_eq!(fresh_report.imported_records, 2);
   8590         assert_eq!(fresh_report.skipped_records, 0);
   8591         assert_eq!(fresh_report.self_observed_records, 0);
   8592         assert_eq!(fresh_product_count, 1);
   8593         assert_eq!(fresh_product.0, product_uuid.to_string());
   8594         assert_eq!(fresh_product.1, farm_uuid.to_string());
   8595         assert_eq!(fresh_product.2, "App Eggs");
   8596         assert_eq!(fresh_imports.len(), 2);
   8597     }
   8598 
   8599     #[test]
   8600     fn app_authored_records_with_non_uuid_tags_do_not_fallback_to_cli_identity() {
   8601         let app_store =
   8602             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8603         let events = local_events_store();
   8604         let app_record = app_local_work_record(
   8605             "app:local_work:farm:invalid-tag",
   8606             "not-a-uuid-d-tag",
   8607             json!({
   8608                 "record_kind": "farm_config_v1",
   8609                 "document": {
   8610                     "selection": {
   8611                         "account": "seller-account",
   8612                         "farm_d_tag": "not-a-uuid-d-tag"
   8613                     },
   8614                     "profile": {
   8615                         "display_name": "App Farm"
   8616                     },
   8617                     "farm": {
   8618                         "d_tag": "not-a-uuid-d-tag",
   8619                         "name": "App Farm"
   8620                     }
   8621                 }
   8622             }),
   8623         );
   8624         events
   8625             .append_record(&app_record)
   8626             .expect("append app local work");
   8627 
   8628         let report = app_store
   8629             .import_shared_local_events_from_store(&events)
   8630             .expect("import shared local events");
   8631         let imported = app_store
   8632             .load_local_interop_records()
   8633             .expect("load imported records");
   8634         let farm_count: i64 = app_store
   8635             .connection()
   8636             .query_row("SELECT COUNT(*) FROM farms", [], |row| row.get(0))
   8637             .expect("farm count");
   8638 
   8639         assert_eq!(report.scanned_records, 1);
   8640         assert_eq!(report.imported_records, 0);
   8641         assert_eq!(report.skipped_records, 1);
   8642         assert_eq!(report.self_observed_records, 0);
   8643         assert_eq!(imported.len(), 1);
   8644         assert_eq!(imported[0].projected_kind, "unsupported");
   8645         assert_eq!(farm_count, 0);
   8646     }
   8647 
   8648     #[test]
   8649     fn signed_app_origin_listing_updates_existing_app_projection() {
   8650         let app_store =
   8651             AppSqliteStore::open(DatabaseTarget::InMemory).expect("open app sqlite store");
   8652         let events = local_events_store();
   8653         let farm_uuid = Uuid::from_u128(0x33333333333343338333333333333333);
   8654         let product_uuid = Uuid::from_u128(0x44444444444444448444444444444444);
   8655         let farm_key = app_d_tag_from_uuid(farm_uuid);
   8656         let listing_key = app_d_tag_from_uuid(product_uuid);
   8657         let listing_addr = format!("30402:app-seller-pubkey:{listing_key}");
   8658         let app_farm_record = app_local_work_record(
   8659             "app:local_work:farm:signed-convergence",
   8660             farm_key.as_str(),
   8661             json!({
   8662                 "record_kind": "farm_config_v1",
   8663                 "document": {
   8664                     "selection": {
   8665                         "account": "seller-account",
   8666                         "farm_d_tag": farm_key
   8667                     },
   8668                     "profile": {
   8669                         "display_name": "App Farm"
   8670                     },
   8671                     "farm": {
   8672                         "d_tag": farm_key,
   8673                         "name": "App Farm"
   8674                     }
   8675                 }
   8676             }),
   8677         );
   8678         let mut app_listing_record = app_local_work_record(
   8679             "app:local_work:listing:signed-convergence",
   8680             farm_key.as_str(),
   8681             json!({
   8682                 "record_kind": "listing_draft_v1",
   8683                 "document": {
   8684                     "listing": {
   8685                         "d_tag": listing_key,
   8686                         "farm_d_tag": farm_key
   8687                     },
   8688                     "seller_actor": {
   8689                         "account_id": "seller-account",
   8690                         "pubkey": "app-seller-pubkey"
   8691                     },
   8692                     "product": {
   8693                         "key": listing_key,
   8694                         "title": "App Draft Eggs",
   8695                         "summary": "Fresh app-origin eggs"
   8696                     },
   8697                     "primary_bin": {
   8698                         "quantity_unit": "each",
   8699                         "price_amount": "7",
   8700                         "price_currency": "USD"
   8701                     },
   8702                     "inventory": {
   8703                         "available": "12"
   8704                     }
   8705                 }
   8706             }),
   8707         );
   8708         app_listing_record.listing_addr = Some(listing_addr.clone());
   8709         events
   8710             .append_record(&app_farm_record)
   8711             .expect("append app farm local work");
   8712         events
   8713             .append_record(&app_listing_record)
   8714             .expect("append app listing local work");
   8715 
   8716         let local_report = app_store
   8717             .import_shared_local_events_from_store(&events)
   8718             .expect("import app local work");
   8719         events
   8720             .append_record(&LocalEventRecordInput {
   8721                 record_id: "cli:signed_event:listing:app-origin".to_owned(),
   8722                 family: LocalRecordFamily::SignedEvent,
   8723                 status: LocalRecordStatus::Published,
   8724                 source_runtime: SourceRuntime::Cli,
   8725                 created_at_ms: 1100,
   8726                 inserted_at_ms: 1101,
   8727                 owner_account_id: Some("seller-account".to_owned()),
   8728                 owner_pubkey: Some("app-seller-pubkey".to_owned()),
   8729                 farm_id: Some(farm_key.clone()),
   8730                 listing_addr: Some(listing_addr.clone()),
   8731                 local_work_json: None,
   8732                 event_id: Some("event-app-origin".to_owned()),
   8733                 event_kind: Some(KIND_LISTING),
   8734                 event_pubkey: Some("app-seller-pubkey".to_owned()),
   8735                 event_created_at: Some(1100),
   8736                 event_tags_json: Some(json!([
   8737                     ["d", listing_key],
   8738                     ["a", format!("30340:app-seller-pubkey:{farm_key}")],
   8739                     ["title", "Relay App Eggs"],
   8740                     ["summary", "Published app-origin eggs"],
   8741                     ["radroots:bin", "bin-1", "1", "each"],
   8742                     ["radroots:price", "bin-1", "8", "USD", "1", "each"],
   8743                     ["inventory", "9"],
   8744                     ["status", "active"]
   8745                 ])),
   8746                 event_content: Some("# Relay App Eggs\n\nPublished app-origin eggs".to_owned()),
   8747                 event_sig: Some("signature".to_owned()),
   8748                 raw_event_json: Some(json!({
   8749                     "id": "event-app-origin",
   8750                     "kind": KIND_LISTING,
   8751                     "pubkey": "app-seller-pubkey",
   8752                     "content": "# Relay App Eggs\n\nPublished app-origin eggs"
   8753                 })),
   8754                 outbox_status: PublishOutboxStatus::Acknowledged,
   8755                 relay_set_fingerprint: Some("relay-set".to_owned()),
   8756                 relay_delivery_json: Some(json!({
   8757                     "state": "acknowledged",
   8758                     "acknowledged_relays": ["ws://127.0.0.1:1234/"]
   8759                 })),
   8760             })
   8761             .expect("append signed app-origin listing");
   8762         let signed_report = app_store
   8763             .import_shared_local_events_from_store(&events)
   8764             .expect("import signed app-origin listing");
   8765         let imported = app_store
   8766             .load_local_interop_records()
   8767             .expect("load imported records");
   8768         let listing_records = imported
   8769             .iter()
   8770             .filter(|record| record.projected_kind == "listing")
   8771             .collect::<Vec<_>>();
   8772         let product_count: i64 = app_store
   8773             .connection()
   8774             .query_row("SELECT COUNT(*) FROM products", [], |row| row.get(0))
   8775             .expect("product count");
   8776         let product: (String, String, String, Option<i64>, Option<i64>) = app_store
   8777             .connection()
   8778             .query_row(
   8779                 "SELECT id, farm_id, status, price_minor_units, stock_count FROM products",
   8780                 [],
   8781                 |row| {
   8782                     Ok((
   8783                         row.get(0)?,
   8784                         row.get(1)?,
   8785                         row.get(2)?,
   8786                         row.get(3)?,
   8787                         row.get(4)?,
   8788                     ))
   8789                 },
   8790             )
   8791             .expect("load product");
   8792 
   8793         assert_eq!(local_report.imported_records, 2);
   8794         assert_eq!(signed_report.scanned_records, 1);
   8795         assert_eq!(signed_report.imported_records, 1);
   8796         assert_eq!(listing_records.len(), 2);
   8797         assert_eq!(
   8798             listing_records[0].projected_id,
   8799             listing_records[1].projected_id
   8800         );
   8801         assert_eq!(product_count, 1);
   8802         assert_eq!(product.0, product_uuid.to_string());
   8803         assert_eq!(product.1, farm_uuid.to_string());
   8804         assert_eq!(product.2, "published");
   8805         assert_eq!(product.3, Some(800));
   8806         assert_eq!(product.4, Some(9));
   8807     }
   8808 }