fix(mesh): enforce LoRa-only off-grid labels

This commit is contained in:
archipelago 2026-06-30 06:22:45 -04:00
parent 2ac0711f8e
commit b4531bb4fc
4 changed files with 24 additions and 6 deletions

View File

@ -1116,7 +1116,14 @@ impl MeshService {
.map(|p| !p.reachable && p.arch_pubkey_hex.is_some())
.unwrap_or(false)
};
if is_federation_synthetic || exceeds_lora || radio_federated_unreachable {
let mesh_only_mode = load_config(&self.data_dir)
.await
.ok()
.and_then(|cfg| cfg.mesh_only_mode)
.unwrap_or(false);
if !mesh_only_mode
&& (is_federation_synthetic || exceeds_lora || radio_federated_unreachable)
{
// Resolve the peer's pubkey/did. Prefer the live mesh peer table,
// but fall back to federation storage for federation-synthetic ids
// that were never seeded into `state.peers` — e.g. a radio-less
@ -1185,6 +1192,17 @@ impl MeshService {
// (`send_dm_via_channel` in listener/session.rs) handles both
// single-frame and chunked transmission internally; we must NOT
// pre-chunk here as well or the receiver sees garbage.
} else if mesh_only_mode
&& (is_federation_synthetic || exceeds_lora || radio_federated_unreachable)
{
tracing::info!(
contact_id,
bytes = wire.len(),
is_federation_synthetic,
exceeds_lora,
radio_federated_unreachable,
"Off-grid mode active; forcing mesh message over LoRa only"
);
}
self.send_raw_payload(contact_id, wire).await?;
Ok(self

View File

@ -3,7 +3,7 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { rpcClient } from '@/api/rpc-client'
export type TransportKind = 'mesh' | 'lan' | 'tor'
export type TransportKind = 'mesh' | 'lan' | 'fips' | 'tor'
export interface TransportInfo {
kind: TransportKind

View File

@ -1477,7 +1477,7 @@ function isImageMime(mime?: string): boolean {
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 5.636a9 9 0 11-12.728 0M12 9v4m0 4h.01" />
</svg>
<span class="text-sm font-medium text-orange-300">OFF-GRID</span>
<span class="text-xs text-white/50">Tor disabled mesh only</span>
<span class="text-xs text-white/50">Tor/FIPS disabled - LoRa only</span>
</div>
<!-- Actions row -->

View File

@ -119,10 +119,10 @@
.mesh-signal-bar.active { background: #4ade80; }
.mesh-unread-badge { background: #fb923c; color: #000; font-size: 0.65rem; font-weight: 700; min-width: 18px; height: 18px; border-radius: 9px; display: flex; align-items: center; justify-content: center; padding: 0 5px; flex-shrink: 0; }
.mesh-chat-card { padding: 0; flex: 1; display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.mesh-chat-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: rgba(255, 255, 255, 0.3); gap: 8px; padding: 40px; }
.mesh-chat-empty-icon { font-size: 3rem; opacity: 0.4; }
.mesh-chat-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: rgba(255, 255, 255, 0.14); gap: 8px; padding: 40px; }
.mesh-chat-empty-icon { font-size: 3rem; opacity: 0.18; }
.mesh-chat-empty p { margin: 0; font-size: 0.9rem; }
.mesh-chat-empty-sub { font-size: 0.75rem !important; color: rgba(255, 255, 255, 0.2); }
.mesh-chat-empty-sub { font-size: 0.75rem !important; color: rgba(255, 255, 255, 0.1); }
.mesh-chat-header { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid rgba(255, 255, 255, 0.06); flex-shrink: 0; }
/* Floating mobile back button (Teleported to body). Hidden by default; only
shown in the single-column mobile mesh layout (see media query below). */