Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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