commit b85da271483bc07f48274a8b992279220bde7203
parent 28ba80f395ec6ffa1c5a9ea2eef2c1e91ac29764
Author: triesap <tyson@radroots.org>
Date: Fri, 27 Mar 2026 12:53:43 +0000
persistence: reject workflow-only sqlite destinations
Diffstat:
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/persistence.rs b/src/persistence.rs
@@ -367,6 +367,7 @@ fn signer_store_state_is_empty(
state.signer_identity.is_none()
&& state.connections.is_empty()
&& state.audit_records.is_empty()
+ && state.publish_workflows.is_empty()
}
fn require_existing_restore_file(path: &std::path::Path, label: String) -> Result<(), MycError> {
@@ -641,11 +642,14 @@ mod tests {
use nostr::PublicKey;
use radroots_identity::RadrootsIdentity;
use radroots_nostr_signer::prelude::{
- RadrootsNostrFileSignerStore, RadrootsNostrSignerConnectionDraft, RadrootsNostrSignerStore,
- RadrootsNostrSqliteSignerStore,
+ RADROOTS_NOSTR_SIGNER_STORE_VERSION, RadrootsNostrFileSignerStore,
+ RadrootsNostrSignerConnectionDraft, RadrootsNostrSignerConnectionId,
+ RadrootsNostrSignerStore, RadrootsNostrSignerStoreState, RadrootsNostrSqliteSignerStore,
};
- use super::{MycPersistenceImportSelection, import_json_to_sqlite};
+ use super::{
+ MycPersistenceImportSelection, import_json_to_sqlite, signer_store_state_is_empty,
+ };
use crate::app::MycRuntime;
use crate::audit::{MycOperationAuditKind, MycOperationAuditOutcome, MycOperationAuditRecord};
use crate::audit_sqlite::MycSqliteOperationAuditStore;
@@ -681,6 +685,27 @@ mod tests {
}
#[test]
+ fn signer_store_state_is_not_empty_when_only_publish_workflows_are_present() {
+ let workflow = radroots_nostr_signer::prelude::RadrootsNostrSignerPublishWorkflowRecord::new_connect_secret_finalization(
+ RadrootsNostrSignerConnectionId::parse("workflow-only-connection")
+ .expect("workflow connection id"),
+ 17,
+ );
+ let state = RadrootsNostrSignerStoreState {
+ version: RADROOTS_NOSTR_SIGNER_STORE_VERSION,
+ signer_identity: None,
+ connections: Vec::new(),
+ audit_records: Vec::new(),
+ publish_workflows: vec![workflow],
+ };
+
+ assert!(
+ !signer_store_state_is_empty(&state),
+ "publish workflows must make the signer-state destination non-empty"
+ );
+ }
+
+ #[test]
fn import_json_to_sqlite_moves_signer_state_and_runtime_audit() {
let temp = tempfile::tempdir().expect("tempdir");
let runtime = bootstrap_json_runtime(temp.path());