- 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>
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>
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>
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>
- 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>
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>
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>
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>
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>
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>
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>
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>
Health endpoint now returns JSON with version and service status instead
of plain "OK". Updated BETA-PROGRESS.md: BUG-1 done, TASK-8 done (12/12
+ code audit), FEATURE-4 at ~80%, overall at ~55%. Added session #5 log.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced single hardcoded release note with scrollable history of all
alpha releases (alpha.1 through alpha.9). Each release has version badge,
date, and categorized highlights. Inner container scrolls independently
with max-height 85vh. Current release highlighted with orange badge,
older releases in muted style with left border timeline.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Password hashing migrated from bcrypt to Argon2id (m=64MiB, t=3, p=4).
Transparent upgrade: on successful bcrypt login, re-hashes with Argon2id
and persists. New signups and password changes use Argon2id directly.
Unifies crypto stack — Argon2id was already used for TOTP and backup KDF.
Bitcoin RPC password: no longer falls back to hardcoded "archipelago123".
On first boot, generates a random 32-char hex password from CSPRNG,
saves to /var/lib/archipelago/secrets/bitcoin-rpc-password with 0600
permissions. Existing installs with secrets file are unaffected.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- RBAC: Viewer role changed from prefix "system." to explicit allowlist
of safe read-only methods. Prevents Viewer access to system.factory-reset,
system.shutdown, system.reboot, system.disk-cleanup.
- identity.create: Name/label param now enforces max 100 chars.
- sanitize_error_message: Changed from contains() to starts_with() for
prefix matching, preventing internal errors that happen to contain
user-facing keywords from leaking through.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TASK-31: Cleaned up Apps page nav header structure (tabs + categories + search).
TASK-38: Added Bitcoin Core sync progress gauge to homepage System Stats card —
shows sync percentage, block height, and green/orange color coding. Only
appears when Bitcoin is running. Grid expands to 4 columns when visible.
Updated MASTER_PLAN.md — cleaned up completed sections, moved done items.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BUG-1 (P0): CSRF tokens now HMAC-derived from session token instead of
random — survives backend restarts, eliminates cookie/header race conditions.
Frontend retries 403s as belt-and-suspenders.
TASK-8 H2: federation.peer-joined verifies ed25519 signature on join messages.
TASK-8 H3: federation.peer-address-changed requires signed proof from known peer.
TASK-8 H4: Rust backend default bind 0.0.0.0 → 127.0.0.1 (nginx proxies all).
BUG-20: ElectrumX index estimate string fixed from ~55GB to ~130GB.
BUG-37: App card Start/Stop buttons split into loading vs interactive states
to prevent WebSocket state flicker during container scans.
BUG-40: Uninstall modal uses Teleport to body with z-[3000] for full overlay.
BUG-41: Uninstalling overlay on card + optimistic store removal.
Updated MASTER_PLAN.md and BETA-PROGRESS.md to reflect all completed work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch docker-compose from regtest to signet, add standalone testnet stack
(docker-compose.testnet.yml) with Bitcoin+LND+ThunderHub+Fedimint. Mock
backend now auto-detects Podman/Docker sockets and includes full LND/Lightning
RPC mocks. Dev scripts refactored with boot mode, testnet option, and macOS
EAGAIN fix for port cleanup. Added dev faucet button to Home.vue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BUG-33: CPU load alert threshold increased from 2x to 4x core count
(8→16 on 4-core machine) to reduce false alerts during container ops
- TASK-27: Launch buttons for new-tab apps now show external link icon
(BTCPay, Grafana, PhotoPrism, Portainer, OnlyOffice, etc.)
- TASK-36: Iframe error screen now distinguishes between X-Frame-Options
blocked vs container not reachable, with appropriate messaging
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Boot screen (BootScreen.vue) is already fully production-integrated:
- RootRedirect health checks → shows boot screen if server down
- Polls /rpc/v1 until healthy → transitions to login/onboarding
- Kiosk launcher loads browser immediately, boot screen handles wait
- All audio/icon assets deployed to /opt/archipelago/web-ui/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile mesh had overflow:hidden inherited from desktop layout,
preventing scrolling. Added overflow:visible override for mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile mesh view uses 0 top padding so the Dashboard's mobileTabPaddingTop
takes effect correctly (pushes content below fixed tab bar).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Mesh: remove display:flex from .mesh-header CSS that overrode
Tailwind hidden class, causing title/peers to show on mobile
- Federation: add title={did} on node name for hover tooltip
- Cloud: add title={did} on peer name for hover tooltip
- Both already show node.name when available, DID as fallback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverted inline-style sticky header. The hack used hardcoded rgba
background that didn't match across screens and shifted position
between tabs. Will implement properly with a shared layout component.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
My Apps/App Store/Services tabs, category filters, and search bar
now stay fixed at the top on scroll using sticky positioning with
glass-blur background. Applied to both Apps.vue and Marketplace.vue
desktop views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reordered receive method tabs from [Lightning, On-Chain, Ecash] to
[On-Chain, Lightning, Ecash] in both ReceiveBitcoinModal and Web5
view. Default selection changed to 'onchain'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile mesh view had padding: 0 causing glass cards to go edge-to-edge.
Added 12px padding for consistent gutters.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added fedimintd to the metadata map with title "Fedimint Guardian"
and description clarifying it's the federation consensus node.
Shares the fedimint.png icon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When ElectrumX is indexing and can't accept TCP connections, the UI
now shows the actual index size (e.g. "126.9 GB") in the Indexed
Height field instead of a generic "Building..." label. Also shows
the size in the status message for better progress visibility.
Updated estimated full index size from 55GB to 130GB (2026 mainnet).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fedimintd serves JSON-RPC API on 8174 and Guardian web UI on 8175.
Updated all port mappings: frontend AppSession, nginx HTTP/HTTPS
proxies, PodmanClient static map.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dynamic port extraction from container bindings, falling back to the
static PodmanClient address map for apps without port bindings (e.g.
host-network containers).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- Remove most hardcoded port overrides from docker_packages.rs, use
dynamic port extraction from actual container bindings with fallback
to static map in PodmanClient
- Fix OnlyOffice (8044), NginxPM (8181), Fedimint (8174) port mappings
- Remove Tailscale fake web UI port (no web UI)
- ElectrumX: detect "Connection reset" as syncing state (not error)
Deploy script:
- Auto-configure sysctl unprivileged_port_start=80 for rootless
- Auto-enable loginctl linger for container persistence
- Auto-enable podman.socket for Portainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>