- system.factory-reset RPC: wipes user data, preserves images/node_key
- Factory Reset button in Settings with confirmation modal
- backup.restore-identity RPC: decrypts and restores DID key
- Restore from Backup panel in OnboardingIntro first screen
- Auto-create default identity with Nostr key on boot if none exist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Check user role against method permissions before dispatch.
All current users default to Admin, laying groundwork for multi-user.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace handle_lnd_lookupinvoice (doesn't exist) with stub.
Payment verification deferred to Y4-02 marketplace implementation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New RPC endpoints:
- analytics.get-status: Check if analytics opted in
- analytics.enable/disable: Toggle opt-in
- analytics.get-snapshot: Anonymous aggregate data (version, app count,
hardware tier, CPU cores, RAM, federation peers)
No personal data: no DIDs, no IPs, no secrets. Strictly opt-in.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New RPC endpoints:
- backup.upload-s3: Upload encrypted backup to any S3-compatible endpoint
- backup.download-s3: Download backup from S3 to local storage
Supports MinIO, Backblaze B2, Wasabi via basic auth + S3 API.
Backups are AES-256-GCM encrypted before upload.
Rate-limited at 3 requests per 10 minutes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Simplify DHT encoding: use JSON instead of DNS packets (drop simple-dns)
- Fix mainline crate API: SigningKey takes 32 bytes, get_mutable returns Result
- Add missing dht_did field to IdentityRecord constructor
- Store DID Document as JSON in DHT (DNS encoding deferred)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- federation.list-nodes now includes vc_verified: bool per node
- True when a non-revoked FederationTrustCredential exists for the peer DID
- Integrates with VC-02's automatic VC issuance on federation join
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Issue W3C VC (type FederationTrustCredential) when joining federation
- Claims: federationPeer=true, establishedAt=timestamp
- Signed with node Ed25519 identity key
- Runs in background task (non-blocking)
- Stored via credentials system for later verification
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add dht_did field to IdentityRecord (optional, serde-compatible)
- Add prefer_dht_did param to identity.issue-credential RPC
- When true and dht_did is set, uses did:dht as VC issuer
- Credential system already format-agnostic for any DID type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PERF-01: Move crash recovery to background tokio task so health
endpoint is available immediately on startup
- PERF-04: Add ResponseCache with 5s TTL for system.stats and
federation.list-nodes. Reduces CPU for frequent polling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make dwn.sync endpoint async: spawns background task, returns immediately
- Add 90s overall timeout to sync_with_peers via tokio::time::timeout
- Deduplicate peer onion addresses before syncing
- Batch message pushes (50 per request) instead of one-at-a-time over Tor
- Add 15s connect_timeout to Tor SOCKS5 client
- Cap local message query to 200 messages per sync
- Fix DWN HTTP handler to process ALL messages in batch (was only first)
- Add recordId deduplication in handler to prevent duplicate imports
- Update test script to poll dwn.status for sync completion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
read_onion_address() now checks tor-hostnames readable cache first,
clears cache before wait_for_hostname, updates it after rotation.
Rotation restarts system Tor (not just archy-tor container). Created
test-tor-rotation.sh with 10 automated checks (INSTALL-03).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added node.nostr-sign RPC that uses the node-level Nostr key (matching
getPublicKey), fixing pubkey mismatch where identity.nostr-sign used a
different key. Updated appLauncher to call node.nostr-sign. Added
nostr_sign_hash() to nostr_discovery.rs. Created test-nip07.sh with
11 automated checks (INSTALL-02).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DWN sync now uses federation node list instead of old peer list
- Fix sync URL to use port 80 (nginx) instead of 5678 (direct backend)
- DWN /dwn endpoint now accessible without auth for peer sync
- Support both message formats: {message:{}} and {messages:[{}]}
- Replace request["message"] with unified message variable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New PeerFiles.vue view shows federated peers and their shared catalogs
- Peer Files card in Cloud.vue shows when federation peers exist
- New content.download-peer RPC fetches content from peer via Tor
- Route: /dashboard/cloud/peers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- PeersOnly access now checks X-Federation-DID header against known federation nodes
- Specific availability restricts content to named peer DIDs only
- Anonymous/unknown DID requests get 403 Forbidden
- Free content remains accessible to everyone
- Paid content still returns 402 with price info
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add /content and /dwn proxy locations to nginx config (both HTTP and HTTPS)
so peer requests reach the backend instead of the SPA catch-all
- Update content_file_path() to check FileBrowser data dir as fallback when
files aren't in the dedicated content/files/ directory
- Populate size_bytes from actual file metadata in content.add
- Filter out availability:nobody items from the public catalog endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add tor-hostnames fallback for reading onion addresses when system Tor
owns hidden_service directories (permissions 700)
- Exempt federation.peer-joined, federation.get-state, and
federation.peer-address-changed from auth/CSRF (inter-node RPC)
- Set up system Tor with AppArmor overrides on archipelago-2 and 3
- All 3 servers federated and syncing successfully
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After rotation, spawns background task that publishes updated .onion to
Nostr relays and sends federation.peer-address-changed RPC to all peers
over Tor. Peers update their nodes.json with the new address.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tor.rotate-service: renames hidden service dir, restarts Tor, waits
for new hostname. Old dir kept for 24h transition.
tor.cleanup-rotated: removes expired old service directories.
tor.toggle-app: enable/disable Tor access per app with service dir
management and container restart.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: identity.nostr-encrypt-nip04, identity.nostr-decrypt-nip04,
identity.nostr-encrypt-nip44, identity.nostr-decrypt-nip44 endpoints
with auto-resolve to default identity. Frontend: appLauncher routes
nip04.* and nip44.* postMessage calls to backend RPC.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added new dependencies: `adler2`, `crc32fast`, `flate2`, `miniz_oxide`, and `libredox`.
- Updated existing dependencies: `tokio-rustls` to version 0.26.4 and `filetime` to version 0.2.27.
- Removed the `backup.rs` file as it is no longer needed.
- Introduced tests for configuration and credential management.
- Enhanced the `identity` module to generate W3C compliant DID documents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace sh -c echo with tokio::fs::write for bitcoin.conf generation
- Add client_max_body_size 1m to /rpc/ in both HTTP and HTTPS nginx blocks
- Document full audit findings in docs/security-audit-2026-03-11.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Webhook module with HTTP delivery, HMAC-SHA256 signing, and event
filtering. RPC handlers for get-config, configure, and test endpoints.
Settings page gains webhook configuration section with URL, secret,
event toggles, and test button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements monitoring/collector.rs that collects per-container CPU/RAM/network/disk,
system-wide metrics, RPC latency, and WebSocket connection count every 60 seconds.
Data stored in dual ring buffers: 1-min resolution (24h) and 15-min resolution (7d).
Three new RPC endpoints: monitoring.current, monitoring.history, monitoring.containers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace blanket cors_origin() with validate_origin() that checks the
incoming Origin header against allowed origins (host IP + dev server).
Unknown origins no longer receive Access-Control-Allow-Origin headers.
Also added X-CSRF-Token to allowed CORS headers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Double-submit cookie pattern: backend generates csrf_token cookie on login
(non-HttpOnly so JS can read it), validates X-CSRF-Token header matches
cookie on all authenticated RPC calls. Returns 403 if missing/mismatched.
Frontend reads cookie and sends header automatically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add network.list-interfaces, network.scan-wifi, network.configure-wifi,
and network.configure-ethernet endpoints using ip and nmcli commands.
Includes input validation to prevent command injection. Deployed and
verified — list-interfaces returns real interface data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Read real metrics from /proc/stat, /proc/meminfo, /proc/uptime, /proc/loadavg,
df, ps, and /sys/class/thermal/. CPU usage computed via dual-sample jiffies.
Deployed and verified on live server — all three endpoints return real data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Allow zero-amount Lightning invoices (BOLT11 "any amount") by changing
validation from amount_sats < 1 to amount_sats < 0
- identity.verify now extracts pubkey directly from did:key format instead
of requiring the DID to belong to a local identity
- tor.create-service writes config to data_dir/tor-config/ instead of
/var/lib/archipelago/tor/ (owned by debian-tor, not archipelago user)
- Add E2E test script (scripts/run-e2e-tests.sh) covering 47 RPC endpoints
- Add testing plan with results (loop/testing.md)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The credential issuance and verification handlers used
Handle::block_on() directly inside the tokio runtime, causing a
deadlock. Wrapped with block_in_place() to properly yield the
runtime thread.
Also completed full feature verification across all 25 test groups
(~175 checks) on live server.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All apps with Bitcoin dependencies now check for running Bitcoin Knots
before install. Mempool also requires Electrs. BTCPay logs a warning
when installed without LND (Lightning payments unavailable).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>