fix: add 6 missing apps to first-boot and fix penpot icon path

Added searxng, onlyoffice, filebrowser, nginx-proxy-manager, portainer,
and tailscale to first-boot-containers.sh so fresh ISO installs have all
marketplace apps ready. Fixed penpot icon path in Marketplace.vue to use
the correct app-icons directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian 2026-03-09 00:18:28 +00:00
parent e8a0e1af19
commit c45de13752
34 changed files with 428 additions and 107 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
demo/content/music/SMRI.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,102 +1,337 @@
# Alpha Release Hardening Plan — Overnight Automation
# 2-Year Production Roadmap — Archipelago v1.0
**Goal**: Make Archipelago flawless for alpha testers installing on their own hardware.
**Priority**: Onboarding perfection > App install reliability > AIUI hardening > UI polish
**Rule**: No new features. No design changes (except smoothing transitions). Harden everything.
**Goal**: Take Archipelago from developer preview to a flawless, mass-market Bitcoin Node OS. Every app installs perfectly, every service runs reliably, every interaction is polished and intuitive — on desktop and mobile.
**Timeline**: March 2026 → March 2028 (8 quarters)
**Method**: Quarterly phases, each building on the last. Deploy and verify after every task.
---
## Phase 1: Onboarding Flow (Critical Path)
## Q1 2026 (MarMay): Foundation Hardening
- [x] **OB-001** — fix(onboarding): convert "Choose Your Path" screen (`neode-ui/src/views/OnboardingPath.vue`) from a selection screen to an informative screen. Keep the exact same 6 cards (Self Sovereignty, Community Commerce, Sovereign Projects, Data Transmitter, Hoster, Sovereign AI) with their current design, but remove the toggle/selection behavior. Remove the `toggleOption()` click handler and `--selected` class binding. Change heading from "Choose Your Path" to "Your Node, Your Possibilities". Change subtitle to "Archipelago gives you the tools to build your sovereign digital life. All of these capabilities are available from your dashboard." Remove "Skip" button — only keep "Continue" which navigates to `/onboarding/did`. The cards should be read-only informational cards, not buttons. Deploy and verify.
### Phase 1A: App Store Reliability — Every App Installs Without Fail
- [x] **OB-002** — fix(onboarding): harden the "Choose Your Setup" screen (`neode-ui/src/views/OnboardingOptions.vue`) — this is the Fresh Start / Restore / Connect screen. For alpha, only "Fresh Start" should work — gray out and disable "Restore Backup" and "Connect Existing" with a "(Coming Soon)" label. Make "Fresh Start" auto-selected on mount so users don't have to click before pressing Continue. Ensure `completeOnboarding()` is called reliably (currently it might fail silently and user gets stuck). Deploy and verify.
- [x] **APP-101** — fix(marketplace): audit and fix all 24 marketplace app install flows. For each app in `getCuratedAppList()` in `neode-ui/src/views/Marketplace.vue` (bitcoin-knots, electrs, btcpay-server, lnd, mempool, homeassistant, grafana, searxng, ollama, onlyoffice, penpot, nextcloud, vaultwarden, jellyfin, photoprism, immich, filebrowser, nginx-proxy-manager, portainer, uptime-kuma, tailscale, fedimint, indeedhub), verify each one: (1) marketplace card renders correctly with icon, (2) clicking Install triggers `package.install` RPC, (3) container pulls and creates successfully, (4) container starts on the correct ports per `apps/PORTS.md`, (5) status shows "Running" in My Apps. Fix any broken apps. Deploy with `./scripts/deploy-to-target.sh --live`. Test each app at http://192.168.1.228.
- [x] **OB-003** — fix(onboarding): harden the DID retrieval step (`neode-ui/src/views/OnboardingDid.vue`). If the server is not reachable (502/503/timeout), show a clear message "Connecting to your server..." with a retry button instead of the fallback "did:key:z6Mk... (connect to server)" text. Auto-fetch the DID on mount (don't wait for button click — the "Retrieve DID" button adds friction). If fetch succeeds, auto-advance after 2 seconds with a "DID retrieved, continuing..." message. Keep Skip button.
- [ ] **APP-102** — fix(apps): ensure iframe vs new-tab behavior is correct for all apps. In `neode-ui/src/stores/appLauncher.ts`, verify `mustOpenInNewTab()` includes all apps that set `X-Frame-Options: DENY/SAMEORIGIN`. Currently covers BTCPay (23000), Home Assistant (8123), Nextcloud (8085), Immich (2283). Test each running app by clicking "Open" in AppDetails.vue — iframe apps must load inside the overlay, new-tab apps must open in a fresh browser tab. If any app fails to load in iframe, either fix the nginx proxy to strip X-Frame-Options or add it to `mustOpenInNewTab()`. Deploy and verify each app.
- [x] **OB-004** — fix(onboarding): harden the Backup step (`neode-ui/src/views/OnboardingBackup.vue`). Ensure the `rpcClient.createBackup()` call works on a fresh install. If it fails, show a helpful error message. Make the download work on mobile (some browsers block `a.click()` programmatic downloads). Test the full backup/download flow. Deploy and verify.
- [ ] **APP-103** — fix(apps): verify all PORT_TO_PROXY mappings in appLauncher.ts match nginx config. Cross-reference every entry in `PORT_TO_PROXY` in `neode-ui/src/stores/appLauncher.ts` with the actual nginx location blocks in `image-recipe/configs/nginx-archipelago.conf` and `image-recipe/configs/snippets/archipelago-https-app-proxies.conf`. Any missing nginx proxy blocks must be added. Any port mismatches must be corrected. Deploy nginx config and verify each app loads via its proxy path.
- [x] **OB-005** — fix(onboarding): harden the Verify step (`neode-ui/src/views/OnboardingVerify.vue`). The `signChallenge()` call must work on a fresh server with a new identity. If it fails, allow user to retry or skip gracefully. Ensure `completeOnboarding()` is called on both proceed and skip paths (already done, but verify). Deploy and verify.
- [ ] **APP-104** — fix(deploy): ensure first-boot-containers.sh creates every marketplace app container. Compare the apps listed in `scripts/first-boot-containers.sh` with `scripts/deploy-to-target.sh`. Any app that deploy creates but first-boot doesn't must be added to first-boot. This ensures fresh ISO installs have all containers ready.
- [x] **OB-006** — fix(onboarding): verify the complete onboarding flow end-to-end. Clear onboarding state on server (`rpcClient.resetOnboarding()` if it exists, or clear localStorage `neode_onboarding_complete`). Walk through every step: Intro → Path (informative) → DID → Backup → Verify → Done → Login. Each transition must be smooth with the 3D depth effect. No JS errors in console. Deploy and verify.
- [ ] **APP-105** — fix(backend): verify get_app_config() handles all 24 apps. In `core/archipelago/src/api/rpc/package.rs`, check `get_app_config()` returns correct ports, volumes, env vars, and custom args for every marketplace app. Any app missing its config will fail to install. Add missing configs.
## Phase 2: First Login & Password Setup
- [ ] **APP-106** — fix(backend): verify get_app_metadata() for all 24 apps. In `core/archipelago/src/container/docker_packages.rs`, check `get_app_metadata()` returns correct title, description, icon path, and repo URL for every marketplace app. Fix missing or incorrect entries.
- [x] **LOGIN-001** — fix(login): verify the login flow on a fresh install. The first user must be able to set a password (setup mode). After setting password, redirect to login. After login, redirect to dashboard. Test: clear all state, visit http://192.168.1.228, complete onboarding, set password, login. The startup progress bar must appear only when the server is genuinely starting (not on normal page loads). Deploy and verify.
### Phase 1B: App Dependencies — Bitcoin, Lightning, Fedimint Chains
- [x] **LOGIN-002** — fix(login): harden the RootRedirect component (`neode-ui/src/views/RootRedirect.vue`). On a fresh install, root `/` must redirect to `/onboarding/intro`. After onboarding, root must redirect to `/login`. After login, must redirect to `/dashboard`. Test all three states. No infinite redirect loops. Deploy and verify.
- [ ] **DEP-101** — fix(backend): implement robust dependency checking for all apps. In `core/archipelago/src/api/rpc/package.rs`, ensure dependency checks work: Electrs requires Bitcoin Knots running, LND requires Bitcoin Knots running, BTCPay requires LND running, Mempool requires Bitcoin Knots + Electrs. When installing an app with unmet dependencies, the UI should either auto-install dependencies or show a clear message: "Bitcoin Knots must be installed and running first." Deploy and verify by trying to install Electrs without Bitcoin.
## Phase 3: App Installation Reliability
- [ ] **DEP-102** — fix(ui): show dependency status in MarketplaceAppDetails.vue. When viewing an app that has dependencies, show a "Requirements" section listing each dependency with a green checkmark (installed & running), yellow warning (installed but stopped), or red X (not installed). Add an "Install All Requirements" button that queues dependency installations in order. This lives in `neode-ui/src/views/MarketplaceAppDetails.vue`.
- [x] **APP-001** — fix(apps): verify that the Marketplace loads all available apps from manifests in `apps/*/manifest.yml`. Each app should have: name, description, icon, version. Test the marketplace page loads without errors. Deploy and verify.
- [ ] **DEP-103** — feat(fedimint): integrate Fedimint Guardian + Gateway as paired services. Fedimint currently runs as a single container (fedimintd). Add Fedimint Gateway as a companion service that runs alongside the Guardian. In `scripts/deploy-to-target.sh`, when creating fedimint, also create `fedimint-gateway` container using `fedimint/gatewayd` image. Configure the gateway to auto-connect to the guardian. In the Marketplace, show Fedimint as one app that runs both services. The UI should show both Guardian and Gateway status.
- [x] **APP-002** — fix(apps): test installing Bitcoin Knots (the most critical app). The install flow is: click Install → pull image → create container → start → show running state. Verify each step works. If image pull fails (no internet), show a clear error. If container fails to start, show logs. After successful install, the app should appear in "My Apps" with correct status. Deploy and verify.
- [ ] **DEP-104** — feat(fedimint): auto-configure Fedimint Gateway to use LND. The Fedimint Gateway needs a Lightning backend. When both LND and Fedimint are installed, auto-configure the gateway to use LND's gRPC endpoint. In `core/archipelago/src/api/rpc/package.rs`, add Fedimint Gateway config that reads LND's tls.cert and admin.macaroon from the LND data volume. The user should only need to open lightning channels — everything else should be automatic.
- [x] **APP-003** — fix(apps): test installing at least 3 more apps from the marketplace (e.g., Mempool, LND, Electrs). Verify each installs and shows correct status. If any app fails, fix the manifest or backend logic. Ensure app dependencies are resolved (e.g., LND depends on Bitcoin). Deploy and verify.
- [ ] **DEP-105** — feat(ui): lightning channel management interface. Create `neode-ui/src/views/apps/LightningChannels.vue` accessible from the LND app detail page. Show: (1) list of open channels with capacity bars, (2) "Open Channel" button with peer URI input and amount, (3) channel status (pending open/close, active, inactive), (4) total inbound/outbound liquidity summary. Use existing RPC to call LND's REST API through the backend proxy. This is critical for Fedimint Gateway to be useful.
- [x] **APP-004** — fix(apps): verify app uninstall works cleanly. Install an app, verify it runs, uninstall it, verify it's removed from both the UI and the container runtime (`podman ps -a`). No orphaned containers or data. Deploy and verify.
### Phase 1C: Animation & UI Polish
- [x] **APP-005** — fix(apps): verify app detail pages load correctly. Click into an installed app → should show: status, version, logs (if available), open button (if applicable). No JS errors, no blank pages. The iframe for web-UI apps must load with correct port. Deploy and verify.
- [ ] **ANIM-101** — fix(css): audit and improve all transition animations in style.css. In `neode-ui/src/style.css`, review every `transition` property. Standardize: (1) hover lifts use `transform: translateY(-2px)` with `transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)`, (2) active presses use `translateY(1px)`, (3) color transitions use `transition: color 0.2s ease, background-color 0.2s ease`, (4) modal/overlay entrances use `transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)`. Replace all `transition: all 0.3s ease` with specific properties to avoid animating layout properties. Deploy and verify animations feel smooth.
## Phase 4: AIUI Chat Hardening
- [ ] **ANIM-102** — fix(ui): add smooth page transitions between routes. In `neode-ui/src/views/Dashboard.vue`, wrap `<RouterView>` in a `<Transition>` component with `name="page"`. In `style.css`, add: `.page-enter-active, .page-leave-active { transition: opacity 0.2s ease, transform 0.2s ease; }` `.page-enter-from { opacity: 0; transform: translateY(8px); }` `.page-leave-to { opacity: 0; }`. This gives every page navigation a subtle fade-up entrance. Deploy and verify navigation feels smooth.
- [x] **AIUI-001** — fix(aiui): verify the AIUI chat loads in the dashboard. Navigate to `/dashboard/chat`. The iframe must load AIUI from `/aiui/`. Check: no 404s, no CORS errors, no blank white screen. The context broker must be initialized. Deploy and verify.
- [ ] **ANIM-103** — fix(ui): add staggered entrance animations for card grids. In views that display card grids (Apps.vue, Marketplace.vue, Home.vue, Web5.vue), add staggered entrance animations so cards appear one after another with a 50ms delay. Use CSS `animation-delay` with `nth-child()` or Vue's `<TransitionGroup>`. The effect should be subtle — cards fade in and slide up slightly. Deploy and verify.
- [x] **AIUI-002** — fix(aiui): verify the Claude proxy is running and responds. Test: `curl -X POST http://192.168.1.228/aiui/api/claude/v1/messages -H 'Content-Type: application/json' -d '{"model":"haiku","messages":[{"role":"user","content":"hello"}],"stream":false}'` (with session cookie). Should get a valid response or proper auth error. If proxy is down, restart `claude-proxy` service. Deploy and verify.
- [ ] **ANIM-104** — fix(ui): smooth loading state transitions. In all views that have loading states, ensure the transition from loading to loaded is animated — not an instant swap. Use Vue's `<Transition>` with `mode="out-in"` around loading/content states. The loading spinner should fade out as the content fades in. Deploy and verify on Apps, Marketplace, Server, and Home views.
- [x] **AIUI-003** — fix(aiui): verify the API key switcher works. Open AIUI settings → Chat tab → enable "Use my own API key" → paste the test key `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` → send a message → verify response comes back. Then disable the toggle → verify it falls back to server OAuth. Deploy and verify.
- [ ] **ANIM-105** — fix(ui): polish the app launcher overlay animation. In `neode-ui/src/components/AppLauncherOverlay.vue`, ensure the overlay slides up smoothly when opening an app. Add a subtle backdrop blur transition. The iframe should have a loading indicator that fades out when the app loads. The close animation should slide down. Use `will-change: transform` for GPU acceleration. Deploy and verify.
- [x] **AIUI-004** — fix(aiui): verify that the context broker surfaces node data to AIUI. Enable all AI permissions in Settings → AI Data Access. Then ask AIUI "what apps are installed?" or "what's my server status?". The response should include real data from the node (via postMessage → contextBroker → stores/RPC). If it doesn't, debug the postMessage flow. Deploy and verify.
### Phase 1D: Mobile Responsiveness
- [x] **AIUI-005** — fix(aiui): verify that message send, reply, and regenerate all work without the "empty content" API error. Send multiple messages in a row. Use reply on a specific message. Use regenerate. None should produce "messages.N: user messages must have non-empty content" errors. Deploy and verify.
- [ ] **MOB-101** — fix(ui): audit and fix all views at 375px (iPhone SE) width. Test every view at 375px: Login, Dashboard sidebar, Home, Apps, Marketplace, AppDetails, MarketplaceAppDetails, Settings, Web5, Cloud, Server, Chat. Fix: horizontal overflow, overlapping elements, text truncation, buttons too small to tap (min 44px touch target), broken grid layouts. Add or fix responsive Tailwind classes in `style.css`. Deploy and verify.
## Phase 5: Dashboard & UI Polish
- [ ] **MOB-102** — fix(ui): optimize sidebar navigation for mobile. The Dashboard sidebar should collapse to a bottom tab bar on mobile (< 768px). Show icons only with labels below. The mode switcher should be accessible from Settings on mobile. Ensure the sidebar doesn't overlap content on mobile. Deploy and verify.
- [x] **UI-001** — fix(ui): verify all dashboard nav items work: Home, My Apps, Marketplace, Cloud, Server, Web5, Settings, Chat. Each must load without errors. No blank pages, no console errors. The sidebar navigation must highlight the active item. Deploy and verify.
- [x] **UI-002** — fix(ui): verify the Home dashboard shows correct data: server status (online/offline), uptime, disk usage, memory, CPU. If metrics RPC fails, show placeholder data with "Connecting..." state instead of errors. Deploy and verify.
- [x] **UI-003** — fix(ui): verify the Server page loads and shows system info. Test all sections: system overview, services list, network info. No JS errors. Deploy and verify.
- [x] **UI-004** — fix(ui): verify the Settings page loads all sections: General, Security (password change), AI Data Access, Tor, About. No JS errors. The AI Data Access toggles must persist between page loads. Deploy and verify.
- [x] **UI-005** — fix(ui): test WebSocket connection stability. After login, the WebSocket at `/ws` should connect and stay connected. If it disconnects, verify auto-reconnect works. Check: no repeated "WebSocket disconnected" errors in console. Deploy and verify.
- [x] **UI-006** — fix(ui): ensure all page transitions are smooth. Navigate between all dashboard pages. The 3D depth transitions should be fluid without flicker or layout jumps. If any transition stutters, optimize by adding `will-change` or reducing transition complexity. Deploy and verify.
## Phase 5b: AIUI Security Hardening (from research audit)
- [x] **SEC-001** — fix(aiui): add confirmation dialog for AIUI app installs. In `neode-ui/src/services/contextBroker.ts`, the `install-app` action currently fires without user confirmation. Change it to emit a custom event (`window.dispatchEvent(new CustomEvent('aiui:install-request', { detail: { appId, version, url } }))`) that the Dashboard UI can intercept with a confirmation modal. Only proceed with `appStore.installPackage()` after user confirms. This prevents AIUI from silently installing apps.
- [x] **SEC-002** — fix(aiui): add file path whitelist to AIUI file access. In `neode-ui/src/services/contextBroker.ts`, the `read-file` action currently allows reading any path. Add a whitelist of allowed directories (e.g., `/var/lib/archipelago/`, `/var/log/`) and reject paths containing sensitive patterns (`id_rsa`, `private`, `secret`, `password`, `seed`, `.env`, `wallet`). This prevents AIUI from exfiltrating secrets.
- [x] **SEC-003** — fix(aiui): add log redaction for container logs. In the context broker's log handler, redact sensitive patterns from container logs before sending to AIUI: RPC passwords, private keys (hex strings > 32 chars), API tokens, and macaroon values.
- [x] **SEC-004** — fix(auth): add `Secure` flag to session cookie in production. In `core/archipelago/src/api/rpc/mod.rs`, add `; Secure` to the `Set-Cookie` header when `dev_mode` is false. This prevents the session cookie from being transmitted over plain HTTP in production.
## Phase 6: Alpha ISO Build
- [x] **ISO-001** — fix(iso): sync all current changes to the dev server. Run full deploy: `./scripts/deploy-to-target.sh --live`. Verify everything works on http://192.168.1.228. Then SSH to the server and run the ISO build: `cd ~/archy/image-recipe && sudo DEV_SERVER=archipelago@localhost ./build-auto-installer-iso.sh`. The ISO must build successfully and be saved to `results/`. Report the ISO path and size.
- [x] **ISO-002** — fix(iso): verify the ISO image configs include all latest changes. Check that `image-recipe/configs/` has up-to-date: `archipelago.service`, `nginx-archipelago.conf`. If they differ from the live server, update them. The ISO must produce a bootable system identical to the current live server.
- [ ] **MOB-103** — fix(ui): optimize app launcher overlay for mobile. The app iframe launcher should be full-screen on mobile with a sticky top bar (app title + close + open-in-new-tab). On desktop, maintain the current overlay style. Deploy and verify apps are usable on mobile.
---
## Post-Completion Verification
## Q2 2026 (JunAug): Identity & Onboarding
After all tasks are done, run a full verification:
### Phase 2A: Multi-Identity System
- [ ] **ID-101** — feat(backend): implement identity manager with multiple DIDs. Create `core/archipelago/src/identity/mod.rs` with: (1) `IdentityManager` struct that stores multiple identities in `/var/lib/archipelago/identity/`, (2) each identity has an Ed25519 keypair, a DID, a display name, and a purpose tag (personal, business, anonymous), (3) the first identity is created during onboarding, (4) RPC endpoints: `identity.list`, `identity.create`, `identity.delete`, `identity.get`, `identity.set-default`. Store identities encrypted using the node's master key. Build on server and deploy.
- [ ] **ID-102** — feat(backend): implement identity signing service. Add `identity.sign` and `identity.verify` RPC endpoints. `identity.sign` takes a DID id and a message, returns a detached Ed25519 signature. `identity.verify` takes a DID, message, and signature, returns boolean. This enables apps to request signatures from the user's chosen identity. Build on server and deploy.
- [ ] **ID-103** — feat(ui): identity management view. Create a new "Identity" section in the Web5 view (replace the hidden `v-if="false"` DID section at line 429 of `Web5.vue`). Show: (1) list of all identities with name, DID (truncated), purpose badge, (2) "Create Identity" button that opens a modal with name + purpose selector, (3) each identity card has Copy DID, Set Default, Delete actions, (4) the default identity shows a star badge. Wire to the backend RPC endpoints from ID-101. Deploy and verify.
- [ ] **ID-104** — feat(ui): identity picker for service connections. Create a reusable `<IdentityPicker>` component that shows a dropdown of the user's identities with their names and truncated DIDs. When a service (like Indeehub) needs a DID, it calls this component to let the user choose which identity to use. The selected identity's DID and signing capability are then passed to the service.
- [ ] **ID-105** — feat(backend): Nostr identity bridge. Each identity can optionally have an associated Nostr keypair (secp256k1). Add `identity.create-nostr-key` RPC that generates a Nostr keypair linked to an identity. Add `identity.nostr-sign` for NIP-01 event signing. This bridges the DID world with Nostr. The user's Nostr pubkey is derivable from their identity. Build on server and deploy.
- [ ] **ID-106** — feat(apps): Indeehub identity integration. When opening Indeehub, pass the user's selected identity DID via the iframe URL or postMessage. Indeehub should recognize the user's sovereign identity without requiring account creation. Implement the postMessage protocol: parent sends `{ type: 'archipelago:identity', did: '...', signature: '...' }`, Indeehub responds with `{ type: 'archipelago:identity:ack' }`. Deploy and verify Indeehub recognizes the user.
### Phase 2B: Onboarding Flow Polish
- [ ] **ONB-101** — fix(ui): polish onboarding intro animation. In `neode-ui/src/views/OnboardingIntro.vue`, add a cinematic entrance: the Archipelago logo fades in with a subtle scale (0.95 → 1.0), followed by the tagline sliding up, then the "Get Started" button fading in. Total duration: 2 seconds. Use CSS keyframe animations. Deploy and verify.
- [ ] **ONB-102** — fix(ui): improve onboarding DID step UX. In `OnboardingDid.vue`, when the backend generates the DID, show a brief animation of key generation (spinning lock icon → checkmark). Display the DID in a styled card with a copy button. Explain in plain language: "This is your sovereign digital identity. It proves you are you, without any company in the middle." Deploy and verify.
- [ ] **ONB-103** — fix(ui): add identity purpose selection to onboarding. After DID creation in onboarding, add a step where the user names their first identity (default: "Personal") and optionally selects a purpose (Personal, Business, Anonymous). This feeds into the multi-identity system from ID-101. Deploy and verify.
- [ ] **ONB-104** — fix(ui): smooth transition between onboarding steps. Add a horizontal slide transition between onboarding steps — swiping left to advance, right to go back. Use `<Transition>` with `name="slide"` and direction-aware classes. Deploy and verify the flow feels like swiping through cards.
---
## Q3 2026 (SepNov): Network & Node Discovery
### Phase 3A: Node Overlay Network
- [ ] **NET-101** — feat(backend): implement node visibility signaling. Create `core/archipelago/src/network/overlay.rs` with: (1) a `NodeVisibility` enum (Hidden, Discoverable, Public), (2) RPC endpoints `network.set-visibility` and `network.get-visibility`, (3) when set to Discoverable, the node publishes a Nostr NIP-33 replaceable event (kind 30078, tag `d:archipelago-node`) with its onion address and public DID, (4) when set to Hidden, the event is deleted. This uses the existing Nostr discovery code in `core/archipelago/src/nostr_discovery.rs`. Build on server and deploy.
- [ ] **NET-102** — feat(backend): implement connection request protocol. Add RPC endpoints: `network.request-connection` (sends a connection request to a peer's onion address over Tor), `network.list-requests` (shows pending incoming requests), `network.accept-request` (adds peer to trusted list), `network.reject-request`. Connection requests are sent as encrypted Nostr DMs (NIP-04) containing the sender's DID and onion address. Build on server and deploy.
- [ ] **NET-103** — feat(ui): node visibility controls in Web5 view. In the Web5 view, add a "Node Visibility" card (replace or augment the existing Connected Nodes section). Show: (1) current visibility status (Hidden/Discoverable/Public), (2) toggle to change visibility, (3) when Discoverable, show the node's onion address, (4) warning: "Making your node discoverable lets other Archipelago users find and connect with you." Wire to NET-101 RPCs. Deploy and verify.
- [ ] **NET-104** — feat(ui): connection request management. In the Web5 view, add a "Connection Requests" tab to the Connected Nodes section. Show: (1) incoming requests with sender DID and timestamp, (2) Accept/Reject buttons, (3) notification badge on the Web5 sidebar icon when requests are pending. Wire to NET-102 RPCs. Deploy and verify.
- [ ] **NET-105** — feat(backend): implement peer health monitoring. Add a background task that periodically (every 5 minutes) checks if connected peers are reachable over Tor. Update peer status in the database. Send WebSocket events when peer status changes. The existing `rpcClient.checkPeerReachable()` in Web5.vue already calls this — ensure the backend implementation is robust with timeouts. Build on server and deploy.
### Phase 3B: Tor Services Management
- [ ] **TOR-101** — feat(backend): implement Tor hidden service management RPC. Create RPC endpoints: `tor.list-services` (returns all configured hidden services with their .onion addresses), `tor.create-service` (creates a new hidden service for a given local port), `tor.delete-service`, `tor.get-onion-address`. Read from `/var/lib/archipelago/tor/` directory structure. Currently Tor setup is hardcoded in deploy script — make it dynamic. Build on server and deploy.
- [ ] **TOR-102** — feat(ui): Tor services management in Settings or Web5. Add a "Tor Services" section showing: (1) list of all hidden services with their .onion addresses and what app they expose, (2) toggle to enable/disable Tor for each service, (3) "Broadcast my services over Tor" master toggle, (4) copy .onion address button for each service. Wire to TOR-101 RPCs. Deploy and verify.
- [ ] **TOR-103** — fix(deploy): make Tor hidden service creation dynamic. Refactor `scripts/deploy-to-target.sh` Tor section (lines 471-530) to read from a config file (`/var/lib/archipelago/tor/services.json`) instead of hardcoding services. When an app is installed that supports Tor, automatically add a hidden service entry. When uninstalled, remove it. Rebuild torrc from the config file and restart the Tor container. Deploy and verify.
- [ ] **TOR-104** — feat(backend): Tor-based content serving. When a peer accesses your node over Tor, serve only the content you've explicitly made available. Create `core/archipelago/src/network/content_server.rs` with: (1) a list of shared content items (files, streams), (2) access control per item (free, paid via ecash), (3) a lightweight HTTP handler that serves content to authenticated peers. This is the foundation for content streaming. Build on server and deploy.
---
## Q4 2026 (DecFeb 2027): Ecash & Content Economy
### Phase 4A: Ecash Integration
- [ ] **ECASH-101** — feat(backend): implement Cashu ecash wallet. Create `core/archipelago/src/wallet/ecash.rs` with: (1) Cashu wallet client that connects to the local Fedimint mint, (2) RPC endpoints: `wallet.ecash-balance`, `wallet.ecash-mint` (create ecash tokens from Lightning), `wallet.ecash-melt` (redeem ecash to Lightning), `wallet.ecash-send` (create ecash token for peer), `wallet.ecash-receive` (accept ecash token from peer). Use the Cashu protocol for interoperability. Build on server and deploy.
- [ ] **ECASH-102** — feat(ui): ecash wallet in Web5 view. Replace the dummy "Web5 Wallet" card in Web5.vue (lines 221-268) with a real ecash wallet UI. Show: (1) ecash balance in sats, (2) Mint button (Lightning → ecash), (3) Melt button (ecash → Lightning), (4) Send button (generates ecash token string), (5) Receive button (paste ecash token), (6) transaction history. Wire to ECASH-101 RPCs. Deploy and verify.
- [ ] **ECASH-103** — feat(backend): implement pay-per-access content gating. Extend the content server from TOR-104 with ecash payment verification. When content is marked as "paid", the server returns a 402 Payment Required with a Cashu invoice. The requesting peer pays with ecash, receives a receipt token, and includes it in subsequent requests. Implement in `core/archipelago/src/network/content_server.rs`. Build on server and deploy.
- [ ] **ECASH-104** — feat(ui): content pricing controls. In the content sharing UI (to be built in Phase 4B), add pricing controls: (1) free/paid toggle per content item, (2) price in sats input, (3) "Pay what you want" option with minimum, (4) preview: "Peers will pay X sats to access this." Wire to backend content server config. Deploy and verify.
### Phase 4B: Content Streaming & File Sharing
- [ ] **CONTENT-101** — feat(backend): implement content catalog RPC. Create `core/archipelago/src/network/content_catalog.rs` with: (1) `content.list-mine` — list content I'm sharing, (2) `content.add` — add a file or stream to my catalog, (3) `content.remove` — stop sharing, (4) `content.set-pricing` — free or ecash-gated, (5) `content.set-availability` — available to all peers, specific peers, or nobody. Store catalog in `/var/lib/archipelago/content/catalog.json`. Build on server and deploy.
- [ ] **CONTENT-102** — feat(backend): implement peer content browsing. Add `content.browse-peer` RPC that connects to a peer's onion address over Tor and fetches their content catalog. Returns a list of available items with titles, descriptions, sizes, and prices. The peer's content server (TOR-104) serves the catalog at a well-known endpoint. Build on server and deploy.
- [ ] **CONTENT-103** — feat(backend): implement content streaming protocol. For media files (video, audio), implement chunked streaming over Tor. The requesting node sends a range request, the serving node streams the content chunk by chunk. For paid content, payment is per-chunk (micropayments via ecash). Use HTTP range requests over the Tor hidden service. Build on server and deploy.
- [ ] **CONTENT-104** — feat(ui): content sharing dashboard. Create a "Content" tab in the Web5 view. Show: (1) "My Shared Content" — list of files/streams you're sharing with pricing, (2) "Add Content" button — file picker to add from Cloud/FileBrowser, (3) "Browse Peers" — select a connected peer and browse their catalog, (4) download/stream buttons with payment flow for paid content. Deploy and verify.
- [ ] **CONTENT-105** — feat(ui): content streaming player. When a user clicks to stream video/audio from a peer, open a media player in the app launcher overlay. Show: (1) video/audio player with standard controls, (2) streaming progress indicator, (3) cost tracker (total sats spent on this stream), (4) quality selector if multiple qualities available. Use HTML5 `<video>` or `<audio>` with the Tor-proxied stream URL. Deploy and verify.
### Phase 4C: Networking Profits — Real Data
- [ ] **PROFIT-101** — feat(backend): implement networking profit tracking. Replace the dummy "₿0.024" in Web5.vue with real data. Create `core/archipelago/src/wallet/profits.rs` with: (1) track all ecash received from content sharing, (2) track Lightning routing fees (from LND), (3) RPC endpoint `wallet.networking-profits` that returns total earnings, breakdown by source, and time series. Build on server and deploy.
- [ ] **PROFIT-102** — feat(ui): real networking profits display. Update the "Networking Profits" quick action in Web5.vue (lines 12-23) to show real data from PROFIT-101. Show total earnings, breakdown (content sales, routing fees), and a mini sparkline chart of recent earnings. Deploy and verify.
---
## Q1 2027 (MarMay): Web5 & Decentralized Services
### Phase 5A: DWN (Decentralized Web Node) Integration
- [ ] **DWN-101** — feat(backend): implement DWN container management. Add a DWN service (using TBD's `dwn-server` or equivalent) as a marketplace app. The DWN stores the user's personal data and makes it accessible via DID-based protocols. In `core/archipelago/src/api/rpc/package.rs`, add DWN app config with proper ports and volumes. In Marketplace.vue, add DWN to the curated list. Deploy and verify.
- [ ] **DWN-102** — feat(backend): implement DWN sync protocol. Create `core/archipelago/src/network/dwn_sync.rs` that: (1) syncs the user's DWN data with their other devices, (2) allows connected peers to query your DWN for data you've shared, (3) implements DWN protocol handlers for standard message types. Replace the `_syncDWNs()` TODO in Web5.vue with real functionality. Build on server and deploy.
- [ ] **DWN-103** — feat(ui): make the DWN section in Web5 functional. Replace the hidden (`v-if="false"`) DWN section in Web5.vue (lines 481-530) with a real interface. Show: (1) DWN status (running/stopped/syncing), (2) storage usage, (3) sync status with connected nodes, (4) data protocols registered, (5) "Manage DWN" button that opens the DWN admin interface. Wire to DWN-102 RPCs. Deploy and verify.
### Phase 5B: Bitcoin Domain Names
- [ ] **DOMAIN-101** — feat(backend): implement BNS (Bitcoin Name System) integration. Research and integrate a Bitcoin naming system (e.g., BNS on Stacks, or Nostr NIP-05 verification). Create `core/archipelago/src/identity/names.rs` with: (1) name registration, (2) name resolution, (3) linking a name to a DID. RPC endpoints: `identity.register-name`, `identity.resolve-name`, `identity.list-names`. Build on server and deploy.
- [ ] **DOMAIN-102** — feat(ui): make Bitcoin Domain Names section functional. Replace the dummy "Bitcoin Domain Names" card in Web5.vue (lines 170-219) with real data. Show: (1) owned names with status, (2) registration flow, (3) name → DID linking, (4) expiry management. Wire to DOMAIN-101 RPCs. Deploy and verify.
### Phase 5C: Nostr Relay Management
- [ ] **NOSTR-101** — feat(backend): implement Nostr relay management. Create RPC endpoints: `nostr.list-relays` (returns configured relays with connection status), `nostr.add-relay` (add a relay URL), `nostr.remove-relay`, `nostr.get-stats` (events stored, connected clients). Currently relay count is hardcoded to 8 in Web5.vue — make it real. Build on server and deploy.
- [ ] **NOSTR-102** — feat(ui): make Nostr Relays section functional. Replace the dummy "Nostr Relays" card in Web5.vue (lines 270-319) with real data. Replace hardcoded `nostrRelaysConnected = ref(8)` with live data from NOSTR-101. Show: (1) connected relay count, (2) relay list with status indicators, (3) add/remove relay controls, (4) events stored count. Wire `manageRelays()` function to open a relay management modal. Deploy and verify.
- [ ] **NOSTR-103** — feat(apps): run your own Nostr relay. Add `nostr-rs-relay` or `strfry` to the marketplace (already listed in PORTS.md). When installed, the user's node runs its own Nostr relay that: (1) stores their events locally, (2) can be made public for others, (3) gets a Tor hidden service automatically, (4) feeds into the node's relay list in the Nostr management UI. Deploy and verify.
### Phase 5D: Self-Sovereign Identity Service — Real Implementation
- [ ] **SSI-101** — feat(backend): implement credential issuance and verification. Extend the identity manager with Verifiable Credential (VC) support: `identity.issue-credential` (issue a VC from one of your DIDs), `identity.verify-credential` (verify a VC against a DID), `identity.list-credentials`. Use W3C VC Data Model. Build on server and deploy.
- [ ] **SSI-102** — feat(ui): make SSI section functional. Replace the hidden (`v-if="false"`) SSI section in Web5.vue (lines 532-581) with real data. Show: (1) managed identities count, (2) issued credentials list, (3) service status, (4) credential issuance flow. Deploy and verify.
---
## Q2 2027 (JunAug): Router & Network Infrastructure
### Phase 6A: Router Integration
- [ ] **ROUTER-101** — feat(backend): implement UPnP port forwarding. Create `core/archipelago/src/network/router.rs` with: (1) UPnP device discovery, (2) automatic port forwarding for exposed services, (3) RPC endpoints: `router.discover`, `router.list-forwards`, `router.add-forward`, `router.remove-forward`. When a user enables "expose service X", automatically create UPnP port forwards. Build on server and deploy.
- [ ] **ROUTER-102** — feat(backend): implement network diagnostics. Add `network.diagnostics` RPC that returns: (1) WAN IP address, (2) NAT type detection, (3) UPnP availability, (4) open ports test, (5) Tor connectivity status, (6) DNS resolution test, (7) recommended actions for improving connectivity. Build on server and deploy.
- [ ] **ROUTER-103** — feat(ui): network settings dashboard. Create a "Network" view (or section in Settings) showing: (1) network status overview (WAN IP, NAT type, Tor status), (2) port forwarding management, (3) UPnP status and controls, (4) "Fix Network" wizard that guides users through common issues (double NAT, blocked ports), (5) Tailscale integration status. Wire to ROUTER-101/102 RPCs. Deploy and verify.
- [ ] **ROUTER-104** — feat(backend): open-source router compatibility layer. Research OpenWrt, pfSense, and OPNsense APIs. Implement a router abstraction layer that can communicate with these routers directly (not just UPnP). When a compatible router is detected, offer enhanced features: direct port management, firewall rules, DNS configuration. Build on server and deploy.
### Phase 6B: Wallet & Payments Polish
- [ ] **WALLET-101** — feat(ui): replace dummy wallet data with real backend. The Web5 wallet section currently shows hardcoded "₿0.025" balance and "12 pending" transactions. Connect to LND's wallet RPC to show: (1) real on-chain balance, (2) real Lightning balance, (3) ecash balance, (4) recent transactions. Deploy and verify.
- [ ] **WALLET-102** — feat(ui): unified send/receive flow. Create a send/receive modal accessible from the wallet card. Support: (1) on-chain Bitcoin send/receive, (2) Lightning invoice create/pay, (3) ecash send/receive, (4) automatic method selection based on amount (ecash for small, Lightning for medium, on-chain for large). Deploy and verify.
- [ ] **WALLET-103** — feat(backend): implement wallet connect protocol. Create a standard protocol for apps to request payments from the user's wallet. When an app (in iframe) needs a payment, it sends a postMessage to the parent. The parent shows a payment confirmation dialog. On confirm, the wallet makes the payment and returns a receipt. This replaces the `connectWallet` TODO in Web5.vue. Build on server and deploy.
---
## Q3 2027 (SepNov): Easy Mode & Goal System
### Phase 7A: Easy Mode Implementation
- [ ] **EASY-101** — feat(ui): implement the Easy Mode home screen. Following `docs/three-mode-ui-design.md`, build `neode-ui/src/components/EasyHome.vue` with goal cards: Open a Shop, Accept Payments, Store My Photos, Store My Files, Run a Lightning Node, Create My Identity, Back Up Everything. Each card shows title, description, estimated time, difficulty, and a "Start" button. Use the existing glass-card design system. Deploy and verify.
- [ ] **EASY-102** — feat(ui): implement the goal workflow wizard. Build `neode-ui/src/views/GoalDetail.vue` (may already exist partially) as a multi-step wizard. For each goal: (1) show all steps with status (completed/in-progress/pending), (2) auto-complete steps where the app is already installed, (3) real-time progress from WebSocket for installations, (4) "configure" steps open the app in iframe for user to complete. Wire to app installation RPCs. Deploy and verify with "Accept Payments" goal (Bitcoin + LND).
- [ ] **EASY-103** — feat(stores): implement goal progress tracking. Create `neode-ui/src/stores/goals.ts` that: (1) tracks which goals the user has started/completed, (2) persists to backend via UIData, (3) computes step completion based on installed app status, (4) emits events for goal completion celebrations. Deploy and verify.
- [ ] **EASY-104** — feat(ui): mode switcher in sidebar. Build `neode-ui/src/components/ModeSwitcher.vue` as a three-segment toggle (Easy / Pro / Chat). Place it in the Dashboard sidebar below the logo. When switching modes, sidebar navigation items change per the spec in `three-mode-ui-design.md`. Persist mode choice to localStorage and backend. Deploy and verify.
### Phase 7B: Pro Mode Enhancements
- [ ] **PRO-101** — feat(ui): add Quick Start Goals to Pro mode home. At the bottom of the Pro mode Home view, add a "Quick Start Goals" section showing horizontal-scrolling goal cards. These link to the same GoalDetail wizard. Gives power users access to guided workflows without switching to Easy mode. Deploy and verify.
- [ ] **PRO-102** — feat(ui): add goals to Spotlight Search. In `neode-ui/src/data/helpTree.ts`, add all goal definitions as searchable items with the "Quick Start Goals" category. When selected, navigate to the goal wizard. Deploy and verify goals appear in Cmd+K search.
### Phase 7C: Chat Mode — AIUI Integration
- [ ] **CHAT-101** — feat(ui): implement Chat mode home with full AIUI integration. The existing Chat.vue loads AIUI in an iframe. In Chat mode, make this the primary interface. Add context-aware prompts: "What apps are installed?", "Set up Lightning", "How much disk space is left?". Wire to the context broker service. Deploy and verify.
- [ ] **CHAT-102** — feat(backend): extend context broker for goal execution. When the user tells AIUI "Set up a Lightning node", the context broker should: (1) identify this as the "Run a Lightning Node" goal, (2) execute goal steps via RPC, (3) stream progress back to the chat. This bridges natural language to the goal system. Deploy and verify.
---
## Q4 2027 (DecFeb 2028): Testing & Reliability
### Phase 8A: Comprehensive App Testing
- [ ] **TEST-201** — test(apps): automated install/uninstall test for all 24 marketplace apps. Create a test script that: (1) installs each app via RPC, (2) waits for container to start, (3) verifies health check passes, (4) verifies UI loads (curl the app port), (5) uninstalls the app, (6) verifies container is removed. Run on the dev server. Fix any failures.
- [ ] **TEST-202** — test(apps): dependency chain test. Test all dependency chains: (1) Install Electrs → should prompt for Bitcoin first, (2) Install BTCPay → should install Bitcoin + LND + BTCPay in order, (3) Install Mempool → should install Bitcoin + Electrs + Mempool in order, (4) Install Fedimint Gateway → should require Fedimint Guardian + LND. Fix any broken chains.
- [ ] **TEST-203** — test(apps): iframe/new-tab verification for all apps. For each running app, verify: (1) apps that should iframe actually load in iframe (test with fetch + check X-Frame-Options header), (2) apps that should open in new tab are correctly in `mustOpenInNewTab()`, (3) no mixed content errors on HTTPS. Fix any issues.
### Phase 8B: Network Testing
- [ ] **TEST-204** — test(network): peer discovery and connection flow. Test: (1) enable node visibility → verify Nostr event published, (2) second node discovers first via Nostr, (3) connection request sent over Tor, (4) request accepted, peer added to list, (5) message sent between peers over Tor, (6) message received and displayed in UI. Fix any failures.
- [ ] **TEST-205** — test(network): content sharing and ecash payments. Test: (1) share a file with ecash pricing, (2) peer browses content catalog, (3) peer pays ecash for content, (4) content downloads successfully, (5) ecash appears in seller's wallet, (6) free content downloads without payment. Fix any failures.
- [ ] **TEST-206** — test(network): Tor hidden service reliability. Test: (1) all configured hidden services are reachable from outside the network, (2) hidden service survives container restart, (3) hidden service survives full node reboot, (4) new hidden services can be created dynamically, (5) removing a service removes the .onion address. Fix any failures.
### Phase 8C: Identity Testing
- [ ] **TEST-207** — test(identity): multi-identity lifecycle. Test: (1) create identity during onboarding, (2) create additional identities, (3) sign a message with each identity, (4) verify signatures, (5) delete a non-default identity, (6) switch default identity, (7) use identity with Indeehub, (8) Nostr key generation and event signing. Fix any failures.
### Phase 8D: Performance & Stress Testing
- [ ] **TEST-208** — test(perf): load test with all apps running simultaneously. Start all 24 apps on the dev server. Verify: (1) system remains responsive (UI loads < 3s), (2) no OOM kills, (3) WebSocket stays connected, (4) resource manager reports accurate usage, (5) no container crashes after 24 hours. Fix any issues.
- [ ] **TEST-209** — test(perf): mobile performance audit. Test all views on a real mobile device (or emulator). Verify: (1) initial load < 5s on 4G, (2) route navigation < 1s, (3) smooth scrolling (60fps), (4) no janky animations, (5) app launcher overlay is usable on mobile. Fix any issues.
---
## Q1 2028 (MarMay): Final Polish & Release Prep
### Phase 9A: UX Micro-Interactions
- [ ] **UX-101** — fix(ui): add haptic-like feedback to all interactive elements. Every button press, toggle switch, and card tap should have a subtle visual feedback (scale 0.97 on press, brighten on hover). Ensure consistent feel across the entire UI. Deploy and verify.
- [ ] **UX-102** — fix(ui): add success/error toast animations. Create a polished toast notification system with: slide-in animation, auto-dismiss after 3s, swipe-to-dismiss on mobile, stacking for multiple toasts, success (green), error (red), info (blue) variants. Replace all `console.log` feedback with toasts. Deploy and verify.
- [ ] **UX-103** — fix(ui): add skeleton loading screens for every view. Every view that fetches data should show a skeleton screen (animated gray placeholders matching the layout) instead of a blank page or spinner. Use a reusable `<SkeletonCard>` component. Deploy and verify.
- [ ] **UX-104** — fix(ui): add empty state illustrations. For views with no data (no apps installed, no peers connected, no content shared), show a friendly empty state with an illustration, explanation text, and a call-to-action button. Deploy and verify.
### Phase 9B: Security Audit
- [ ] **SEC-201** — security: comprehensive penetration test. Run a full penetration test covering: (1) authentication bypass attempts, (2) session management, (3) API input validation, (4) path traversal, (5) SSRF, (6) container escape, (7) ecash double-spend, (8) Tor deanonymization risks, (9) XSS/injection. Document all findings and fix critical/high issues.
- [ ] **SEC-202** — security: secrets audit. Verify: (1) no hardcoded credentials in codebase, (2) all secrets use the secrets manager, (3) ecash wallet keys are encrypted at rest, (4) identity private keys are encrypted at rest, (5) backup encryption is sound, (6) TOTP secrets are encrypted. Fix any issues.
- [ ] **SEC-203** — security: dependency audit. Run `npm audit` on frontend, `cargo audit` on backend. Fix all critical and high vulnerabilities. Pin all dependency versions. Verify no supply-chain risks.
### Phase 9C: ISO & Distribution
- [ ] **ISO-101** — fix(iso): update ISO build to include all new features. Update `image-recipe/build-auto-installer-iso.sh` to: (1) include all new container images, (2) include DWN and Nostr relay containers, (3) include Fedimint Guardian + Gateway, (4) include all identity system files, (5) include updated nginx configs with all proxy blocks, (6) include updated first-boot script. Build and test ISO.
- [ ] **ISO-102** — fix(iso): implement ISO auto-update mechanism. Create an update system: (1) node checks for updates via a Nostr event or signed manifest, (2) downloads delta updates (not full ISO), (3) applies updates with rollback capability, (4) updates frontend, backend binary, container images independently. Deploy and verify.
- [ ] **ISO-103** — docs: create user-facing documentation. Write: (1) Getting Started guide (flash USB, install, first boot), (2) App Store guide (installing, managing apps), (3) Identity guide (creating DIDs, using with services), (4) Networking guide (connecting peers, sharing content), (5) Troubleshooting FAQ. Host in the UI as a help section.
### Phase 9D: Final Verification
- [ ] **FINAL-201** — test(final): fresh install end-to-end test. Build a fresh ISO, install on clean hardware, and walk through the entire user journey: (1) boot and install, (2) onboarding with identity creation, (3) install Bitcoin + LND + Fedimint, (4) open Lightning channels, (5) share content, (6) connect to another node, (7) send ecash payment, (8) use Easy mode goal system, (9) use AIUI chat, (10) manage Tor services, (11) create multiple identities, (12) sign into Indeehub. Everything must work flawlessly.
- [ ] **FINAL-202** — test(final): 72-hour stability test. Run the fully configured node for 72 continuous hours. Verify: (1) no memory leaks, (2) no container crashes, (3) WebSocket stays connected, (4) Tor services remain accessible, (5) peer connections survive, (6) ecash wallet balance is accurate, (7) all app UIs still load. Fix any issues.
- [ ] **FINAL-203** — test(final): multi-node network test. Set up 3 Archipelago nodes. Verify: (1) all three discover each other via Nostr, (2) connection requests and acceptance work, (3) content sharing works between all pairs, (4) ecash payments work between all pairs, (5) peer-to-peer messaging works, (6) node going offline/online is handled gracefully by other nodes.
---
## Release Criteria (v1.0)
Before releasing to the public, ALL of these must be true:
- [ ] All 24+ marketplace apps install, run, and open without errors
- [ ] Iframe apps load in iframe, new-tab apps open in new tab — zero exceptions
- [ ] App dependency chains install correctly in order
- [ ] Fedimint Guardian + Gateway work together out of the box
- [ ] Lightning channel management is easy and intuitive
- [ ] Multi-identity system works with DID creation, signing, and service integration
- [ ] Indeehub recognizes sovereign identity without account creation
- [ ] Node overlay network: discover, connect, message over Tor
- [ ] Content sharing with ecash micropayments works trustlessly
- [ ] All Web5 sections show real data (no dummy content)
- [ ] Easy mode goals guide users through complex multi-app setups
- [ ] Chat mode leverages AIUI for natural language node management
- [ ] Tor hidden services are manageable via UI
- [ ] Router integration works with UPnP and open-source routers
- [ ] Animations are smooth (60fps) on desktop and mobile
- [ ] Mobile responsive on all screen sizes
- [ ] Fresh ISO install → full functionality in under 1 hour
- [ ] 72-hour stability test passes
- [ ] Security audit passes with no critical/high findings
- [ ] Zero TypeScript errors, zero Rust warnings, zero linter errors
---
## Post-Completion
```bash
# 1. Test onboarding flow (clear state first)
sshpass -p 'EwPDR8q45l0Upx@' ssh archipelago@192.168.1.228 \
'echo "EwPDR8q45l0Upx@" | sudo -S systemctl restart archipelago'
# Final verification on live server
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 'echo "EwPDR8q45l0Upx@" | sudo -S systemctl status archipelago'
# 2. Visit http://192.168.1.228 in browser
# 3. Walk through complete onboarding
# 4. Login with password
# 5. Install Bitcoin Knots from marketplace
# 6. Open AIUI chat and send a message
# 7. Verify all dashboard pages work
# Check all containers running
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 'sudo podman ps --format "table {{.Names}}\t{{.Status}}"'
# If all pass: ISO is ready for alpha testers
# Run frontend checks
cd neode-ui && npm run type-check && npm run build
# Run backend checks on server
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 'cd ~/archy && cargo clippy --all-targets --all-features && cargo fmt --all --check'
# Visit http://192.168.1.228 and verify everything works
```

View File

@ -1,64 +1,91 @@
You are hardening Archipelago (Archy) for its first alpha release. People will flash this ISO to USB, install on their hardware, and use the web UI to manage their node. Everything must work flawlessly.
You are running a 2-year production roadmap for Archipelago (Archy) — taking it from developer preview to a flawless, mass-market Bitcoin Node OS (v1.0).
Read these files first:
1. `loop/plan.md` — Your task checklist (mark items `- [x]` as you complete them)
2. `CLAUDE.md` — Archy project conventions, architecture, coding standards
## What You're Doing
**No new features. No design changes.** You are:
- Hardening the first-time onboarding flow so it works perfectly
- Ensuring app installation is bulletproof
- Making the AIUI chat work reliably
- Fixing any UI bugs or rough edges
- Building the alpha ISO when everything passes
## Architecture Quick Reference
```
Server: 192.168.1.228 (ssh: archipelago@192.168.1.228, pass: EwPDR8q45l0Upx@)
Server: 192.168.1.228 (ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228)
Frontend: neode-ui/ → builds to web/dist/neode-ui/ → deployed to /opt/archipelago/web-ui/
Backend: core/archipelago/ → Rust binary → deployed to /usr/local/bin/archipelago
AIUI: /Users/dorian/Projects/AIUI/packages/app/ → builds to dist/ → deployed to /opt/archipelago/web-ui/aiui/
Claude Proxy: port 3141 → systemd service claude-proxy
Nginx: port 80 → proxies /rpc/, /ws/, /health, /aiui/
Nginx: /etc/nginx/sites-available/archipelago (source: image-recipe/configs/nginx-archipelago.conf)
Systemd: /etc/systemd/system/archipelago.service (source: image-recipe/configs/archipelago.service)
Deploy: scripts/deploy-to-target.sh, scripts/first-boot-containers.sh
ISO: image-recipe/build-auto-installer-iso.sh
```
## Key Paths
- Onboarding views: `neode-ui/src/views/Onboarding*.vue`
- Views: `neode-ui/src/views/*.vue`
- Components: `neode-ui/src/components/*.vue`
- Stores: `neode-ui/src/stores/*.ts`
- API clients: `neode-ui/src/api/*.ts`
- Global styles: `neode-ui/src/style.css`
- Router: `neode-ui/src/router/index.ts`
- App store: `neode-ui/src/stores/app.ts`
- RPC client: `neode-ui/src/api/rpc-client.ts`
- Container client: `neode-ui/src/api/container-client.ts`
- App manifests: `apps/*/manifest.yml`
- Context broker: `neode-ui/src/services/contextBroker.ts`
- AIUI composable: `/Users/dorian/Projects/AIUI/packages/app/src/composables/useAI.ts`
- Claude proxy: `/Users/dorian/Projects/AIUI/packages/app/server/claude-proxy.ts`
- Types: `neode-ui/src/types/*.ts`
- Backend entry: `core/archipelago/src/main.rs`
- RPC handlers: `core/archipelago/src/api/rpc/*.rs`
- Container mgmt: `core/container/src/*.rs`
- Security: `core/security/src/*.rs`
- Identity: `core/archipelago/src/identity/` (to be created)
- Network: `core/archipelago/src/network/` (to be created)
- Wallet: `core/archipelago/src/wallet/` (to be created)
- Nginx config: `image-recipe/configs/nginx-archipelago.conf`
- Systemd service: `image-recipe/configs/archipelago.service`
- Web5 docs: `docs/WEB5_NOSTR_IDENTITY.md`
- Three-mode UI spec: `docs/three-mode-ui-design.md`
- Port assignments: `apps/PORTS.md`
## For each task in loop/plan.md:
1. Find the first unchecked `- [ ]` item
2. Read the task description carefully — it tells you exactly what to do
3. Read the relevant source files before making changes
4. Make the change following CLAUDE.md conventions
5. Run `cd neode-ui && npm run type-check` — fix all errors
6. Run `cd neode-ui && npm run build` — must succeed
7. Deploy: `./scripts/deploy-to-target.sh --live`
8. If AIUI files were changed: build AIUI (`cd /Users/dorian/Projects/AIUI/packages/app && node node_modules/vite/bin/vite.js build`) and deploy to server (`tar czf /tmp/aiui.tar.gz -C dist . && sshpass -p 'EwPDR8q45l0Upx@' ssh archipelago@192.168.1.228 'mkdir -p /tmp/aiui-deploy' && sshpass -p 'EwPDR8q45l0Upx@' scp /tmp/aiui.tar.gz archipelago@192.168.1.228:/tmp/aiui-deploy/ && sshpass -p 'EwPDR8q45l0Upx@' ssh archipelago@192.168.1.228 'cd /tmp/aiui-deploy && tar xzf aiui.tar.gz && echo "EwPDR8q45l0Upx@" | sudo -S rsync -a --delete /tmp/aiui-deploy/ /opt/archipelago/web-ui/aiui/'`)
9. Verify the fix works on http://192.168.1.228
10. Mark it done `- [x]` in `loop/plan.md`
11. Commit: `type: description`
12. Move to next task immediately
3. Read ALL relevant source files before making changes
4. Make the change following CLAUDE.md conventions strictly:
- Global CSS classes in style.css, NEVER inline Tailwind in components
- `<script setup lang="ts">` only, no Options API
- No `any` types — use proper TypeScript types
- No `unwrap()`/`expect()` in Rust production code — use `?` operator
- Use `tracing` for Rust logging — never `println!`
5. For frontend changes:
- Run `cd neode-ui && npm run type-check` — fix ALL errors
- Run `cd neode-ui && npm run build` — must succeed
- Deploy: `./scripts/deploy-to-target.sh --live`
- Verify at http://192.168.1.228
6. For backend changes:
- Do NOT build Rust on macOS — the deploy script handles it
- Deploy: `./scripts/deploy-to-target.sh --live`
- Verify the service is running on the server
7. For nginx/systemd/infra changes:
- Deploy the config file to the server (commands in the task description)
- Validate config before applying (nginx -t)
- Verify the service works after applying
8. For new feature development:
- Create new files in the appropriate module directories
- Follow existing patterns in the codebase
- Wire new RPC endpoints through the existing RPC system
- Add new views to the router
- Add new stores as needed
9. Mark it done `- [x]` in `loop/plan.md`
10. Commit: `type: description`
11. Move to the next unchecked task immediately
## Rules
## Critical Rules
- Read files before editing — understand before changing
- Never skip build/typecheck — if it fails, fix before moving on
- Always deploy after completing a task — changes must be live
- **Do NOT break existing functionality** — if your change breaks something, fix it before moving on
- **Read files before editing** — understand before changing
- **Never skip type-check or build** — if it fails, fix before moving on
- **Always deploy after completing a task** — changes must be live
- **Use SSH key, not password**: `ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228`
- For sudo: pipe the password `echo "EwPDR8q45l0Upx@" | sudo -S <command>`
- **Follow the design system** — glass cards, glass buttons, existing color tokens, no gradient buttons
- **Replace dummy data with real backends** — no more hardcoded values in Web5.vue
- **New Rust modules** go in `core/archipelago/src/` with proper error types
- **New Vue views** go in `neode-ui/src/views/` with `<script setup lang="ts">`
- If a task is proving difficult after 15+ genuine attempts, add `(BLOCKED: reason)` to the task and move on
- Test on the actual server, not just locally
- Do not stop until all tasks are checked or you hit rate limits
- AIUI files are outside the project — use Bash with python3 for edits if the Edit tool is blocked by hooks
- For ISO build: SSH to 192.168.1.228 and run the build script there
- Commit after each completed task

View File

@ -82,7 +82,7 @@ define(['./workbox-21a80088'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
"revision": "0.qqvn6d3mva8"
"revision": "0.nrq8o7pr84g"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
@ -116,7 +116,7 @@ define(['./workbox-21a80088'], (function (workbox) { 'use strict';
})]
}), 'GET');
workbox.registerRoute(/\/assets\/.*/i, new workbox.CacheFirst({
"cacheName": "assets-cache",
"cacheName": "assets-cache-v2",
plugins: [new workbox.ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 2592000

View File

@ -653,7 +653,7 @@ function getCuratedAppList() {
title: 'Penpot',
version: '2.0.0',
description: 'Open-source design and prototyping platform. Self-hosted alternative to Figma.',
icon: '/assets/img/penpot.webp',
icon: '/assets/img/app-icons/penpot.webp',
author: 'Penpot',
dockerImage: 'docker.io/penpotapp/frontend:latest',
manifestUrl: null,

View File

@ -250,6 +250,65 @@ if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q nextcloud; then
-p 8085:80 -v /var/lib/archipelago/nextcloud:/var/www/html \
docker.io/library/nextcloud:28 2>>"$LOG" || true
fi
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q searxng; then
log "Creating SearXNG..."
$DOCKER run -d --name searxng --restart unless-stopped \
--cap-drop ALL --security-opt no-new-privileges:true \
--read-only --tmpfs /tmp:rw,noexec,nosuid,size=256m --tmpfs /run:rw,noexec,nosuid,size=64m \
-p 8888:8080 \
docker.io/searxng/searxng:latest 2>>"$LOG" || true
fi
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q onlyoffice; then
log "Creating OnlyOffice..."
$DOCKER run -d --name onlyoffice --restart unless-stopped \
--cap-drop ALL --cap-add CHOWN --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
--security-opt no-new-privileges:true \
-p 9980:80 \
docker.io/onlyoffice/documentserver:7.5.1 2>>"$LOG" || true
fi
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q filebrowser; then
log "Creating File Browser..."
mkdir -p /var/lib/archipelago/filebrowser
$DOCKER run -d --name filebrowser --restart unless-stopped \
--cap-drop ALL --security-opt no-new-privileges:true \
--read-only --tmpfs /tmp:rw,noexec,nosuid,size=256m --tmpfs /run:rw,noexec,nosuid,size=64m \
-p 8083:80 -v /var/lib/archipelago/filebrowser:/srv \
docker.io/filebrowser/filebrowser:v2.27.0 2>>"$LOG" || true
fi
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q nginx-proxy-manager; then
log "Creating Nginx Proxy Manager..."
mkdir -p /var/lib/archipelago/nginx-proxy-manager/data /var/lib/archipelago/nginx-proxy-manager/letsencrypt
$DOCKER run -d --name nginx-proxy-manager --restart unless-stopped \
--cap-drop ALL --cap-add CHOWN --cap-add SETUID --cap-add SETGID --cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
-p 81:81 -p 8084:80 -p 8443:443 \
-v /var/lib/archipelago/nginx-proxy-manager/data:/data \
-v /var/lib/archipelago/nginx-proxy-manager/letsencrypt:/etc/letsencrypt \
docker.io/jc21/nginx-proxy-manager:latest 2>>"$LOG" || true
fi
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q portainer; then
log "Creating Portainer..."
mkdir -p /var/lib/archipelago/portainer
$DOCKER run -d --name portainer --restart unless-stopped \
--cap-drop ALL --cap-add CHOWN --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
--security-opt no-new-privileges:true \
-p 9000:9000 \
-v /var/lib/archipelago/portainer:/data \
-v /var/run/podman/podman.sock:/var/run/docker.sock \
docker.io/portainer/portainer-ce:2.19.4 2>>"$LOG" || true
fi
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q tailscale; then
log "Creating Tailscale..."
mkdir -p /var/lib/archipelago/tailscale
$DOCKER run -d --name tailscale --restart unless-stopped \
--network host --privileged \
--cap-add NET_ADMIN --cap-add NET_RAW \
--device=/dev/net/tun \
-v /var/lib/archipelago/tailscale:/var/lib/tailscale \
-e TS_STATE_DIR=/var/lib/tailscale \
docker.io/tailscale/tailscale:stable \
sh -c 'tailscale web --listen 0.0.0.0:8240 & exec tailscaled' 2>>"$LOG" || true
fi
# Immich stack (postgres + redis + server - ML optional)
# Remove old single-container 'immich' if present (wrong port 2283:3001, conflicts with immich_server)