feat(TASK-12): beta telemetry — report endpoint + settings toggle

Backend: telemetry.report RPC builds anonymous health report with node ID
(SHA-256 hash of pubkey, truncated), version, uptime, container states,
CPU/RAM, federation peers, and recent alerts. Saves latest report to disk.
Requires analytics opt-in (existing analytics.enable/disable flow).

Frontend: "Beta Telemetry" section in Settings with enable/disable toggle.
Shows what data is and isn't collected. Mock backend handles all analytics
and telemetry RPCs.

Privacy: No wallet data, no private keys, no DIDs, no IP addresses.
Node identified by truncated hash only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-18 23:14:47 +00:00
parent b7edada7fe
commit 165972e75c
4 changed files with 230 additions and 38 deletions

View File

@@ -844,6 +844,28 @@
</div>
</div>
<!-- Beta Telemetry Section -->
<div class="glass-card px-6 py-6 mb-6">
<div class="flex items-center justify-between mb-3">
<div>
<h2 class="text-xl font-semibold text-white/96 mb-1">Beta Telemetry</h2>
<p class="text-sm text-white/60">Help improve Archipelago by sharing anonymous system health data. No wallet data, no keys, no personal info.</p>
</div>
<button
@click="toggleTelemetry"
:disabled="telemetryLoading"
class="shrink-0 ml-4 px-4 py-2 rounded-lg text-sm font-medium transition-colors"
:class="telemetryEnabled ? 'bg-green-500/20 text-green-300 border border-green-500/30 hover:bg-green-500/30' : 'glass-button'"
>
{{ telemetryLoading ? '...' : telemetryEnabled ? 'Enabled' : 'Enable' }}
</button>
</div>
<div v-if="telemetryEnabled" class="mt-3 text-xs text-white/50 space-y-1">
<p>Reporting: version, uptime, container states, CPU/RAM, error alerts.</p>
<p>Not reporting: wallet balances, private keys, DIDs, IP addresses.</p>
</div>
</div>
<!-- Backup & Restore Section -->
<div class="glass-card px-6 py-6 mb-6">
<div class="mb-4">
@@ -1091,6 +1113,26 @@ async function saveServerName() {
const version = computed(() => store.serverInfo?.version || '0.0.0')
const showReleaseNotes = ref(false)
// Telemetry
const telemetryEnabled = ref(false)
const telemetryLoading = ref(false)
async function loadTelemetryStatus() {
try {
const res = await rpcClient.call<{ enabled: boolean }>({ method: 'analytics.get-status' })
telemetryEnabled.value = res.enabled
} catch { /* ignore */ }
}
async function toggleTelemetry() {
telemetryLoading.value = true
try {
const method = telemetryEnabled.value ? 'analytics.disable' : 'analytics.enable'
await rpcClient.call({ method })
telemetryEnabled.value = !telemetryEnabled.value
} catch { /* ignore */ }
telemetryLoading.value = false
}
loadTelemetryStatus()
const serverTorAddressFromStore = computed(() => store.serverInfo?.['tor-address'] || null)
const torAddressFromRpc = ref<string | null>(null)
const serverTorAddress = computed(() => serverTorAddressFromStore.value || torAddressFromRpc.value)