archy/.claude/plans/shiny-bouncing-raven.md
2026-03-12 12:56:59 +00:00

4.6 KiB

Plan: Fix Iframe Apps, Detail Pages, Kiosk, Identity Pairing, NIP-07

Context

Three web-only apps (BotFights, 484 Kitchen, Arch Presentation) show black screens in iframe despite nginx reverse proxies being set up. The kiosk on .228 isn't running. Web-only apps need proper detail pages. The user wants Nostr identity formally paired with DID and NIP-07 browser integration for frictionless login to embedded apps.


Task 1: Fix iframe black screen (HIGH)

Root cause: Proxied HTML contains root-relative paths (href="/css/main.css"). Browser resolves these against the origin root, not /ext/botfights/, so all assets 404.

Fix: Add sub_filter to nginx proxy blocks to rewrite root-relative paths.

File: image-recipe/configs/nginx-archipelago.conf (6 location blocks — 3 HTTP, 3 HTTPS)

Key additions per block:

proxy_set_header Accept-Encoding "";  # Disable gzip so sub_filter works
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/ext/{app}/';
sub_filter 'src="/' 'src="/ext/{app}/';
sub_filter 'action="/' 'action="/ext/{app}/';
sub_filter "href='/" "href='/ext/{app}/";
sub_filter "src='/" "src='/ext/{app}/";

Deploy + nginx reload. Verify in browser DevTools (Network tab — no 404s on assets).


Task 2: Detail pages for web-only apps (MEDIUM)

Problem: Clicking a web-only app card navigates to /dashboard/apps/{id}. AppDetails.vue can't resolve it because web-only apps aren't in store.packages or dummyApps.

Fix:

  1. Add 7 web-only apps to dummyApps in AppDetails.vue (botfights, nwnn, 484-kitchen, call-the-operator, arch-presentation, syntropy-institute, t-zero) — same pattern as IndeeHub
  2. Add URL mappings in AppDetails.vue appUrls for all 7 (if not already present)
  3. Hide uninstall/start/stop buttons for web-only apps in AppDetails.vue

Files: neode-ui/src/views/AppDetails.vue


Task 3: Kiosk on .228 (MEDIUM)

Problem: Code exists but was never installed on server. No X11/Chromium packages.

Steps (SSH to .228, no code changes):

  1. sudo apt-get install -y xorg chromium unclutter xinit
  2. cd ~/archy && sudo ./scripts/setup-kiosk.sh archipelago
  3. sudo systemctl enable --now archipelago-kiosk.service
  4. Verify on monitor

Task 4: Pair Nostr identity with DID (LOW)

Current state: Ed25519 (DID) and secp256k1 (Nostr) are separate key pairs, both generated at startup. Not formally linked.

Fix: Include the Nostr secp256k1 pubkey in the DID Document as an additional verification method:

  • Modify did_document_from_pubkey_hex() in identity.rs to accept optional Nostr pubkey
  • Add EcdsaSecp256k1VerificationKey2019 entry to verificationMethod array
  • Pass Nostr pubkey from server startup context

Files: core/archipelago/src/identity.rs, core/archipelago/src/server.rs


Task 5: NIP-07 Nostr login via iframe injection (EXPLORATORY)

Goal: Web apps in iframe (like IndeeHub) can call window.nostr.getPublicKey() and window.nostr.signEvent() for frictionless Nostr login.

Approach: Inject a window.nostr shim into proxied pages via sub_filter, communicating with the parent Archipelago frame via postMessage.

Steps:

  1. Create neode-ui/public/nostr-provider.js — implements window.nostr interface, uses postMessage to parent
  2. Add sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>'; to nginx ext proxy blocks
  3. Add postMessage listener in AppLauncherOverlay that handles nostr-getPublicKey and nostr-signEvent by calling backend RPC
  4. Backend already has identity.nostr-sign and node.nostr-pubkey RPC endpoints

Security: Validate postMessage origin, prompt user before signing, never expose secret key to frontend.

Files: new neode-ui/public/nostr-provider.js, image-recipe/configs/nginx-archipelago.conf, AppLauncherOverlay component, neode-ui/src/stores/appLauncher.ts


Execution Order

  1. Task 1 — fix iframe black screen (deploy nginx)
  2. Task 2 — detail pages (deploy frontend)
  3. Task 3 — kiosk on .228 (SSH ops)
  4. Task 4 — DID+Nostr pairing (deploy backend)
  5. Task 5 — NIP-07 injection (deploy full)

Verification

  • Task 1: Open BotFights/484 Kitchen/Arch Presentation in iframe — page renders with styles and interactivity
  • Task 2: Click web-only app card → detail page shows with title, description, launch button, no container buttons
  • Task 3: .228 monitor shows kiosk app grid
  • Task 4: node.did RPC returns DID Document with Nostr pubkey in verificationMethod
  • Task 5: Open IndeeHub in iframe, browser console window.nostr.getPublicKey() returns hex pubkey