16 KiB
MASTER PLAN
Archipelago project task tracking and roadmap.
BETA FREEZE ACTIVE (2026-03-18) — No new features. Fix bugs, harden security, test everything. Pipeline: Feature Testing → User Testing → Beta Live Progress:
docs/BETA-PROGRESS.md| Acceptance:docs/BETA-RELEASE-CHECKLIST.md
Roadmap
Phase 1: Feature Testing (internal) — CURRENT
| ID | Title | Priority | Status | Dependencies |
|---|---|---|---|---|
| FEATURE-4 | Onboarding loading screen with progress | P1 | IN PROGRESS | - |
| TASK-9 | Full feature testing sweep | P1 | PLANNED | - |
| TASK-10 | ISO build verification + multi-hardware test | P1 | PLANNED | - |
| TASK-12 | Beta telemetry — reporter + toggle + collector POST | P1 | IN PROGRESS | - |
| TASK-39 | Finish .198 rootless container migration | P1 | PLANNED | TASK-11 |
| TASK-42 | LUKS2 full-partition encryption for /var/lib/archipelago/ | P1 | PLANNED | TASK-10 |
| BUG-44 | App iframe shows blank/broken when container is starting or crashed | P2 | PLANNED | - |
| TASK-45 | Deploy script: auto-chown data dirs after rootful→rootless migration | P2 | PLANNED | - |
Phase 2: User Testing (controlled, real hardware)
| ID | Title | Priority | Status | Dependencies |
|---|---|---|---|---|
| TASK-13 | Recruit 3-5 test users, distribute ISOs | P1 | NOT STARTED | Phase 1 complete |
| TASK-14 | Monitor telemetry, triage + fix user-reported issues | P1 | NOT STARTED | TASK-12, TASK-13 |
| TASK-15 | Rebuild ISO with fixes, re-verify | P1 | NOT STARTED | TASK-14 |
Phase 3: Beta Live (public)
| ID | Title | Priority | Status | Dependencies |
|---|---|---|---|---|
| TASK-16 | Final ISO build + release notes + distribution | P1 | NOT STARTED | Phase 2 complete |
Post-Beta (FROZEN — do not start)
| ID | Title | Priority | Status | Dependencies |
|---|---|---|---|---|
| TASK-2 | Roll incoming-tx into deploy & ISO | P2 | DEFERRED | - |
| INQUIRY-5 | Offline balance check via mesh relay | P2 | DEFERRED | - |
| FEATURE-6 | Watch-only wallet architecture | P1 | DEFERRED | - |
| TASK-7 | Mesh Bitcoin security hardening | P1 | DEFERRED | FEATURE-6 |
| FEATURE-43 | P2P encrypted voice/video calling (WebRTC over federation) | P1 | DEFERRED | - |
Active Work
FEATURE-4: Onboarding loading screen with progress (IN PROGRESS)
Priority: P1 — High Status: IN PROGRESS (2026-03-17)
Users hit the onboarding screen before the backend is ready, resulting in "Server is still starting up" errors that block identity creation. The onboarding flow should not begin until the server is fully operational.
Solution: Show the existing screensaver as a loading/boot screen with server startup progress. Swap the inner logo for animated pixel art icons (smiley face, Bitcoin logo, etc.) that cycle while services come online. Show progress indicators for each backend service (identity store, container runtime, LND, etc.). Only transition to onboarding once /health returns ready.
Key considerations:
- Reuse the existing screensaver component as the boot screen
- Animated pixel art icons rotate in the center (smiley, BTC, lightning bolt, etc.)
- Progress bar or status checklist showing which services are ready
- Poll
/healthendpoint for service readiness - Smooth transition from boot screen → onboarding once all critical services are up
- First-boot vs normal boot: first boot shows onboarding after, normal boot goes to dashboard
Key files:
neode-ui/src/views/Onboarding.vue— current onboarding flowneode-ui/src/components/Screensaver.vue— existing screensaver to repurposecore/archipelago/src/api/rpc/mod.rs— health endpointcore/archipelago/src/server.rs— startup sequence and service initialization
Tasks:
- Investigate current health endpoint — what services does it check, what's missing
- Design boot screen component: screensaver background + animated pixel icons + progress
- Create pixel art icon set (smiley, BTC, lightning, shield, etc.) as SVG/CSS animations
- Implement service readiness polling (health check with granular service status)
- Add backend support for granular startup progress (which services are ready)
- Build boot screen component with smooth transition to onboarding/dashboard
- Handle edge cases: very slow starts, partial service failures, timeout fallback
- Test on fresh ISO install (first-boot scenario)
TASK-9: Full app testing matrix on fresh install (PLANNED)
Priority: P1 — High Status: PLANNED (2026-03-18)
Run through the complete docs/BETA-RELEASE-CHECKLIST.md app matrix on a fresh ISO install. Every app: install, launch, UI loads, uninstall. Every dependency chain: correct errors when deps missing.
TASK-10: ISO build verification + multi-hardware test (PLANNED)
Priority: P1 — High Status: PLANNED (2026-03-18)
Build a fresh ISO, install on at least 2 different hardware configurations, verify full onboarding flow, app installs, and multi-day uptime.
TASK-17: Alpha version tags + rollback strategy (PLANNED)
Priority: P2 — Medium Status: PLANNED (2026-03-18)
Tag every significant alpha version with git tags for easy rollback. Each tag should correspond to a deployable state. Maintain a version log so any alpha can be rebuilt and deployed.
Tasks:
- Tag current state as
v1.2.0-alpha.1(pre-rootless-podman) - Establish naming convention:
v{major}.{minor}.{patch}-alpha.{build} - Tag after rootless podman migration:
v1.2.0-alpha.2 - Document rollback procedure (git checkout tag + deploy)
- Add version tag step to deploy script (auto-tag on successful deploy)
- Update CHANGELOG.md with each alpha milestone
TASK-42: LUKS2 full-partition encryption for /var/lib/archipelago/ (PLANNED)
Priority: P1 — High Status: PLANNED (2026-03-19)
Encrypt all Archipelago app data at rest using LUKS2 full-partition encryption. Protects Bitcoin wallet data, LND macaroons, FileBrowser files, Vaultwarden vault, secrets, and everything else from physical disk seizure. Seamless UX — user never interacts with encryption directly.
Design:
- LUKS2 partition for
/var/lib/archipelago/created during ISO install - Cipher: AES-256-XTS (hardware AES-NI on x86_64, ChaCha20 fallback on ARM without AES-NI)
- Key derived from setup password via Argon2id + hardware salt (
/sys/class/dmi/id/product_uuid) - Key file stored at
/root/.luks-archipelago.key(root:600, on boot partition) - Auto-unlock via
/etc/crypttabon every boot — no passphrase prompt - Password change in Settings re-derives key and rotates LUKS keyslot
Threat model:
- Disk removed from machine = fully encrypted, unreadable
- Running machine with login = transparent (same as today)
- Forgot password = cannot decrypt (correct sovereign behavior)
Tasks:
- ISO installer: create LUKS2 partition, format + mount at
/var/lib/archipelago/ - First-boot: derive LUKS key from setup password via Argon2id + hardware salt
- Store key file at
/root/.luks-archipelago.keywith 600 perms - Configure
/etc/crypttabfor auto-unlock at boot - Settings password change: re-derive LUKS key, add new keyslot, remove old
- Detect AES-NI availability, fall back to ChaCha20 on ARM without it
- Test: fresh install, reboot survives, power-cycle survives, password change works
- Test: disk removed from machine is unreadable
- Update
BUILD-GUIDE.mdandimage-recipe/build-auto-installer-iso.sh
Key files:
image-recipe/build-auto-installer-iso.sh— partition creationscripts/first-boot-containers.sh— runs after LUKS mountcore/archipelago/src/api/rpc/system.rs— password change handlercore/archipelago/src/server.rs— startup checks
BUG-44: App iframe shows blank/broken when container is starting or crashed (PLANNED)
Priority: P2 — Medium Status: PLANNED (2026-03-21)
When an app container is still starting up or has crashed, the iframe overlay shows a blank/broken page with no feedback. Should show contextual loading states:
- Starting: skeleton loader or "App is starting up..." with spinner
- Crashed: "App has stopped" with restart button and link to logs
- Port not ready: "Waiting for app to become available..." with timeout warning
- X-Frame-Options blocked: Detect and open in new tab automatically
Key files:
neode-ui/src/views/AppSession.vue— iframe containerneode-ui/src/stores/appLauncher.ts— app launch stateneode-ui/src/api/container-client.ts— container status checks
TASK-45: Deploy script: auto-chown data dirs after rootful→rootless migration (PLANNED)
Priority: P2 — Medium Status: PLANNED (2026-03-21)
When deploy-tailscale.sh migrates from rootful to rootless Podman, all files in /var/lib/archipelago/ created by the old root-running backend are owned by root:root. The new backend runs as archipelago user and can't read them (node-key.pem, credentials, sessions, identity, etc.). Deploy script must auto-detect and fix ownership after migration.
Also fix:
/run/user/1000/crunownership (left as root from rootful container creation)- Container recreation needs
--cap-add NET_BIND_SERVICEfor apps binding port 80 (nextcloud) - Container recreation needs config volume mounts for apps writing to
/etc/(searxng) - Frontend should be copied from .228, not built locally (prevents build mismatches)
Key files:
scripts/deploy-tailscale.sh— Step 14 (UID mapping) and Step 22 (container creation)scripts/first-boot-containers.sh— container creation reference
Post-Beta (FROZEN)
These tasks are deferred until after beta ships. Do not start.
- INQUIRY-5: Offline balance check via mesh relay
- FEATURE-6: Watch-only wallet architecture
- TASK-7: Mesh Bitcoin security hardening
- TASK-2: Roll incoming-tx into deploy & ISO
- FEATURE-43: P2P encrypted voice/video calling (WebRTC over federation)
FEATURE-43: P2P encrypted voice/video calling — WebRTC over federation (DEFERRED)
Priority: P1 — High Status: DEFERRED (post-beta)
Self-sovereign encrypted voice and video calling between Archipelago peers. Zero new containers or dependencies — uses browser-native WebRTC with signaling over the existing federation WebSocket. Integrates directly into peer tabs/chat.
Security & Privacy:
- All media encrypted via DTLS/SRTP (WebRTC mandatory encryption — no opt-out)
- Signaling (SDP offers, ICE candidates) transmitted over existing federation WebSocket through Tor
- ICE candidate filtering: strip local/public IP candidates in Tor-relay mode
- No central server, no metadata leakage — true P2P between browsers
- Two privacy modes:
- LAN Direct: <50ms latency, IPs visible to peer (trusted same-network peers)
- Tor Relay: 300-800ms latency, full anonymity via coturn TURN server on .onion
Architecture:
- Signaling reuses existing federation WebSocket — new message types:
call-offer,call-answer,call-ice,call-hangup,call-reject,call-busy - Browser
getUserMedia()+RTCPeerConnection— no backend media processing - Opus codec for voice (~30kbps, handles Tor latency well)
- VP8/VP9 adaptive bitrate for video (720p on LAN, degrades gracefully)
- Optional
coturncontainer (~10MB RAM) for Tor-relay media mode only
UX:
- Voice and video call buttons in peer chat (federation contacts)
- Incoming call: glass modal slides up with peer name + avatar, accept/decline
- In-call: floating glass PIP overlay — navigate while talking
- One-tap mute, camera toggle, speaker toggle, hangup
- Call quality indicator (green/yellow/red based on RTT)
- Ring timeout (30s) → missed call notification
- Call history in peer chat thread
Tasks:
CallService.ts— WebRTC wrapper (offer/answer, ICE management, stream handling, codec negotiation)- Federation signaling protocol — new message types over existing WS (
call-offer,call-answer,call-ice,call-hangup) - Rust backend — relay call signaling messages between federation peers (pass-through, no media processing)
- ICE candidate filtering — strip public IPs in privacy mode, force relay-only
CallOverlay.vue— incoming call modal (glass aesthetic, ring animation, accept/decline)CallPIP.vue— floating picture-in-picture during active call (draggable, minimize/expand)CallControls.vue— mute, camera toggle, speaker, hangup, privacy mode switch- Voice-only mode — Opus codec, bandwidth-optimized, Tor-friendly
- Video mode — VP8/VP9 adaptive bitrate, resolution scaling based on connection quality
- Optional
coturncontainer manifest — TURN relay for Tor-routed media - Call quality monitoring — RTT measurement, packet loss detection, quality indicator
- Call history — persist in peer chat thread, missed call notifications
- Multi-peer consideration — design for 1:1 first, extensible to group calls later
- Test: LAN direct call (voice + video)
- Test: Tor relay call (voice — verify latency is acceptable)
- Test: call during active chat, call while navigating other views
- Test: network interruption recovery (ICE restart)
Key files (new):
neode-ui/src/services/CallService.ts— WebRTC engineneode-ui/src/components/call/CallOverlay.vue— incoming call UIneode-ui/src/components/call/CallPIP.vue— in-call floating overlayneode-ui/src/components/call/CallControls.vue— call action buttonsapps/coturn/manifest.yml— optional TURN relay container
Key files (modified):
neode-ui/src/views/Federation.vue— call buttons in peer chatcore/archipelago/src/api/rpc/federation.rs— call signaling relayneode-ui/src/stores/federation.ts— call state management
Completed
| ID | Title | Completed |
|---|---|---|
| TASK-11 | Rootless podman migration (.228 — 30 containers) | 2026-03-18 |
| TASK-32 | Integrate boot loader into deploy + build + production | 2026-03-17 |
| TASK-34 | Pentest findings remediation plan | 2026-03-18 |
| TASK-26 | Rename fedimintd to "Fedimint Guardian" + icon | 2026-03-18 |
| TASK-27 | Add tab-launch icon to apps that open in tabs | 2026-03-18 |
| TASK-28 | Sort installed apps to end of marketplace | 2026-03-18 |
| TASK-29 | Fix mesh mobile: remove title/flash/peers header, fix gutters | 2026-03-18 |
| TASK-30 | On-Chain as first tab in receive Bitcoin modals | 2026-03-18 |
| TASK-35 | Federation node names (show name not DID, hover for key) | 2026-03-18 |
| TASK-36 | Cleaner iframe error screen with remediation | 2026-03-18 |
| BUG-1 | Random logout / CSRF mismatch — HMAC-derived tokens | 2026-03-18 |
| TASK-8 | Security hardening — 12/12 pentest findings fixed | 2026-03-18 |
| BUG-20 | ElectrumX index estimate string ~55→~130 GB | 2026-03-18 |
| BUG-37 | App card Start/Launch flicker during container scan | 2026-03-18 |
| BUG-40 | Uninstall dialog not full-screen modal | 2026-03-18 |
| BUG-41 | Uninstall loader ends but app card persists | 2026-03-18 |
| BUG-33 | CPU load alert threshold too low (8 = 2x cores) | 2026-03-18 |
| TASK-31 | Sticky nav header (Apps page) | 2026-03-18 |
| TASK-38 | Blockchain sync info on homepage System card | 2026-03-18 |
| TASK-17 | Alpha version tags + deploy auto-tag | 2026-03-18 |
| BUG-3 | IndeedHub WebSocket spam — removed dead nostrConfig | 2026-03-18 |