feat: P2P relay + Nostr + Endpoints settings (all 6 phases)#4
Open
CyberAshven wants to merge 25 commits into
Open
feat: P2P relay + Nostr + Endpoints settings (all 6 phases)#4CyberAshven wants to merge 25 commits into
CyberAshven wants to merge 25 commits into
Conversation
- gui_bridge.py: read `models_path` from qubes-config.json to let users store models on any drive/path (e.g. D:\MyModels). Priority order: QUBES_MODELS_DIR env var > qubes-config.json models_path > auto-detect. Sets QUBES_MODELS_DIR so all subsystems see the same base path. - audio/audio_manager.py: _load_config_from_env now resolves all model paths (piper, whisper, qwen3-tts) relative to QUBES_MODELS_DIR instead of the hardcoded ~/.qubes/models default. - audio/audio_manager.py: _get_qwen3_provider now auto-triggers Qwen3ModelDownloader.start_download() when the selected variant is not yet on disk, so the model downloads automatically in the background instead of silently failing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…S models - Add pull_ollama_model Rust command: streams NDJSON progress from Ollama API, emits ollama-pull-progress Tauri events to frontend - Add check_local_tts_models Rust command: delegates to Python sidecar - Add update_local_tts_models Rust command: delegates to Python sidecar - Add check-local-tts-models Python handler: checks HF_HOME for Kokoro, sentence-transformers, and Whisper model directories - Add update-local-tts-models Python handler: re-pulls models from HuggingFace using snapshot_download with QUBES_MODELS_DIR awareness - Add 📦 Local Models collapsible section in SettingsTab after GPU Acceleration: - Lists installed Ollama models with per-model Update button - Update All Ollama Models button with live progress bar - Shows Kokoro TTS, Sentence Transformers, Whisper install status - Re-download Voice Models button Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merge custom QUBES_MODELS_DIR support (our branch) with master's auto-download improvements. Combined result: - Priority: custom _custom_models_dir config > frozen auto-detect - Always mkdir HF_HOME so models auto-download on first use - Sets QUBES_MODELS_DIR in both paths Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Balance UI: - Remove TotalBalanceWidget from header title bar - Add Total Balance widget in QubeManagerTab toolbar (next to + New Qube): - Shows total BCH across all qubes (gray when 0, accent when has balance) - Refresh button (↻) refreshes all qube balances - Sweep All button (↓ Sweep) — disabled/gray at 0, active when balance > 0 - Inline sweep-all input: enter destination address, confirm, sweeps all qubes with balance Card Flip Sweep: - Add ↓ Sweep Funds button on blockchain flip side per qube - Gray + disabled when balance = 0 - Active (accent color) when balance > 0 - Inline input: enter bitcoincash:q... address, confirm, sweeps that qube only - Shows ✓/✗ result, updates cached balance to 0 on success Backend: - Add sweep-qube-wallet Python command (calls orchestrator._sweep_before_delete) - Add sweep_qube_wallet Rust invoke command TTS Fix: - Re-applied to local D:\Qubes binary (torch/nn/__init__.py pre-imports functional+init before modules) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ilds - Loosen Tauri crate version constraints to "2" so cargo resolves latest compatible versions (fixes version mismatch with npm packages) - Add pnpm-lock.yaml for reproducible frontend dependency installs - Add .npmrc with allow-build=esbuild for Vite/Rollup native bindings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eration The PyInstaller bundle strips torch.distributed, torch.futures, torch.rpc and their submodules. TTS (Kokoro) and GPU acceleration code paths import these at runtime, causing startup failures: - No module named 'torch.distributed' - cannot import name 'Future' from 'torch.futures' - cannot import name 'nn' from partially initialized module 'torch' Fixes: - torch/distributed/__init__.py: import hook that auto-stubs any torch.distributed.* submodule import; pre-builds Join/Joinable/JoinHook as real classes so nn.parallel.distributed can subclass them - torch/futures/__init__.py: minimal Future class with full interface - torch/rpc/__init__.py: stub - torch/nn/__init__.py: pre-import functional+init before modules to break circular import chain Apply patches/ files to D:\Qubes\qubes-backend\_internal\torch\ after any Qubes update that overwrites the bundle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…layout - sidecar_server.py: add _handle_check_local_tts_models and _handle_update_local_tts_models handlers + POSITIONAL_ARG_NAMES entries. Fixes "Unknown command: update-local-tts-models (no method on GUIBridge)" error — commands now route through sidecar server instead of stale main() elif chain. - SettingsTab.tsx: add Download New Model input (model:tag + Download button) below Ollama model list. Reuses existing handlePullModel / pullProgress state. - QubeManagerTab.tsx: move Total Balance widget after "+ New Qube" button; restructure widget with label+refresh row, balance row, full-width Sweep All button. - Bump version 0.9.0 → 0.9.1 across package.json, tauri.conf.json, Cargo.toml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migration period ended — wallet authentication is now required for: - Backup (export_account_backup): added wallet_sig param to Rust command and UI; backup button disabled until wallet signed - Restore local file: Restore button disabled until wallet signed - Restore from IPFS: Restore button disabled until wallet signed - LoginScreen: both restore flows require wallet sig before proceeding Login, auto-anchor, and session operations remain password-only (unchanged). Labels updated: "Optional: Wallet 2FA" → "Required: Wallet 2FA" everywhere. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Every sync was uploading a new file without deleting old ones, causing duplicate accumulation (e.g. JARVIS backed up 15+ times). Added _pinata_unpin_old() helper that queries Pinata pinList for the filename, then DELETEs all old CIDs except the newly uploaded one. Called after both per-Qube (sync_qube_to_ipfs_backup) and account-level (export_account_backup_ipfs) uploads. Each Qube/account now keeps exactly one backup in Pinata. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-bound Added peek_backup_manifest command (Rust + sidecar pre-bridge handler) that reads manifest.json from a .qube-backup ZIP without decrypting anything, returning wallet_bound flag. Frontend now: - Peeks manifest when file is selected in restore modal (QubeManagerTab + LoginScreen) - Shows "Required: Wallet 2FA" if wallet_bound=True, "Wallet 2FA" otherwise - Blocks Restore button only if wallet_bound=True and no sig provided - Auto-anchor backups (wallet_bound=False) remain fully restorable without wallet - Manual backups (wallet_bound=True) still require wallet sig Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove wallet sig requirement from backup (export) flow - Always require wallet sig at restore (local + IPFS) — no conditional - Remove peek_backup_manifest command and pre-bridge handler - Remove wallet_bound conditional logic from QubeManagerTab + LoginScreen - Remove backupWalletSig/backupWcAddress/isSigningBackupWc/restoreWalletBound states Security model: file + password alone cannot restore — wallet ownership required at restore time. Backup creation needs no wallet sig. Auto-anchor unaffected (creates backups, never restores). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LoginScreen: fix text "Required for all restores" (not backups) - LoginScreen: add Copy URL button below QR code - QubeManagerTab restore: inline connect flow (no longer says "connect wallet first") - QubeManagerTab restore: shows QR code + Copy URL while waiting for scan - Works for both wallet-connected and wallet-disconnected users Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… new owner) After a Qube is received via wallet transfer and imported, automatically trigger IPFS backup so it gets anchored to the recipient's own Pinata account. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Import from wallet now shows 3 clear steps with animated progress bar: 1. Downloading & decrypting from IPFS (per-Qube progress) 2. Uploading to recipient's own Pinata backup (inline, not background) 3. Done — modal auto-closes after 1.2s IPFS upload is awaited (not silent) so user sees full progress. Modal stays open until everything is safely backed up. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After decrypting each Qube from a backup, verify the restoring wallet currently owns that Qube's NFT on-chain before writing any files. Closes the "old backup" loophole: if Van's NFT was transferred away, an old backup file still containing Van's data will now skip it (skipped_count++) instead of silently restoring it. - gui_bridge.py: import_account_backup + import_account_backup_ipfs accept wallet_address; build NFTVerifier once before loop; skip any Qube whose category_id the wallet no longer holds; unminted Qubes (no nft_metadata) are restored unconditionally - lib.rs: import_account_backup + import_account_backup_ipfs accept wallet_address: Option<String> and forward it via secrets dict - QubeManagerTab.tsx: passes restoreWcAddress to both restore invokes - LoginScreen.tsx: passes wcAddress to both restore invokes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- IPFS restore modal now has 3 tabs: Pinata Account | Direct CID | Scan Wallet
- Scan Wallet: connects WalletConnect, calls scan_wallet with wallet address,
lists found Qubes (with already_imported flag), imports each via
import_from_wallet with master password + 3-step progress bar
- Both QubeManagerTab (logged-in restore) and LoginScreen (account recovery)
- Renamed "Restore from File" → "Restore from Local File" throughout LoginScreen
- Copy URL button was already present in walletConnectBlock — rebuild exposes it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Connect Wallet button now uses GlassButton (same as restore modals inside app) - Copy URL button now shows '✓ Copied!' feedback for 2s after click - Adds wcCopied state to walletConnectBlock Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- gui_bridge.py: background anchor subprocess now checks auto_sync_ipfs_on_anchor preference and calls sync_qube_to_ipfs_backup after each successful anchor (pin new CID, unpin old — no Pinata bloat) - config/user_preferences.py: default both IPFS sync options to True, 15 min interval - SettingsTab.tsx: restructure into two clear sections (BCH Anchor + IPFS Backup) with timing shown on every row; threshold shows estimated message count; interval dropdown always visible (grayed when periodic disabled); 5 min option added Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 1 (fully implemented): - network/relay_list.py — built-in BitFaced seed relays (Electron Cash pattern) Pre-loaded with well-known BCH Fulcrum nodes and Nostr relays - network/relay_node.py — RelayNodeManager (wraps libp2p p2pd, store-forward) - network/store_forward.py — JSON-backed offline message queue (7-day retention) - network/bundle_manager.py — relay bundle path management (all in Qubes dir) - 11 new Rust commands in lib.rs (relay + endpoints) - 12 new Python commands in gui_bridge.py (relay + endpoints) - RelayPreferences + EndpointPreferences in config/user_preferences.py Phases 2-6 (scaffolded): - network/onion.py — 2-hop onion router stub (Phase 2) - network/cover_traffic.py — uniform-size cover traffic stub (Phase 2) - network/nostr_transport.py — NIP-44 + ephemeral keys stub (Phase 3, BitChat-style) - Phase 4 (mobile), Phase 5 (bundle update), Phase 6 (BLE/LoRa): TODOs in place Settings UI (SettingsTab.tsx): - 📡 Relay Node accordion — local relay start/stop with live green/red status dot (Gupaxx-style), p2pd binary path selector, remote relay status dots (seed + custom), relay bundle update button - 🔌 Endpoints accordion — green terminal-style UI matching reference screenshot: Fulcrum/Electrum nodes, Nostr relays (textareas, one URL per line), Cauldron indexer, Thorchain Midgard, Meta/Icon service, RESET/CANCEL/SAVE buttons, pre-loaded with well-known defaults SDK (@qubesai/sdk): - sdk/src/relay/ — createRelayNode, sendMessage, onMessage, types (Phase 1) - sdk/src/nostr/ — deriveSessionKeypair, nostrSend, nostrListen stubs (Phase 3) - sdk/package.json — ./relay and ./nostr export entries added (10 modules total) README: updated architecture diagram with relay stack, P2P Relay section, SDK module count 8 → 10, relay daemon dev commands relay/: standalone relay daemon for community operators (npm run relay:start / relay:dev / relay:test) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s, auto-load defaults - Merge Relay Node and Endpoints into one "Endpoints" accordion panel (same style as API Keys section — one GlassCard, one toggle) - Remove Thorchain Midgard, Cauldron Indexer, Meta/Icon Service (not relevant to P2P relay; can be added to a DeFi section later) - Pre-fill Fulcrum/Electrum and Nostr relay textareas with well-known defaults on initial render — user never sees empty fields - Load endpoint prefs on mount (useEffect) instead of only on panel open - Show seed relay names statically with "start relay to ping" hint instead of "Open the relay to see seed relay status" - Relay status dot appears in the Endpoints panel header Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… lib - check_endpoints(): uses installed websockets>=14.1 for real WSS handshake checks (not just TCP) — connects to ALL Fulcrum + Nostr endpoints in parallel - Add check_endpoints Tauri command + dispatch case - UI: X/Y counter next to each section header (green=all up, yellow=partial, red=none), per-line status dots appear after ping, "↻ ping all" button - Editing a textarea clears stale status so user re-pings after changes - Nostr defaults trimmed to 4 well-known relays (damus, nos.lol, nostr.band, snort.social) — user confirmed these are the good ones - Remove 4 extra Nostr defaults from user_preferences.py to match Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- bundle_manager.py now resolves relay bundle to {qubes_root}/relay/
matching the D:\Qubes\ollama\ pattern — one clear folder per component
- _qubes_root_dir() detects install root from PyInstaller executable path
- p2pd.exe lookup: relay/ → _internal/ → system PATH
- Created D:\Qubes\relay\ with README.txt explaining what to place there
- Settings → Endpoints → Update Bundle will manage this folder
To activate relay: drop p2pd.exe into D:\Qubes\relay\
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…date, mobile) Phase 2 — Privacy Layer: - network/onion.py: Real 3-layer ECIES onion routing (ephemeral ECDH + AES-256-GCM) Outer→R1, Middle→R2, Inner→dest. 512-byte uniform packet padding. - network/cover_traffic.py: 1Hz dummy packet emission to random online peers. Cover traffic failure never blocks real message delivery. - network/relay_node.py: Onion wrap before DHT publish when 2+ peer pubkeys known. Phase 3 — Nostr Integration: - network/nostr_transport.py: Full NIP-44 v2 implementation. Pure Python secp256k1 (no native deps). BIP-340 Schnorr signing. XChaCha20-Poly1305 encryption (ChaCha20 fallback). WebSocket send+listen. HKDF-derived ephemeral keypairs — mathematically unlinked from BCH identity. - relay_node.py: Nostr fallback when DHT publish throws. Start/stop lifecycle. Phase 5 — Bundle Update: - network/bundle_manager.py: check_for_update() fetches manifest via aiohttp. update_bundle(): download, SHA-256 verify, secp256k1 sig verify, atomic swap. Backup-and-restore on failure. Makes p2pd executable on non-Windows. Phase 6 — BLE Transport: - network/ble_transport.py: Cross-platform BLE driver via bleak. GATT service UUID, message fragmentation (512-byte chunks), async receive. - requirements.txt: Add bleak>=0.21.0 (graceful fallback if not installed). Phase 4 — Mobile Scaffolding: - mobile/android/relay_node_android.py: gomobile binding surface documentation. - mobile/ios/apns_bridge.py: APNS notification bridge scaffold. - mobile/README.md: Architecture and build instructions for mobile devs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Transport layer: - Add QUIC (/udp/quic) + WebSocket (/tcp/ws) listen addrs to p2pd daemon - Enable -natPortMap and -autoRelay flags for better NAT traversal - New network/lora_transport.py — LoRa long-range radio driver stub (Priority 4) - New network/wifi_direct_transport.py — WiFi-Direct P2P driver stub (Priority 3) - New network/i2p_transport.py — I2P anonymous overlay driver stub (Priority 5) BLE mesh (BitChat parity): - Add BLEServer class to ble_transport.py using bless library - BLEServer advertises Qubes relay GATT service so nearby devices can discover and connect without internet (central + peripheral roles) - Add bless>=0.2.5 to requirements.txt p2pd auto-download: - bundle_manager.ensure_p2pd_binary() downloads correct binary for Windows/macOS/Linux on first relay start if p2pd not present - relay_node.start() calls ensure_p2pd_binary() before spawning daemon Developer experience: - Add relay:start / relay:dev / relay:test npm scripts to package.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan