Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@ reticulum-sidecar/
*.gif
*.svg
*.webp

# Fonts (binary; no Prettier parser)
*.woff
*.woff2
*.ttf
*.otf
*.eot
6 changes: 6 additions & 0 deletions docs/credits.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ We were inspired by features from these projects:
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `mesh-client-reticulum` | AGPL-3.0 | Spawned Reticulum/LXMF sidecar (separate process; see [docs/reticulum.md](reticulum.md)) |

### Bundled fonts

| Font / file | License | Role |
| ------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------- |
| `MeshClientNomadMono.woff2` (JetBrains Mono Nerd Font Mono, subset) | OFL-1.1 | Nomad Micron viewer monospace + Nerd/FA PUA icons ([OFL](../src/renderer/assets/fonts/OFL-JetBrainsMonoNerdFont.txt)) |

Exact semver ranges live in [`package.json`](https://github.com/Colorado-Mesh/mesh-client/blob/main/package.json) at the repository root; the tables below mirror them for attribution.

### Runtime dependencies
Expand Down
2 changes: 1 addition & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,7 @@ In dev, **Start stack** now rebuilds when `reticulum-sidecar/src/**/*.rs` or `Ca

Unrecognized codes pass through unchanged.

TCP/network Nomad Links use path-scaled proof budgets (`link_hops = clamp(path_hops, 3, 7)` → ~18–42s), matching released v5.25.0 multi-hop behavior more closely than #756’s flat ~18s cap (a HEAD regression for slower hub peers). First attempts use a cached path when present (no DropPath storm); missing paths RequestPath briefly and may return `path_timeout`. Retries may DropPath + rediscover; `force_path_ok=true` means rediscovered after absence only (cache hits log `force_path_ok=false`). Failure logs (`[nomadNetworkStore] … fetch failed` and sidecar `Nomad Link query failed`) include `path_hops`, `link_hops`, `proof_budget_secs`, `force_path_ok`, `path_ensure`, `elapsed_ms`, and `raw=`. UI errors distinguish cached-path vs rediscovered-path link failures.
TCP/network Nomad Links use path-scaled initiator hops (`link_hops = clamp(path_hops, 3, 7)`) and a LinkClient proof wait of the **remaining overall MeshChat deadline** (~45s TCP after instant pubkey recall), matching v5.25.0. Do not cap LRPROOF at hops×6 or a 30s floor — that false-failed multi-hop hub pages that still load on release. First attempts use a cached path when present (no DropPath storm); missing paths RequestPath briefly and may return `path_timeout`. Retries may DropPath + rediscover; `force_path_ok=true` means rediscovered after absence only (cache hits log `force_path_ok=false`). Failure logs (`[nomadNetworkStore] … fetch failed` and sidecar `Nomad Link query failed`) include `path_hops`, `link_hops`, `proof_budget_secs`, `force_path_ok`, `path_ensure_kind`, `elapsed_ms`, and `raw=`. UI errors distinguish cached-path vs rediscovered-path link failures.

**Cause**: Older `LinkClient` always waited for a fresh path-response announce for the destination public key, even when Nomad announces had already cached it. Successful fetches could also deregister all `nomadnetwork.node` announce handlers. Distant/high-hop nodes can still time out at the path stage (expected RF/mesh reachability limits).

Expand Down
2 changes: 1 addition & 1 deletion reticulum-sidecar/patches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ When [ratspeak/rsReticulum#14](https://github.com/ratspeak/rsReticulum/pull/14)

## rsReticulum-link-client-proof-budget.patch

Cap `LinkClient::query` proof wait at `link.establishment_timeout` so a cached path cannot burn the entire overall Nomad deadline (MeshChat TCP link stage ~15s). Apply **after** the LinkClient Nomad overlay.
Keep `LinkClient::query` proof wait on the **remaining overall deadline** (v5.25.0 / release parity). Earlier overlays capped at `establishment_timeout` (hops×6) or `max(establishment, 30s)` and false-failed multi-hop TCP hub Nomad pages (e.g. Northern Ireland) that need the rest of the MeshChat 45s window. Apply **after** the LinkClient Nomad overlay; the apply script migrates those older caps to remaining-deadline.

| Field | Value |
| ----- | ----- |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ diff --git a/crates/rns-runtime/src/link_client.rs b/crates/rns-runtime/src/link
.await?;

- let proof_data = wait_for_proof(&mut dest_rx, link_id, time_remaining(deadline)?).await?;
+ // Cap proof wait at link establishment timeout (6s × hops). Otherwise a
+ // cached path lets wait_for_proof burn the entire overall deadline
+ // (e.g. TCP 45s) even when MeshChat would fail the link stage in ~15s.
+ let proof_budget = time_remaining(deadline)?.min(link.establishment_timeout);
+ // Release / v5.25.0 parity: use remaining overall deadline for LRPROOF.
+ // Do not cap at establishment (hops×6) or a 30s floor — that false-failed
+ // multi-hop TCP hub Nomad pages that need the rest of the MeshChat 45s window.
+ let proof_budget = time_remaining(deadline)?;
+ let proof_data = wait_for_proof(&mut dest_rx, link_id, proof_budget).await?;

let identity_ed25519_pub: [u8; 32] = pubkey[32..64].try_into().map_err(|_| {
Expand Down
12 changes: 12 additions & 0 deletions reticulum-sidecar/src/api/nomad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub struct NomadPageQuery {
/// When true, RequestPath even if a cached path exists (stale-route retry).
#[serde(default)]
pub force_path_refresh: bool,
/// Client correlation id echoed on `nomad.page_progress` WS events.
pub request_id: Option<String>,
}

pub async fn get_nomad_page(
Expand All @@ -51,6 +53,7 @@ pub async fn get_nomad_page(
&query.path,
query.data.as_deref(),
query.force_path_refresh,
query.request_id.as_deref(),
)
.await,
)
Expand Down Expand Up @@ -218,6 +221,7 @@ mod force_path_refresh_query_tests {
let q: NomadPageQuery =
serde_urlencoded::from_str("path=%2Fpage%2Findex.mu").expect("query");
assert!(!q.force_path_refresh);
assert!(q.request_id.is_none());
assert_eq!(q.path, "/page/index.mu");
}

Expand All @@ -229,6 +233,14 @@ mod force_path_refresh_query_tests {
assert!(q.force_path_refresh);
}

#[test]
fn nomad_page_query_parses_request_id() {
let q: NomadPageQuery =
serde_urlencoded::from_str("path=%2Fpage%2Findex.mu&request_id=load-42")
.expect("query");
assert_eq!(q.request_id.as_deref(), Some("load-42"));
}

#[test]
fn nomad_file_query_parses_force_path_refresh_true() {
let q: NomadFileQuery =
Expand Down
Loading