UEFI boot:
- xorriso now uses -append_partition with ESP type GUID
(C12A7328-F81F-11D2-BA4B-00A0C93EC93B) instead of -isohybrid-gpt-basdat
which only creates "basic data" partitions. Strict UEFI firmware
requires the correct ESP type to find BOOTX64.EFI.
- Uses Arch Linux ISO approach: -append_partition + appended_part_as_gpt
WebSocket/login from LAN browser:
- HTTPS nginx /ws block was missing proxy_set_header Cookie $http_cookie
Session cookie wasn't forwarded → backend returned 401 → WS failed
Password UX:
- Renamed "Change Password" → "Set Password" with description explaining
default password is password123
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move installingApps from local refs in Marketplace/Discover to the
global server store. Install progress now persists when navigating
between views. My Apps shows installing overlay with progress bar
for apps being installed from the Marketplace.
Changes:
- server.ts: add installingApps Map + helpers to store
- Marketplace.vue: use store's installingApps instead of local ref
- Discover.vue: same
- Apps.vue: pass isInstalling + installProgress to AppCard
- AppCard.vue: add amber installing overlay with progress bar
522 tests pass, vue-tsc clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OnboardingDone: "Go to Login" → "Set Password" with context text
- Reboot: lazy-unmount live FS before USB removal prompt, suppress
kernel SquashFS messages, auto-reboot after 10s countdown
- Initramfs: filter "Possible missing firmware" warnings (cosmetic)
- ISOLINUX: menu centered at bottom (VSHIFT 18, HSHIFT 32, WIDTH 18)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Frontend:
- Router guard checks isOnboardingComplete before redirecting to /login.
Fresh installs now go to /onboarding/intro instead of stuck on login.
- Login.vue: autocomplete="off" — fixes Enter key focusing button
instead of submitting the form.
ISO build:
- Added uidmap, slirp4netns, fuse-overlayfs to rootfs (required for
rootless Podman, lost to --no-install-recommends)
- Tor setup: mkdir + chmod 700 for hidden service dirs before starting
(Tor refuses 750/setgid permissions)
CI:
- QEMU headless boot test step after smoke test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add identity.create + server.echo to UNAUTHENTICATED_METHODS
- Clear web/dist before frontend build to prevent stale artifacts
- Add autocomplete attrs to login inputs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CI: configure root podman with insecure registry so FileBrowser
image can be pulled during ISO build
- CI: chmod u+rwX on workspace and act cache to fix cleanup failure
- ISO: auto-login on tty1 (no password prompt on console)
- Frontend: add console.log debug output for onboarding routing,
health checks, and 401 redirects to diagnose session issues
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ISO build: configure insecure registry for root podman so FileBrowser
image can be pulled during build (was failing with HTTPS error)
- Auto-login on tty1 so no password prompt on console
- RootRedirect: persistent debug logging to sessionStorage
(view in DevTools > Application > Session Storage > archipelago_boot_log)
- Logs: health check, onboarding state, routing decisions, 401 handling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Kiosk: show cursor when active (removed -nocursor from Xorg),
unclutter hides after 3s idle. X11 on VT7 for Ctrl+Alt+F1/F7 switching.
- Kiosk: keep getty@tty1 running so MOTD is accessible via Ctrl+Alt+F1
- Kiosk: disable Chromium password save overlay (--password-store=basic)
- Esc: don't navigate back from top-level pages (dashboard, login, kiosk)
to prevent dead-end at root redirect
- PWA: suppress install prompt in kiosk mode (/kiosk path)
- Gamepad: Enter in text fields moves focus to next element (submit button)
instead of submitting the form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- rpc-client: don't redirect to /login on 401 during onboarding flow,
which caused session expired kicks on fresh installs
- style.css: add translateZ(0) + isolation:isolate to glass-card,
glass-strong, path-option-card to fix Chromium compositor bug where
backdrop-filter + animated fixed overlays cause black rectangles
- App.vue: pause background animations when tab hidden, force
compositor layer rebuild on tab return to prevent stale renders
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All app images now pull from 80.71.235.15:3000/archipelago/
instead of Docker Hub / ghcr.io. Insecure registry config
baked into ISO for fresh installs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Dashboard.vue: move DashboardMobileNav outside <main> so position:fixed
isn't broken by will-change:transform on the perspective container
- Add container-specs.sh and reconcile-containers.sh utility scripts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- F29-F32: Split 4 views (Marketplace 1293→505, Server 1132→486, Home 1059→394, AppDetails 1036→386)
- F20: Add aria-current="page" to Dashboard nav links
- F21: Add 150ms search debounce in Marketplace and Apps views
- F22: Reduce backdrop-filter blur to 8px on mobile for GPU performance
- F23: Track and clear WebSocket connect check interval in all paths
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- S10: Add warnings to silent health check failures in deploy scripts
- S11: Add trap cleanup for temp dirs in deploy and tailscale scripts
- S12: Quote 20+ critical unquoted variables across deploy scripts
- S13: Extract hardcoded IPs to deploy-config-defaults.sh
- S15: Add --memory=256m to UI container runs
- F16: Remove in-memory JWT, use cookie-only auth in filebrowser client
- F17: Add meta tag fallback for CSRF token in RPC client
- F19: Track and clear setTimeout in AppSession on unmount
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- F4: Fetch fresh server state after WebSocket reconnect
- F5: Guard message polling timer with auth check, stop on logout
- F6: Remove NIP-07 listener in appLauncher close()
- F7: Initialize audio player once to prevent listener stacking
- S3: Pin all container images to specific versions, create image-versions.sh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- F1: Guard connectWebSocket against concurrent calls with isWsConnecting flag
- F2: Serialize mesh send operations with sendQueue to prevent fetchMessages races
- F3: Add global Vue error handler with toast notification
- S1: Replace sudo podman with podman across all scripts (rootless Podman)
- S2: Add health-cmd to all 40 container run commands in first-boot-containers.sh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AppDetails.vue now checks Bitcoin sync progress for LND, ElectrumX,
BTCPay, and Mempool. Shows orange warning banner with sync progress
bar and block height when Bitcoin is still syncing. Users see clear
feedback instead of broken wallet connect pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
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>
- 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>
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>
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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
- "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>
- 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>
- 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>
- 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>