790 Commits

Author SHA1 Message Date
Dorian
aae3391ce8 fix: fullscreen video in media lightbox
Video fills entire viewport with no padding/border-radius. Double-click
toggles native fullscreen. Reduced padding for all media types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:38:36 -04:00
Dorian
bb14490fb7 feat: botfights, discover, mobile gamepad, content handler, package config updates
Miscellaneous improvements: botfights manifest, discover page curated
apps, mobile gamepad enhancements, content HTTP handler, package
install config updates, health monitor tweaks, shared content UI,
container specs and image version updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:11:41 -04:00
Dorian
24f122f35a fix: allow Fedimint install without local Bitcoin node
Fedimint can use a remote Bitcoin RPC (e.g., over Tailscale or Tor).
Dependency check now logs info instead of blocking installation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:00:06 -04:00
Dorian
8d82666c82 fix: beautiful media lightbox, filebrowser noauth, deploy script
MediaLightbox: full glassmorphic redesign with dark backdrop, smooth
transitions, proper video/audio/image support. FileBrowser: noauth
config on persistent volume. Deploy script: fixed sed quoting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:49:01 -04:00
Dorian
2c98bdd19d feat: streaming ecash payments + media playback overhaul
Cashu ecash protocol (BDHKE blind signatures, cashuA token format,
mint HTTP client) replacing the stub wallet. TollGate-inspired streaming
data payment system with step-based pricing (bytes/time/requests),
session management with incremental top-ups, usage metering, and
Nostr kind 10021 service advertisements.

13 new streaming.* RPC endpoints. Content server now verifies real
Cashu tokens. Profits tracking includes streaming revenue.

Frontend: GlobalAudioPlayer (persistent bottom bar across all pages),
video lightbox with full controls, audio in MediaLightbox, free file
previews (no blur), paid 10% audio/video previews, separated play
vs download buttons in PeerFiles.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:31:28 -04:00
Dorian
0995aa1033 fix: move resolver directives into server blocks in external-app-proxies
Prevents duplicate resolver directive error when both
nginx-archipelago.conf and external-app-proxies.conf are loaded
at http context level.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 16:57:58 -04:00
Dorian
abf6ca000d feat: botfights container app + mobile gamepad + indeedhub fixes
- Promote botfights from external proxy to container app (port 9100)
- Add /app/botfights/ nginx proxy rules (HTTP + HTTPS)
- Add ARCHY_EMBEDDED env var to botfights container config
- Add BOTFIGHTS_IMAGE to image-versions.sh
- Add mobile gamepad overlay (D-pad + A/B + START/SELECT) for botfights
  arcade mode, sends postMessage arcade-input to iframe
- Remove old /ext/botfights/ and port 8901 external proxy blocks
- IndeeHub: add post-install nginx patching for NIP-07 provider injection
- IndeeHub: fix docker image references to registry (was localhost)
- IndeeHub: update port 7777 -> 7778

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 16:47:54 -04:00
Dorian
c421fdb064 feat: companion app improvements and intro overlay
Android: NES controller/keyboard enhancements, WebSocket reconnect,
portrait mode. Backend: remote input handler updates. UI: companion
intro overlay on dashboard, relay improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 20:01:14 +01:00
Dorian
918fec0af7 feat: promote botfights from web-only to container app
Convert botfights from external link to real container app on port 9100.
Add manifest, update marketplace/discover/kiosk/session configs, switch
registry URLs to git.tx1138.com.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 20:01:14 +01:00
Dorian
548107eb8b feat: add botfights app config and update container registry
- Add git.tx1138.com to trusted registries (replaces old 80.71.235.15)
- Add botfights app config: port 9100, data volume, JWT_SECRET auto-gen, fight loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 20:01:14 +01:00
Dorian
a3217a9db4 refactor: remove app container creation from deploy script
Apps are now installed exclusively via the Marketplace UI.
The deploy script handles code sync, backend/frontend builds,
and service restarts only. The legacy container creation code
is wrapped in `if false` to preserve git history.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:16:31 -04:00
Dorian
8ffb10d7e0 fix: ISO build freshness, WireGuard startup, VPN status, kiosk remote doubling
- ISO builder: run npm ci before npm run build to prevent stale UI artifacts
- Unbundled ISO: clean container-images dir to prevent bundled tars leaking
- WireGuard: use After=network.target instead of network-online.target for
  faster wg0 startup on install
- VPN status: check actual nvpn0 interface instead of config tunnel_ip to
  prevent NostrVPN from showing standalone WireGuard IP
- ContainerApps: filter out not-installed bundled apps (fixes Bitcoin Knots
  appearing on clean unbundled installs)
- Kiosk: persist kiosk mode to localStorage before /kiosk redirect so
  App.vue can skip remote relay (fixes input doubling with companion app)
- IndeedHub: fix port mapping and X-Forwarded-Prefix passthrough

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:01:10 -04:00
Dorian
401a44b40a fix: IndeedHub port 7778, podman registries v2 format
- IndeedHub container port changed from 7777 to 7778 (7777 used by nostr-relay)
- Nginx proxy updated to route to 7778
- Backend config.rs port mapping updated
- Podman registries.conf switched to v2 format (fixes mixed v1/v2 error)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:32:32 -04:00
Dorian
dd5c3783ed chore: update Cargo.lock
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:02:36 -04:00
Dorian
7ca973e7b1 chore: bump version to 1.3.5
Registry migration to git.tx1138.com/lfg2025, version bump for
release testing across nodes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:38:45 -04:00
Dorian
a147db9b70 refactor: migrate container registry from 80.71.235.15:3000 to git.tx1138.com/lfg2025
All hardcoded references to the old IP-based registry replaced across
Rust backend, Vue frontend, shell scripts, Dockerfiles, CI, and docs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:33:10 -04:00
Dorian
68b02359dc ui updates 2026-04-11 13:38:01 +01:00
Dorian
b7ff0b1d38 fix: VPN IP dedup, status polling, pair-a-device text
- VPN status: don't show WG IP as NostrVPN IP when tunnel not up
- VPN section polls every 15s so IP updates after pairing
- NostrVPN shows "Pair a device" when service active but no tunnel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 04:48:08 -04:00
Dorian
b9044e58c7 fix: unbundled first-boot, fast VPN status, kiosk relay dedup
- Unbundled ISO: first-boot only creates FileBrowser (marker file .unbundled)
  Users install apps from Marketplace — no more bitcoin/mempool on clean install
- VPN status: read tunnel IP from config file (instant) instead of nvpn status (22s)
- Kiosk: App.vue skips remote relay on /kiosk path (prevents duplicate input)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 04:01:35 -04:00
Dorian
067a3ed106 fix: ISO boot, container installs, VPN, nginx, companion input
- LUKS auto-unlock: initramfs hook + systemd service + nofail fstab
- Rootfs packages: add passt, aardvark-dns, netavark, nftables for Podman 5.x
- nginx: resolver + variable proxy_pass for external domains (DNS at boot)
- Boot: loglevel=0 suppresses kernel warnings, serial console for QEMU
- Container installs: write configs before chown, sudo chown for LUKS volumes
- Container installs: build UI sidecars locally (not from registry) for auth injection
- Bitcoin UI: inject RPC auth from secrets file, --no-cache rebuild
- Secrets: chown to archipelago user in first-boot (backend needs read access)
- Podman: image_copy_tmp_dir for read-only /var/tmp in user namespace
- NostrVPN: enable service in auto-install, always include public relays
- NostrVPN: read tunnel IP from nvpn status (not just config file)
- VPN invite: v2 base64 no-pad format matching phone app
- Companion input: relay always active, kiosk skips relay listener (prevents double input)
- dev-start.sh: production build includes AIUI deployment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 03:10:49 -04:00
Dorian
88bdba19db fix: route ISO builds to iso-builder runner (ThinkPad only)
VPS runner was sniping jobs and failing instantly (no build env).
Changed runs-on from ubuntu-latest to iso-builder label, which only
the ThinkPad runner has registered.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:50:44 +01:00
Dorian
f8cf0afbfc fix: source nvm in CI workflow for npm/npx availability
act_runner runs non-interactive shells where nvm isn't loaded.
Cargo steps already source .cargo/env but frontend steps were missing
the equivalent nvm.sh sourcing, causing "npm: command not found".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:36:03 +01:00
Dorian
e8251b5bad feat: add production build mode to dev-start.sh (option 10)
Linux-only option that mirrors ISO install exactly: builds backend
(release), frontend (with typecheck), syncs all configs, and restarts
all system services (Tor, WireGuard, NostrVPN, nginx, backend).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:08:42 +01:00
Dorian
ca2ddc889e fix: add e2fsprogs and cryptsetup-initramfs to rootfs
ISO boot failed in emergency mode because:
- fsck.ext4 binary missing (no e2fsprogs in rootfs)
- LUKS data volume never opened (no cryptsetup-initramfs in initramfs)

Both packages were in the installer debootstrap but not the target rootfs
Dockerfile. The initramfs regeneration at install time now includes LUKS
support since cryptsetup-initramfs is present.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 21:07:34 +01:00
Dorian
2517379ac3 chore: Debian 12 → 13 (Trixie) migration, service hardening
- Update all references from Debian 12 (Bookworm) to Debian 13 (Trixie)
- Enable SystemCallArchitectures, RestrictAddressFamilies, RestrictRealtime
  in archipelago.service (safe on systemd 256+ which respects NoNewPrivileges=no)
- Update GLIBC compatibility checks from 2.36 to 2.40
- ISO filename, build container, and docs updated throughout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 21:32:08 +02:00
Dorian
b8a09b448b fix: AIUI /aiui/ base path, nginx alias cycle, VPN auth, container boot
- AIUI: rebuild with /aiui/ base path (router, chunk loader, SW scope)
- nginx: remove alias from /aiui/ location (caused try_files redirect cycle)
- VPN: WireGuard standalone setup, auth improvements
- ISO: build script hardening, service file updates
- first-boot-containers: networking stack fixes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 20:42:09 +02:00
Dorian
a8c6a36cd1 fix: netavark GLIBC mismatch in ISO, container adopt, app updates
ISO build no longer copies netavark from build host (Debian 13/GLIBC 2.41)
which broke container networking on Debian 12 targets. Rootfs already
installs netavark from Debian 12 repos — just configure the backend.

Install RPC now adopts existing containers (from first-boot) instead of
erroring on duplicates. Container scanner extracts real versions from
image tags and detects available updates against pinned versions.

Frontend shows update button with version info when updates are available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 11:47:35 +02:00
Dorian
d0b9f168f4 fix: harden ElectrumX status — cached backend, stable frontend
Backend: cache status in RwLock, refresh every 15s via background task.
Eliminates per-request TCP race to ElectrumX that caused volatile errors.
Fix error classification so "Failed to read" is transient, not hard error.

Frontend: keep last-known-good data across failed polls, persist Tor
onion once discovered, adaptive polling (5s active / 30s synced).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 10:32:55 +02:00
Dorian
07dff3e4ca fix: container stack installers, DNS resolution, uninstall cleanup
- Replace aardvark-dns container names with host.containers.internal
  for all cross-app connections (LND→Bitcoin, ElectrumX→Bitcoin,
  Mempool→ElectrumX, Fedimint→Bitcoin, NBXplorer→Bitcoin P2P+RPC)
- Add BTCPay multi-container stack installer (postgres + nbxplorer +
  btcpay-server) with proper secrets, data dir ownership, NOAUTH
- Add Mempool multi-container stack installer (mariadb + mempool-api +
  mempool-frontend) with host.containers.internal for RPC
- Immediately remove apps from state on uninstall (no 3-min ghost delay)
- Include archy-bitcoin-ui in bitcoin uninstall container list
- Fix LND UI port 8081 (was 8080, conflicting with LND gRPC)
- Fix ElectrumX UI: proxy /electrs-status to backend, cache-busting
  headers, graceful fallback when backend returns HTML
- Add Tor hidden services for ElectrumX and LND in torrc template
- Remove unused detect_bitcoin_container_name() (replaced by
  host.containers.internal)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 23:29:50 +02:00
Dorian
b30f41f3d7 feat: standalone WireGuard from first install, fix networking stack
Standalone WireGuard (wg0:51820):
- New archipelago-wg.service creates wg0 independent of NostrVPN
- Keypair generated on first-boot, persisted on LUKS partition
- vpn.create-peer uses wg genkey/pubkey (no nvpn dependency)
- wg-address service depends on archipelago-wg, not nostr-vpn

Networking fixes:
- Remove nos.lol from default relays (requires PoW, events rejected)
- Add Tor hidden service for private relay (port 7777) — NAT'd peers
  can reach relay over Tor for NostrVPN signaling
- Fix Tor hostname sync race: wait loop before copying hostname files
- Add tor-hostnames + wireguard dirs to LUKS partition setup
- Include relay in hostname sync loops (setup-tor.sh + first-boot)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 20:27:38 +02:00
Dorian
a029a4c948 feat: NostrVPN add-device guided wizard
Replace disconnected "Generate Invite" + "Add participant" with a 2-step
wizard: enter phone npub → get invite QR + mesh details. Backend vpn.invite
now accepts optional npub param to add participant in the same call. Modal
shows network ID, node npub, and relay URLs for manual app configuration.

Also includes nostr-vpn service hardening (rate-limit restarts, reset-failed
before enable).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 19:04:53 +02:00
Dorian
ef69434364 fix: reboot/shutdown commands work without sudo prefix
polkit denies reboot/shutdown for non-root users without a local seat
(e.g. SSH sessions). Since archipelago has NOPASSWD sudo, add shell
aliases so reboot/shutdown/halt/poweroff transparently use sudo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:51:21 +02:00
Dorian
3ee5dd6715 fix: nostr-vpn crash-loop on fresh install, relay config lost on LUKS
Two issues on fresh ISO install:
1. nostr-vpn.service was enabled in rootfs but env file doesn't exist
   until first-boot generates Nostr identity — crash-loop on boot.
   Now only enabled by first-boot-containers.sh after identity exists.
2. LUKS encrypted partition mounts over /var/lib/archipelago/, hiding
   the relay config.toml the Dockerfile put there. Now copies relay
   config and creates nostr-relay/nostr-vpn dirs on the LUKS partition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:48:38 +02:00
Dorian
eebdade0d4 fix: vpn.add-participant writes to root-owned daemon config via sudo
The nvpn daemon config at /var/lib/archipelago/nostr-vpn/ is owned by
root, but the backend runs as archipelago. Direct write silently failed,
so adding a second phone's npub never reached the daemon — service
restarted with stale config. Now falls back to sudo cp for root-owned
paths, and first-boot sets ownership to archipelago.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:25:39 +02:00
Dorian
aa2a13d510 fix: build report — rootfs tar path prefix, git repo path
podman export creates paths without ./ prefix, but tar tf checks
used ./etc/... which never matched. List once, grep without prefix.
Also fix git commands to use $HOME/archy (workspace has no .git).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:00:53 +02:00
Dorian
d7286d5f63 fix: expand brace globs in Dockerfile RUN — dash has no brace expansion
Dockerfile RUN steps execute under /bin/sh (dash on Debian), which
doesn't support brace expansion {a,b,c}. The nostr-relay directory
was never created, causing the config copy to fail (build #444).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:43:22 +02:00
Dorian
5f40cd2af4 fix: restore musl static build, brand GRUB as Archipelago
Runner is Debian 13 (glibc 2.41), ISO rootfs is Debian 12/bookworm
(glibc 2.36). Dynamic binary crashes with GLIBC_2.41 not found.
Musl static build eliminates the dependency entirely.

Also set GRUB_DISTRIBUTOR="Archipelago" so installed system boot
menu says "Archipelago" not "Debian GNU/Linux".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:19:14 +02:00
Dorian
42c29b99e2 feat: ISO networking stack — relay + nvpn v0.3.7 + WireGuard
Add nostr-rs-relay as native system service (port 7777) for VPN
signaling. Every node runs its own private relay from first boot.
Update nvpn binary from v0.3.4 to v0.3.7 (fixes mesh event
processing). Add WireGuard helper and address service for peer VPN.
First-boot script configures relay, nvpn identity, relay URLs
(direct + Tor onion), and syncs daemon config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:06:27 +02:00
Dorian
b0907c48b2 feat: NostrVPN mesh + VPN card UI + nvpn v0.3.7
- VPN card: relay URLs, device management, invite QR, add participant
- Backend: vpn.invite, vpn.add-participant, vpn.peer-config RPCs
- nvpn v0.3.7 system service (fixes event processing bug in v0.3.4)
- First-boot: auto-configure nvpn with node identity and endpoint
- Service: AF_NETLINK for WireGuard, NoNewPrivileges=no for sudo wg
- TASK-50: networking stack reliability from first install

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:00:00 +02:00
Dorian
6c1f316956 fix: revert musl build, add ACPI power-off support
- Revert CI to normal cargo build --release (musl was false positive)
- Add acpid + acpi-support-base to rootfs packages
- Add acpi=force to GRUB and ISOLINUX boot params (installer + installed)
- Fixes "Maybe missing ACPI. Shutdown not powering off" on some hardware

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:15:09 +02:00
Dorian
8e094c7ce9 fix: install/uninstall UI state, progress bar, auto-Tor hidden services
- Install progress bar replaces action buttons (no overlay)
- Hide status badge during install/uninstall
- Uninstall keeps progress state until container disappears from WebSocket
- Uninstall RPC timeout increased to 660s (Bitcoin UTXO flush)
- Installing apps appear in My Apps immediately as placeholders
- Auto-configure Tor hidden service for every app on install
- Widen Tor module visibility for install hooks
- Only clear stale install entries on error status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 09:20:18 +02:00
Dorian
5c117f5718 fix: static musl build — eliminates GLIBC version mismatch on ISO
Build server (Debian 13) has GLIBC 2.41 but ISO targets Debian 12
(GLIBC 2.36). Switching to x86_64-unknown-linux-musl produces a
fully static binary that runs on any Linux.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 01:27:47 +02:00
Dorian
43ac2975dc fix: fast VPN status — read config file instead of slow nvpn CLI
nvpn status command hangs for seconds (connects to relays), causing
the Network page to never finish loading. Read tunnel_ip from the
local config file instead (instant).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:36:49 +02:00
Dorian
a34075287d fix: nostr-vpn service crash on reboot, detect activating state
- Remove ReadWritePaths sandbox (causes namespace error when /run/nostr-vpn
  doesn't exist after reboot — /run is tmpfs)
- Detect both 'active' and 'activating' states in VPN status check

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 22:05:08 +01:00
Dorian
0ecfdd1d01 perf: skip missed ticks on all intervals, reduce scan frequency
Prevents burst of health checks, scans, and snapshots after slow
podman responses by using MissedTickBehavior::Skip. Bumps container
scan interval from 30s to 60s to reduce DB lock contention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 20:25:09 +01:00
Dorian
4fc6c103ba feat: VPN peer QR code UI, consolidate CI workflows
- Add vpn.create-peer, vpn.list-peers, vpn.remove-peer RPC methods
- Generate WireGuard config + QR code (SVG) for mobile device connection
- Add "Add Device" modal on Network page with QR scanner support
- Remove old build-iso.yml (replaced by build-iso-dev.yml)
- Remove container-tests.yml (tests run in dev workflow)
- Remove container orchestration tests from dev workflow (redundant)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:44:00 +01:00
Dorian
b0e5e8c00e perf: incremental cargo builds, skip apt when cached
- Build in $HOME/archy to reuse target/ cache across CI runs
- Skip apt-get install when ISO build deps already present
- Cargo tests also use persistent target dir

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 16:08:29 +01:00
Dorian
9eb5d8cee0 fix: kiosk boot loop — redirect /kiosk to / for proper boot screen
Kiosk was redirecting /kiosk → /dashboard, bypassing RootRedirect
and BootScreen entirely. This caused the kiosk to land on Login.vue
showing "server is starting up" in a loop instead of the proper
terminal-style boot progression screen.

Now /kiosk → / → RootRedirect → BootScreen, matching what remote
browsers see.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 16:04:58 +01:00
Dorian
d8d472f72c fix: nostr-vpn service — set HOME, create dirs, remove strict sandbox
nvpn binary writes to $HOME/.config/nvpn. Set HOME to data dir,
create runtime dirs in ExecStartPre, remove overly restrictive
ProtectSystem/ProtectHome that blocked the binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:57:38 +01:00
Dorian
7a78d750f4 fix: TS type error in VPN status, remove unused assignment warning
- Fix vpnStatus type mismatch (provider: string|undefined vs string|null)
- Remove redundant history_dirty assignment in health_monitor.rs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:23:17 +01:00