689 Commits

Author SHA1 Message Date
Dorian
b31148a8b7 fix: rpcauth credentials, reboot survival, system Tor for all containers
- Bitcoin RPC: switch to rpcauth (salted hash in bitcoin.conf, no plaintext
  in config or CLI). Password stable across reboots/restarts/deploys.
- Remove daily-reboot-test.sh cron on both servers
- Enable podman-restart.service for container auto-start after reboot
- System Tor: SocksPort 0.0.0.0:9050 with SocksPolicy for container access
- LND: tor.socks=host.containers.internal:9050 (system Tor, not container)
- Bitcoin: -proxy=host.containers.internal:9050 for Tor outbound
- bitcoin_rpc.rs: reads from secrets file, cached, stable credentials
- package.rs: dynamic rpc_user/rpc_pass, rpcauth hash generation
- network.rs: fix missing send_to_peer args (mesh encryption update)
- first-boot-containers.sh: rpcauth generation, system Tor config
- deploy-to-target.sh: rpcauth credentials, LND config migration
- Mesh: encrypted channel message support (ChaCha20-Poly1305 updates)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:56:20 +00:00
Dorian
b4d204d1d6 feat: reboot button in Settings with password confirmation
- system.reboot RPC endpoint requires password re-verification
- Uses systemd path unit pattern (tor-helper.sh) for privilege escalation
- 2-second delay before reboot to allow RPC response to reach client
- Clean UI: password input modal, loading state, error feedback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 10:48:06 +00:00
Dorian
c82158c7c8 refactor: PodmanClient uses REST API socket instead of CLI
Replace all `podman` CLI shell-outs with HTTP requests to the rootless
Podman API unix socket (/run/user/{UID}/podman/podman.sock).

Benefits:
- No process spawning overhead — direct HTTP over unix socket
- Structured JSON responses — no string parsing fragility
- Proper timeouts on all operations (5s connect, 30s default, 120s create)
- Health check method to verify socket availability
- Restart container as first-class operation

Still uses CLI for:
- Image pulls (streaming operation better suited to CLI)
- Container logs (raw text stream, not JSON)

The Podman socket is rootless (runs as archipelago user), local-only
(unix socket), and already behind our session auth in the backend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 10:13:49 +00:00
Dorian
9b6adfc42d feat: E2E encrypted Tor channel messages (ChaCha20-Poly1305)
Messages between federated nodes are now end-to-end encrypted:
- X25519 ECDH key agreement from existing ed25519 node identities
- HKDF-SHA256 key derivation with domain separation
- ChaCha20-Poly1305 authenticated encryption per message
- Random 12-byte nonce per message via OsRng (CSPRNG)
- Graceful fallback to plaintext if encryption fails
- Receiver auto-detects encrypted vs plaintext messages

The Tor transport was already encrypted (onion routing), this adds
application-layer E2E encryption so even a compromised receiving
backend can't read messages without the node's private key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 09:04:43 +00:00
Dorian
f0a403b224 fix: persistent Tor channel messages, bulletproof Tor after deploys
- Messages persisted to disk (messages.json) — survive restarts
- Sent messages stored on backend via node-store-sent RPC
- Message deduplication (same pubkey + message within 30s)
- Max 200 messages in circular buffer
- Direction field (sent/received) for proper UI display
- Container doctor: prefer system Tor, remove archy-tor container
- Deploy torrc generator: read from tor-config/services.json,
  web apps map port 80→local port for clean .onion URLs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 08:26:40 +00:00
Dorian
fc1120338d fix: Tor management system, bug fixes, federation name sync
Major changes:
- Full Tor hidden service management via systemd path unit pattern
  (tor-helper.sh + archipelago-tor-helper.path/service) — respects
  NoNewPrivileges=yes, no sudo needed from backend
- Container doctor: prefer system Tor over container, remove archy-tor
- Deploy script: fix torrc generation (read correct services.json path),
  web apps map port 80→local port, enable both tor and tor@default
- Federation: server rename pushes name to peers via background sync
- Server name: fix root-owned file, optimistic store update
- Mesh: local echo for sent messages, sendingArch loading state
- Web5: Message button → Mesh redirect, node name lookup in messages
- PeerFiles: show DID not onion in header
- Connected Nodes: flex-1 instead of fixed max-h
- Toast notifications route to Mesh
- Deploy script: fix single-quote syntax in SSH block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 02:59:29 +00:00
Dorian
4c0c8a83a9 chore: session state save — active bugs and outstanding tasks documented
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 23:03:11 +00:00
Dorian
b3949fdcf7 fix: file sharing path, Tor status consistency, Archipelago channel fixes
- ShareModal: strip leading / from filepath (was causing "absolute paths not allowed")
- Server.vue: Tor status in Local Network section now uses same source as header
- Both fixes needed for file sharing and Tor to work consistently

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:56:37 +00:00
Dorian
c4853fe746 feat: Archipelago public channel (Tor), FileBrowser auto-login
Public Channel:
- "Archipelago" channel in Mesh — broadcasts to all federation peers over Tor
- Shows received messages from all peers with pubkey label
- Auto-polls every 15s for new messages
- Orange-branded channel icon with unread badge
- Send handler routes to Tor broadcast when arch channel is active

FileBrowser Auto-Login:
- All filebrowser-client methods now call ensureAuth() before requests
- Auto-authenticates with default credentials if not logged in
- Fixes "files don't work when FileBrowser hasn't been logged into"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:24:27 +00:00
Dorian
c5417640a2 feat: Lightning channel backup, Web5 mobile tab active, file path fix
Task 14: Lightning Channel Backup
- New lnd.export-channel-backup RPC — exports SCB (Static Channel Backup)
- Settings UI: "Lightning Channel Backup" section with export + copy
- Returns base64 backup data, channel count, timestamp

Web5 mobile tab active state
- Fixed combined tab matching for Web5: includes /web5, /federation, /mesh routes
- Previously only matched /cloud and /server (wrong branch)

Content file path fix
- Allow forward slashes in filenames for subdirectories (Music/song.mp3)
- Still block .., \, null bytes, hidden files, absolute paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:47:18 +00:00
Dorian
1f732d8d08 fix: persist install progress across page navigation (Task 11)
Marketplace picks up in-progress installs from WebSocket store even
if install was started before page was opened. Removed nested .git.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:24:04 +00:00
Dorian
867e56cb84 feat: Federation UI polish — modals, backgrounds, scroll, names, blocked
- Federation page uses bg-web5.jpg background
- Invite code in full-screen modal with type label (Link/Peer)
- Join modal upgraded to full-screen with backdrop blur
- "Untrusted" renamed to "Blocked" in trust selector
- Your Nodes / Peers containers: max-h-[60vh] with inner scroll
- Server name from Settings shown on DID card + network map
- DID sync between Web5 and Federation on rotation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:11:11 +00:00
Dorian
203b044646 fix: DID sync between Web5 and Federation, cloud peer names
- Web5 loads node DID from backend on mount (authoritative, survives rotation)
- Federation rotation updates localStorage so Web5 picks up new DID
- Cloud peer names: peerDisplayName() "Node-XXXX" instead of raw DID
- Cloud hides onion addresses from peer cards
- Sync timeout increased to 180s with better error message

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:59:42 +00:00
Dorian
d98a2512b7 fix: node names everywhere, cloud peer names, sync timeout 180s
- Federation: nodeName() with Node-XXXX fallback for all views + map + sync results
- Cloud: peerDisplayName() replaces raw DIDs, hides onion addresses
- Sync timeout increased to 180s for Tor-connected nodes
- Better error message when sync fails

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:52:39 +00:00
Dorian
93aaeb4abe fix: node names not DIDs, file sharing path validation, sync results
- nodeName() shows friendly "Node-XXXX" instead of truncated DID
- nodeNameFromDid() for sync results lookup
- Map labels use node names
- Content filename validation: allow / for subdirectories (Music/song.mp3)
  but still block .., \, null bytes, hidden files, absolute paths
- Increased filename max length to 512 for paths with subdirectories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:35:41 +00:00
Dorian
12679b77b7 security: observer peers can't see onion address, resources, apps, deploy
- Onion address shows "Not visible to peers" for non-trusted nodes
- Resource usage and app list only shown for trusted nodes
- Deploy app already gated to trusted only
- Backend should also strip data in get-state (future: TASK)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:11:09 +00:00
Dorian
781cbf3263 fix: Federation layout — DID card, two-column nodes/peers grid
- DID in glass-card top-right (desktop) / below title (mobile)
- Your Nodes + Peers in two-column grid (lg breakpoint)
- "Remove Dead Nodes" button for unreachable peers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:00:59 +00:00
Dorian
f1d9ecc392 feat: Federation & Peers — split nodes/peers, invite types, cleanup dead nodes
- Page title: "Federation & Peers"
- "Link Your Nodes" generates trusted invite, "Invite a Peer" generates observer invite
- "Your Nodes" section shows trusted nodes, "Peers" section shows observer/untrusted
- "Remove Dead Nodes" button cleans up unreachable nodes with no last_seen
- DID in header with "Copied!" feedback
- Node count in section headers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:56:24 +00:00
Dorian
973beb887a fix: Federation UI — title, DID in header, copy feedback, node count
- Title: "Federation & Peers"
- Your Node DID moved to top-right header row (desktop), below title (mobile)
- Copy button shows "Copied!" feedback for 2 seconds
- Removed "X federated nodes" from description, added count to section header
- Rotate button compact in header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:44:54 +00:00
Dorian
cf184661d9 feat: DID management UI in Federation — rotate DID + notify peers
- "My Node Identity" card shows DID with copy button
- "Rotate DID" button opens modal with password confirmation
- Rotation generates new keypair, then auto-notifies all federation peers
- Shows success/failure count after notification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:31:03 +00:00
Dorian
1a138c0409 feat: DID rotation + federation peer notification (Part 3)
- node.rotate-did: generates new Ed25519 keypair, signs rotation proof
  with old key, overwrites identity files, requires password
- federation.notify-did-change: broadcasts rotation proof to all
  trusted/observer peers over Tor
- federation.peer-did-changed: receiving side verifies rotation proof
  against known pubkey before updating peer's DID
- Rate-limited: 3/600s for rotation, 5/60s for peer notification
- Signature verification uses ed25519_dalek (constant-time)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:27:16 +00:00
Dorian
f8794791f3 feat: DID persistence + federation node names in sync
Part 1 — DID Persistence:
- Deploy script creates /var/lib/archipelago/identity/ directory
- First-boot script creates identity dir with proper ownership
- Identity load now logs pubkey to confirm persistence across restarts

Part 2 — Node Names:
- NodeStateSnapshot includes node_name field
- build_local_state() passes server name to sync responses
- update_node_state() stores peer's announced name on the FederatedNode
- Names propagate automatically during federation.sync-state

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:19:13 +00:00
Dorian
f8eefa87d2 fix: AIUI chat page uses bg-aiui.jpg background
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:21:15 +00:00
Dorian
96d722ed0f fix: hide dwn from My Apps (backend service, not user app)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:05:22 +00:00
Dorian
42a1526b70 fix: hide infrastructure containers from My Apps, orange glass hover on App Store cards
- Task 13: added archy-* prefix containers, mempool-api, UI containers
  to SERVICE_NAMES filter — removes empty squares from My Apps grid
- Task 12: App Store card hover changed from white/10 to orange-500/5
  with orange border glow (subtle, not severe)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:54:26 +00:00
Dorian
86df0bcaf2 fix: LND Connect bulletproof — CORS, credentials, memory limits, restart policy
Ensures LND Connect works through every deployment path:
- Nginx: CORS $http_origin on /lnd-connect-info (both HTTP+HTTPS)
- Nginx: no cookie gate (backend is 127.0.0.1-only)
- LND UI source: fetch with credentials: 'include'
- Deploy: rebuilds LND UI with --no-cache every deploy
- First-boot: --restart unless-stopped + memory limits on UI containers
- Backend: bound to 127.0.0.1:5678 in systemd service

Root cause was CORS: LND UI on :8081 fetching :80 is cross-origin.
Browser blocked reading the 200 response without CORS headers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:17:14 +00:00
Dorian
9fe680def1 fix: CORS headers on /lnd-connect-info for cross-origin LND UI fetch
The LND UI runs on port 8081 (separate nginx container) but fetches
/lnd-connect-info from port 80. This is cross-origin, so browsers
block reading the response without CORS headers. Added dynamic
Access-Control-Allow-Origin from $http_origin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:11:40 +00:00
Dorian
9e15444228 fix: LND Connect — remove nginx cookie gate, rebuild LND UI with credentials
- Nginx cookie check removed for /lnd-connect-info — backend is
  localhost-only so no external access possible. Browsers (especially
  Brave) don't reliably send SameSite=Lax cookies from iframe fetches.
- LND UI source restored from archive with credentials: 'include'
- Discover.vue install banner removed (inline card progress only)
- Server.vue: Connectivity → Tor Status, using tor.list-services

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:02:17 +00:00
Dorian
c78a123e9c fix: Tor Status label (was Connectivity), remove Discover install banner
- Server.vue: "Connectivity" → "Tor Status" with tor.list-services check
- Discover.vue: removed full-width install progress banner (progress shown inline on cards)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:44:46 +00:00
Dorian
ca65a8172c feat: Tor status + cleanup, Tailscale admin, marketplace install UX
- Task 0: Tor status dot (green/red) + "Cleanup Old" rotated services button
- Task 2: BTCPay already handled (opens new tab)
- Task 3: Tailscale launches https://login.tailscale.com/admin/machines in new tab
- Task 8: Marketplace install shows inline progress on card (removed banner)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:38:11 +00:00
Dorian
f20f0650cf feat: Discover view, Fleet dashboard, MeshMap, type fixes
- New Discover.vue (app store redesign)
- Fleet.vue dashboard for .228
- MeshMap.vue component
- Fixed Discover.vue type errors (unused var, type predicate)
- Various UI updates (Apps, Dashboard, Marketplace, Mesh, Web5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:12:01 +00:00
Dorian
9b4aa712f2 docs: add post-pentest security standards to CLAUDE.md
Mandatory rules for all new code based on 33 pentest findings.
Covers: input validation, auth checks, SSRF prevention, session
management, CSP, nginx config, container security, RBAC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:04:21 +00:00
Dorian
e574b6dd18 fix: SameSite=Strict → Lax for session cookies (fixes iframe fetch)
SameSite=Strict prevents cookies from being sent when iframe content
(like the LND UI at /app/lnd/) fetches endpoints on the parent origin
(/lnd-connect-info). Lax still protects against CSRF on POST requests
but allows same-site GET navigations and fetches from iframes.

This was the root cause of "Failed to fetch" on LND Connect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:30:58 +00:00
Dorian
6033199864 fix: remove backend auth check on /lnd-connect-info (nginx validates session)
Backend is bound to 127.0.0.1 — only nginx can reach it.
Nginx checks cookie_session presence. Adding backend auth broke
the LND UI iframe fetch because the session validation was too
strict for the cross-proxy cookie flow. The nginx layer is the
correct auth gate for this endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:20:44 +00:00
Dorian
5e19a80f9d feat: add Discover page — cypherpunk app store with sovereignty messaging
- New Discover.vue with hero banner, featured sovereignty stack apps,
  principle cards, manifesto footer, and full app grid
- Featured apps (Bitcoin Knots, LND, BTCPay, Vaultwarden) with
  expanded privacy/sovereignty descriptions
- Discover is first tab in categories bar on App Store pages
- Smart back navigation: detail pages return to Discover when navigated from there
- Category clicks from Discover navigate to Marketplace with category pre-selected
- Cypherpunk aesthetic: terminal tags, scanline overlays, gradient accents,
  animated Bitcoin orange headings
- Global CSS classes: discover-hero, discover-terminal-tag, discover-featured-card,
  discover-principle-card, discover-manifesto
- Route added: /dashboard/discover

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:14:12 +00:00
Dorian
aabeb2e679 security: add is_authenticated check to /lnd-connect-info backend handler (AUTH-011)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:58:16 +00:00
Dorian
e8674a3801 fix: iframe auto-retry for apps still starting + retry button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:52:16 +00:00
Dorian
ba6a0e6fe6 fix: deploy fixes secrets dir ownership (was root-only, backend couldn't read)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:07:13 +00:00
Dorian
f292ebf63e fix: ElectrumX status uses headers.subscribe (returns height correctly)
The previous blockchain.numblocks.subscribe call returned data in a
format the parser couldn't extract height from. headers.subscribe
returns {height: N, hex: "..."} which is properly parsed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:51:03 +00:00
Dorian
1dfceeb957 fix: deploy auto-fixes root-owned config files + dead man's switch permissions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:04:50 +00:00
Dorian
c037db9d42 fix: What's New v1.3.0, backend bind 127.0.0.1 in deploy + systemd, dead man's switch permissions
- Added v1.3.0 release notes to Settings "What's New" modal
- Deploy script now auto-fixes backend bind address (0.0.0.0 → 127.0.0.1)
- All image-recipe systemd/service files updated to 127.0.0.1
- Fixed dead man's switch: alert-config.json owned by root, now chown'd
- Removed unused toggleAutoSync function (build error)
- Deploy script adds LND REST port 8080 to Tor config generation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:55:31 +00:00
Dorian
1a74a930f7 security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation

Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)

UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet

Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
Dorian
d1b48388fb fix: add QR codes to Home wallet receive modal
ReceiveBitcoinModal was missing QR code generation that Web5.vue has.
Added canvas refs + qrcode rendering for both on-chain (bitcoin: URI)
and lightning (lightning: URI) receive flows. Matches Web5 pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 00:18:41 +00:00
Dorian
8c800525c0 fix: deploy auto-fixes stale LND config (rpchost + rpcpass)
LND was crash-looping because lnd.conf had 127.0.0.1:8332 (container
loopback, not reachable) and the old hardcoded password. Deploy script
now detects stale values and patches them to bitcoin-knots:8332 with
the current secrets file password. Fixes address generation failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 00:09:15 +00:00
Dorian
aad98dec08 fix: telemetry reporter field name cpu_percent, add type annotation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:53:17 +00:00
Dorian
a9bb5a28ce chore: mark TASK-17 and BUG-3 done in MASTER_PLAN
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:50:49 +00:00
Dorian
7cb4fd6812 feat(TASK-17): deploy auto-tag + BUG-3 IndeedHub WS fix
TASK-17: Deploy script auto-tags successful clean deploys with next
alpha version number. Skips if commit already tagged or working tree
is dirty.

BUG-3: Updated IndeedHub submodule — removed dead nostrConfig with
hardcoded ws://localhost:7777 that caused WebSocket reconnection spam
in browser console. Relay detection via relay.ts (auto-detect /relay
proxy) is the active path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:46:51 +00:00
Dorian
75018da1da chore: update TASK-12 status in MASTER_PLAN
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:38:47 +00:00
Dorian
41ab499698 feat(TASK-12): periodic telemetry reporter — 15min interval, collector POST
Background task spawned on server startup: every 15 minutes, checks opt-in
status, builds anonymous health report (node ID hash, version, uptime,
CPU/RAM/disk %, container states, recent alerts), saves to disk, and POSTs
to TELEMETRY_COLLECTOR_URL env var if configured. Non-fatal on failure.

Fixed FiredAlert field references (kind not rule_type, timestamp not
fired_at) in both monitoring and analytics modules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:36:57 +00:00
Dorian
b8afb10ec6 test: fix 5 appLauncher tests for panel mode, 515/515 passing
Tests expected router.push but panel mode (now default) uses panelAppId
store state instead. Updated assertions to check panelAppId. Fixed
BTCPay app ID from 'btcpay' to 'btcpay-server'. All 515 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:27:26 +00:00