diff --git a/core/archipelago/src/api/rpc/content.rs b/core/archipelago/src/api/rpc/content.rs index 5c314927..315bff7f 100644 --- a/core/archipelago/src/api/rpc/content.rs +++ b/core/archipelago/src/api/rpc/content.rs @@ -326,11 +326,20 @@ impl RpcHandler { )); } - let body: serde_json::Value = response + let mut body: serde_json::Value = response .json() .await .context("Failed to parse peer catalog")?; + // Surface the transport that actually reached the peer so the cloud + // browse UI can show a FIPS/Tor pill instead of always assuming Tor (B21). + if let Some(obj) = body.as_object_mut() { + obj.insert( + "transport".to_string(), + serde_json::Value::String(transport.to_string()), + ); + } + Ok(body) } diff --git a/neode-ui/src/views/PeerFiles.vue b/neode-ui/src/views/PeerFiles.vue index 1369a862..3dfdcb4a 100644 --- a/neode-ui/src/views/PeerFiles.vue +++ b/neode-ui/src/views/PeerFiles.vue @@ -30,7 +30,15 @@ @@ -43,7 +51,7 @@ -

Connecting via Tor... This may take a few seconds.

+

Connecting to peer… This may take a few seconds.

@@ -288,6 +296,23 @@ const catalogItems = ref([]) const downloading = ref(null) const playing = ref(null) const purchaseError = ref(null) +// Transport actually used to reach this peer (returned by content.browse-peer) +// so we can show a FIPS/Tor pill instead of always assuming Tor (B21). +const transport = ref(null) +const transportPill = computed(() => { + switch (transport.value) { + case 'fips': + return { label: 'FIPS', cls: 'bg-green-500/20 text-green-300', title: 'Connected over the fast encrypted mesh (FIPS)' } + case 'mesh': + return { label: 'Mesh', cls: 'bg-green-500/20 text-green-300', title: 'Connected over the mesh' } + case 'lan': + return { label: 'LAN', cls: 'bg-blue-500/20 text-blue-300', title: 'Connected over the local network' } + case 'tor': + return { label: 'Tor', cls: 'bg-amber-500/20 text-amber-300', title: 'Connected over Tor (slower)' } + default: + return null + } +}) const previewUrls = reactive>({}) const audioPlayer = useAudioPlayer() @@ -329,12 +354,13 @@ async function loadCatalog() { loading.value = true catalogError.value = '' try { - const result = await rpcClient.call<{ items?: CatalogItem[] }>({ + const result = await rpcClient.call<{ items?: CatalogItem[]; transport?: string }>({ method: 'content.browse-peer', params: { onion }, timeout: 30000, }) catalogItems.value = result?.items ?? [] + transport.value = result?.transport ?? null } catch (e: unknown) { catalogError.value = e instanceof Error ? e.message : 'Failed to connect to peer' if (!hadItems) catalogItems.value = [] diff --git a/tests/production-quality/TRACKER.md b/tests/production-quality/TRACKER.md index 60ccf199..ac4b6445 100644 --- a/tests/production-quality/TRACKER.md +++ b/tests/production-quality/TRACKER.md @@ -108,7 +108,7 @@ We previously broadcast bitcoin block headers over mesh to archipelago nodes but ### B14b — FIPS reachability: many peers fall back to Tor — TODO (priority, deeper) Live (2026-06-15) federation sync last_transport on .116/.198: ~4 peers fips, ~6 tor, ~5 none. So beyond the recording fix (B14), FIPS genuinely doesn't reach many federated peers (they use Tor). Investigate WHY: is fips_npub known for those peers? are they FIPS-online? is the shared anchor connecting them? (cf project_fips_integration, project_tor_node_to_node_works). This is the real "Tor not FIPS" depth. -### B21 — Show Tor/FIPS transport pill on cloud browse — ROOT-CAUSED (pairs with B14) +### B21 — Show Tor/FIPS transport pill on cloud browse — FIXED (build+type-check green; deploy+UI-confirm on .116/.198) Tag whether the peer connection is Tor or FIPS and surface it as a small pill on the cloud browse screens / connection loader. Data source: federation node last_transport (now recorded by B14) exposed via federation.list-nodes; frontend renders a pill (FIPS=fast/green, Tor=slower) on PeerFiles.vue / Cloud peer view + the connection loader. Frontend-only-ish. FINDINGS: PeerFiles.vue:46 loader HARDCODES 'Connecting via Tor...' even when FIPS used (bug). Frontend types already have last_transport ('fips'|'tor'|'mesh'|'lan') federation/types.ts:31; NodeList.vue:167 already renders a transport indicator. PLAN: have content.browse-peer RETURN the transport used (B14 already computes it) → frontend shows a pill (FIPS green / Tor amber) on PeerFiles header + fix the loader text to reflect actual/attempted transport. Small backend (add transport to browse response) + frontend pill. ### B8 — netbird app doesn't work — TODO (LOW / much later)