fix: alpha release hardening — onboarding, security, and ISO build
- Convert "Choose Your Path" screen to informative (read-only cards) - Harden "Choose Your Setup" (gray out Coming Soon options, auto-select Fresh Start) - Auto-fetch DID on mount with retry and auto-advance after success - Improve backup download for mobile compatibility - Add retry logic to verify step with graceful skip option - Route verify → done → login for complete onboarding flow - Add AIUI install confirmation via custom event (SEC-001) - Add file path whitelist for AIUI file access (SEC-002) - Add log redaction for container logs sent to AIUI (SEC-003) - Add Secure flag to session cookie in production (SEC-004) - Fix ISO build script to handle zstd compression errors gracefully - Sync archipelago.service from live server Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
58
loop/plan.md
58
loop/plan.md
@@ -8,77 +8,77 @@
|
||||
|
||||
## Phase 1: Onboarding Flow (Critical Path)
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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] **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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
## Phase 2: First Login & Password Setup
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
## Phase 3: App Installation Reliability
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
## Phase 4: AIUI Chat Hardening
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
## Phase 5: Dashboard & UI Polish
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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)
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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-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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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
|
||||
|
||||
- [ ] **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.
|
||||
|
||||
- [ ] **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.
|
||||
- [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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user