diff options
| author | Your Name <you@example.com> | 2026-05-26 22:07:55 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-26 22:07:55 +0530 |
| commit | d60fa03de6edae0667a93ac36be4206e76255a2c (patch) | |
| tree | 566adbe43f446a1f92a425c439c8c60f52c8ae51 /src/main.rs | |
| parent | 7b1b36b8c7e448d1d170c8c6e1f88bb766163fbb (diff) | |
Add NIP-46 remote signing for kind:30618 state events
- nip46.rs: full NIP-46 client with session management, NIP-04 encrypted
relay-based communication, oneshot response awaiting
- db.rs: nip46_sessions table, upsert/get methods
- config.rs: Nip46Config with relays + signing_timeout_secs
- git_mirror.rs: builds unsigned kind:30618 state event from bare repo refs,
signs via NIP-46 before push, publishes to target server relay
- http_health.rs: exposes NIP-46 session status in health endpoint
- main.rs: wires NIP-46 client into daemon startup, passes to mirror_cycle
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index 3fcd27b..8e1383e 100644 --- a/src/main.rs +++ b/src/main.rs | |||
| @@ -4,6 +4,7 @@ mod discovery; | |||
| 4 | mod git_mirror; | 4 | mod git_mirror; |
| 5 | mod health; | 5 | mod health; |
| 6 | mod http_health; | 6 | mod http_health; |
| 7 | mod nip46; | ||
| 7 | mod nostr_mirror; | 8 | mod nostr_mirror; |
| 8 | mod signing; | 9 | mod signing; |
| 9 | 10 | ||
| @@ -71,14 +72,50 @@ async fn run_daemon(config: config::ResolvedConfig, db: db::MirrorDb) -> Result< | |||
| 71 | let db = Arc::new(db); | 72 | let db = Arc::new(db); |
| 72 | let config = Arc::new(config); | 73 | let config = Arc::new(config); |
| 73 | 74 | ||
| 75 | let nip46_client = if let Some(ref nip46_cfg) = config.nip46 { | ||
| 76 | let client = nip46::Nip46Client::new( | ||
| 77 | nip46_cfg.relays.clone(), | ||
| 78 | nip46_cfg.signing_timeout_secs, | ||
| 79 | db.clone(), | ||
| 80 | ) | ||
| 81 | .await?; | ||
| 82 | |||
| 83 | client.init_sessions(&config.npubs).await?; | ||
| 84 | client.start_listener().await; | ||
| 85 | |||
| 86 | for status in client.get_status().await { | ||
| 87 | tracing::info!( | ||
| 88 | npub = %status.npub, | ||
| 89 | connected = status.connected, | ||
| 90 | "NIP-46 session status" | ||
| 91 | ); | ||
| 92 | if !status.connected { | ||
| 93 | if let Some(uri) = &status.pairing_uri { | ||
| 94 | tracing::info!( | ||
| 95 | npub = %status.npub, | ||
| 96 | uri = %uri, | ||
| 97 | "Pair this npub by opening the nostrconnect URI in Amber" | ||
| 98 | ); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | Some(Arc::new(client)) | ||
| 104 | } else { | ||
| 105 | tracing::warn!("no [nip46] config — remote signing disabled"); | ||
| 106 | None | ||
| 107 | }; | ||
| 108 | |||
| 74 | let (cycle_count_tx, cycle_count_rx) = tokio::sync::watch::channel(0u64); | 109 | let (cycle_count_tx, cycle_count_rx) = tokio::sync::watch::channel(0u64); |
| 75 | let (last_cycle_ok_tx, last_cycle_ok_rx) = tokio::sync::watch::channel(true); | 110 | let (last_cycle_ok_tx, last_cycle_ok_rx) = tokio::sync::watch::channel(true); |
| 76 | 111 | ||
| 112 | let nip46_status = nip46_client.clone(); | ||
| 77 | let health_state = Arc::new(http_health::HealthState { | 113 | let health_state = Arc::new(http_health::HealthState { |
| 78 | started_at: std::time::Instant::now(), | 114 | started_at: std::time::Instant::now(), |
| 79 | cycle_count: cycle_count_rx, | 115 | cycle_count: cycle_count_rx, |
| 80 | last_cycle_ok: last_cycle_ok_rx, | 116 | last_cycle_ok: last_cycle_ok_rx, |
| 81 | db_path: config.storage.database.display().to_string(), | 117 | db_path: config.storage.database.display().to_string(), |
| 118 | nip46_client: nip46_status, | ||
| 82 | }); | 119 | }); |
| 83 | 120 | ||
| 84 | let health_port = config.storage.health_port; | 121 | let health_port = config.storage.health_port; |
| @@ -111,6 +148,8 @@ async fn run_daemon(config: config::ResolvedConfig, db: db::MirrorDb) -> Result< | |||
| 111 | let mirror = git_mirror::GitMirror::new(&config.storage.mirror_dir); | 148 | let mirror = git_mirror::GitMirror::new(&config.storage.mirror_dir); |
| 112 | let nostr_mirror = nostr_mirror::NostrMirror::new(nostr_client.clone()); | 149 | let nostr_mirror = nostr_mirror::NostrMirror::new(nostr_client.clone()); |
| 113 | 150 | ||
| 151 | let nip46_client_ref: Option<Arc<nip46::Nip46Client>> = nip46_client.clone(); | ||
| 152 | |||
| 114 | let mut interval = tokio::time::interval(std::time::Duration::from_secs( | 153 | let mut interval = tokio::time::interval(std::time::Duration::from_secs( |
| 115 | config.discovery.poll_interval_secs, | 154 | config.discovery.poll_interval_secs, |
| 116 | )); | 155 | )); |
| @@ -132,6 +171,7 @@ async fn run_daemon(config: config::ResolvedConfig, db: db::MirrorDb) -> Result< | |||
| 132 | &mirror, | 171 | &mirror, |
| 133 | &nostr_mirror, | 172 | &nostr_mirror, |
| 134 | &healthy, | 173 | &healthy, |
| 174 | nip46_client_ref.as_ref(), | ||
| 135 | ).await; | 175 | ).await; |
| 136 | 176 | ||
| 137 | match &result { | 177 | match &result { |
| @@ -160,6 +200,7 @@ async fn mirror_cycle( | |||
| 160 | mirror: &git_mirror::GitMirror, | 200 | mirror: &git_mirror::GitMirror, |
| 161 | nostr_mirror: &nostr_mirror::NostrMirror, | 201 | nostr_mirror: &nostr_mirror::NostrMirror, |
| 162 | servers: &Arc<Vec<health::GraspServer>>, | 202 | servers: &Arc<Vec<health::GraspServer>>, |
| 203 | nip46_client: Option<&Arc<nip46::Nip46Client>>, | ||
| 163 | ) -> Result<()> { | 204 | ) -> Result<()> { |
| 164 | tracing::info!("starting mirror cycle"); | 205 | tracing::info!("starting mirror cycle"); |
| 165 | 206 | ||
| @@ -190,7 +231,7 @@ async fn mirror_cycle( | |||
| 190 | "mirroring to missing servers" | 231 | "mirroring to missing servers" |
| 191 | ); | 232 | ); |
| 192 | 233 | ||
| 193 | if let Err(e) = mirror.mirror_repo_to_servers(db, repo, &missing).await { | 234 | if let Err(e) = mirror.mirror_repo_to_servers(db, repo, &missing, nip46_client).await { |
| 194 | tracing::error!(identifier = %repo.identifier, error = %e, "git mirror failed for repo, continuing"); | 235 | tracing::error!(identifier = %repo.identifier, error = %e, "git mirror failed for repo, continuing"); |
| 195 | } | 236 | } |
| 196 | 237 | ||
| @@ -310,6 +351,7 @@ async fn run_mirror_once(config: config::ResolvedConfig, db: db::MirrorDb) -> Re | |||
| 310 | &mirror, | 351 | &mirror, |
| 311 | &nostr_mirror, | 352 | &nostr_mirror, |
| 312 | &healthy, | 353 | &healthy, |
| 354 | None, | ||
| 313 | ) | 355 | ) |
| 314 | .await | 356 | .await |
| 315 | } | 357 | } |