Files
archy/docs/architecture.md
T
archipelagoandClaude Opus 5 cc00884b98 docs: repair links left dangling by the operations-doc removal
Untracking the ops docs broke every reference to them. Repoints or removes
those references across README, architecture, ROADMAP, the archive index,
lifecycle TESTING, the hardening plan, and the security docs — pointing at
the issue tracker where a live task list was meant, and dropping the entry
entirely where it only existed to link an internal file.

Also fixes two pre-existing broken links found by validating every relative
link in the tracked docs:
- README linked docs/OPEN_SOURCE_READINESS.md, which never existed
  (underscores vs hyphens).
- reticulum-daemon/README.md linked a local Claude session plan at
  ../../.claude/plans/enchanted-strolling-rocket.md — outside the repo, and
  a path that would have shipped publicly pointing at nothing.

All relative links in tracked markdown now resolve: 0 broken.
audit-secrets.sh still 5/5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 10:10:25 -04:00

13 KiB

Archipelago — Architecture

Bitcoin Node OS — Flash to USB, install on hardware, manage via web UI.

Stack: Rust backend + Vue 3 + TypeScript (strict) + Vite + Tailwind CSS + Pinia + rootless Podman (Quadlet) Target OS: Debian 13 (Trixie) — x86_64 and ARM64 Status: 1.8.0-alpha — single-node production gate green; multinode pass + release hardening in progress (see ROADMAP.md)


System Layers

┌──────────────────────────────────────────────────────┐
│                 YOUR BROWSER                         │
│          Vue 3 SPA (Composition API + Pinia)         │
└──────────────────────┬───────────────────────────────┘
                       │ HTTP / WebSocket
┌──────────────────────┴───────────────────────────────┐
│                    NGINX                             │
│   /rpc/v1 → backend    /app/{id}/ → container        │
└──────────────────────┬───────────────────────────────┘
                       │ port 5678 (127.0.0.1)
┌──────────────────────┴───────────────────────────────┐
│              RUST BACKEND (core/)                    │
│  Auth, ~380 RPC methods, orchestrator + reconciler,  │
│  federation, mesh, identity, wallet, updates         │
└──────────────────────┬───────────────────────────────┘
                       │ Podman REST API socket + systemd Quadlet units
┌──────────────────────┴───────────────────────────────┐
│           ROOTLESS PODMAN CONTAINERS                 │
│  50+ manifest-driven apps as user.slice Quadlet      │
│  units — survive backend restarts, self-heal         │
└──────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────┐
│              DEBIAN 13 (Trixie)                      │
│  systemd, UFW, Tor, AppArmor, Reticulum daemon       │
└──────────────────────────────────────────────────────┘

Codebase Stats

Component Lines Files
Rust backend (core/) ~117,000 ~334
TypeScript/Vue (neode-ui/src/) ~69,000 ~325
Shell scripts (scripts/) ~51
Packaged apps (apps/*/manifest.yml) 51

Backend Crates (core/)

Workspace members (root core/Cargo.toml):

Crate Purpose
archipelago Main binary — API (~380 RPC methods), container orchestrator + boot reconciler, mesh, identity/federation, wallet, updates, marketplace
container (archipelago-container) Podman REST client, canonical manifest schema, Quadlet compiler, health monitor, signed app catalog, image verification
security (archipelago-security) AppArmor/seccomp container policy generation, secrets manager
openwrt (archipelago-openwrt) TollGate gateway provisioning over SSH/UCI
performance (archipelago-performance) Resource limits

Also on disk but not workspace members (standalone/legacy, cleanup tracked in the hardening plan §G): models, helpers, js-engine, container-init.

Key Backend Modules

core/archipelago/src/
├── api/handler/            — HTTP routing (/rpc, /health, /dwn, /ws)
├── api/rpc/dispatcher.rs   — RPC dispatch (~380 method arms)
├── api/rpc/package/        — App install/lifecycle/stacks (multi-container)
├── container/              — prod_orchestrator, boot_reconciler, quadlet,
│                             app_catalog (signed, embedded manifests),
│                             version_config, crash_recovery, secrets
├── trust/                  — release-root anchor (pinned Ed25519 pubkey),
│                             detached-signature verify, did:key
├── mesh/                   — Meshtastic + MeshCore + Reticulum transports,
│                             X3DH/double-ratchet crypto, outbox/scheduler,
│                             mesh AI assistant, bitcoin relay
├── federation/             — multi-node federation over Tor, state sync
├── identity.rs / identity_manager.rs — Ed25519 did:key, multi-identity
├── credentials/            — W3C Verifiable Credentials
├── nostr_discovery.rs      — Nostr presence (NIP-33 kind 30078)
├── nostr_handshake.rs      — NIP-44 encrypted peer comms
├── marketplace.rs          — decentralized app marketplace (Nostr NIP-78,
│                             DID-signed manifests, trust scoring)
├── wallet/                 — LND integration, ecash (Fedimint/Cashu)
├── update.rs               — signed OTA: resumable download, rollback,
│                             post-update self-verify window
├── session.rs / auth.rs    — sessions (persisted), Argon2id, TOTP
├── transport/ / network/   — Tor transport, DWN store/sync
└── fips/ / swarm/ / streaming/ — federation IPS anchor, P2P swarm (gated), streaming (WIP)

App Platform (as built)

An app is a directory apps/<id>/manifest.yml parsed by the canonical schema in core/container/src/manifest.rs. A manifest declares identity, a container source (image XOR build), and runtime shape: ports, volumes (confined to /var/lib/archipelago), generated config files, environment, devices, resources, health checks, and the launch interface. Ergonomics are declarative too: derived_env (host-fact templating), secret_env (podman secrets — values never appear in podman inspect or unit files), generated_secrets / generated_certs (self-healing), network_aliases, data_uid, and allow-listed post_install hooks that run inside the app's own sandbox.

Install compiles the manifest to a rootless Quadlet unit under user.slice — containers survive backend restarts and reboots. Multi-container apps (BTCPay, Mempool, Immich, NetBird, IndeeHub) are sets of per-member manifests installed via the stack orchestrator on an app-local network with readiness gates and generated cross-service secrets. A level-triggered boot reconciler converges actual state to desired state every 30 seconds.

Distribution: the signed catalog (releases/app-catalog.json, Ed25519 detached signature over canonical JSON, verified against the pinned release-root anchor in trust/anchor.rs) embeds the full manifest per app; nodes overlay catalog manifests over disk files (catalog wins), so apps can ship without OTA disk files. A curated subset (27 apps) powers the store UI (app-catalog/catalog.json). A parallel decentralized marketplace (Nostr NIP-78 discovery, DID-signed manifests, federation-weighted trust scoring, Lightning purchase invoices) is implemented as a second, community-distribution channel.

Security invariants enforced at manifest validation: read-only root and no-new-privileges by default, capability allow-list, network_policy ∈ {isolated, bridge, host}, bind mounts confined to /var/lib/archipelago, no privileged containers, rootless only.

Frontend (neode-ui/src/)

├── api/                    — RPC client, WebSocket, container client
├── views/                  — Dashboard, Apps, Marketplace, Cloud, Server,
│                             Mesh, Web5, Settings, Monitoring, Fleet, Chat,
│                             onboarding flow (11 screens), kiosk, recovery
├── components/             — EasyHome, ModeSwitcher, BootScreen, SpotlightSearch, …
├── stores/                 — Pinia: app, install, mesh, cloud, goals, uiMode,
│                             controller (gamepad), aiPermissions, …
├── composables/            — useControllerNav, useToast, useNavSounds, …
├── router/                 — ~51 routes
└── style.css               — global glassmorphism theme

Three UI modes (Pro/Easy/Chat), gamepad navigation, i18n, PWA. Tested with Vitest + Playwright. AIUI is a separate external app surfaced via nginx.

Mesh Networking

Three LoRa transports behind one chat UI and a common MeshRadioDevice surface:

  • Meshtastic — in-process async serial driver (protobuf over SLIP)
  • MeshCore — framed-serial protocol; phone companion apps speak this
  • Reticulum (RNS/LXMF) — host-supervised Python daemon (reticulum-daemon/, PyInstaller-packaged, one per RNode radio) speaking Unix-socket JSON-RPC to the backend; archy-rnodeconf ships as an OS-level radio config tool

End-to-end encryption uses X3DH key agreement + double-ratchet. Extras: image and voice attachments, mesh AI assistant (!ai), Bitcoin balance relay over mesh, steganography, store-and-forward outbox.

Networking

  • Container DNS: app-local Podman networks with network_aliases; aardvark-dns resolution
  • Tor: system daemon, SOCKS5 on 9050, hidden services per node; all inter-node federation traffic
  • Federation: invite-based joining, DID-based trust levels, state sync, cross-node app deploy
  • UFW: DEFAULT_FORWARD_POLICY="ACCEPT" required for LAN container access
  • OpenWrt/TollGate: gateway provisioning via the openwrt crate

Security Model

Layer Measures
OS Debian hardening, AppArmor, minimal packages
Nginx CSP headers, rate limiting, auth_request, session validation
Backend Input validation, CSRF, session auth, bind 127.0.0.1 only
Containers Rootless Podman, cap-drop ALL + reviewed allow-list, readonly root, no-new-privileges, memory limits
Supply chain Ed25519-signed release manifests + app catalog against a pinned release-root anchor; auto-apply refuses unsigned
Crypto Ed25519 signatures, ChaCha20-Poly1305 encryption, Argon2id password hashing (transparent bcrypt upgrade), constant-time comparisons
Network Tor hidden services, UFW firewall, SSRF prevention

Data Paths

Data Path
App data /var/lib/archipelago/{app-id}/
Identity /var/lib/archipelago/identity/
Multi-identity /var/lib/archipelago/identities/
Federation /var/lib/archipelago/federation/
DWN messages /var/lib/archipelago/dwn/messages/
Credentials /var/lib/archipelago/credentials/
Backups /var/lib/archipelago/backups/ (ChaCha20-Poly1305)
Secrets /var/lib/archipelago/secrets/{app-id}/ (0600, service-user-owned)
Sessions /var/lib/archipelago/sessions.json
Marketplace cache /var/lib/archipelago/marketplace/
Frontend /opt/archipelago/web-ui/
Backend binary /usr/local/bin/archipelago

Key Features (Working)

  • 50+ containerized apps with one-click install/manage; full lifecycle matrix repeatedly green on real hardware
  • Bitcoin Core and Knots with per-app version pinning and safe switching; LND + Core Lightning
  • Multi-node federation with invite-based joining and trust levels
  • W3C DID identity (did:key, DID Documents, Verifiable Credentials)
  • Nostr: NIP-33 node discovery, NIP-44/NIP-04 encryption, NIP-07 signer bridge for iframe apps, relay hosting
  • Decentralized marketplace (NIP-78 discovery, trust scoring, Lightning purchases)
  • File sharing with access controls (free/peers-only/paid via LN, on-chain, ecash)
  • Encrypted backups (Argon2 + ChaCha20-Poly1305)
  • Health monitoring + level-triggered reconciler with tiered auto-restart
  • Tri-protocol LoRa mesh (Meshtastic / MeshCore / Reticulum) with E2E crypto
  • Signed OTA updates with rollback and post-update self-verification
  • Three-mode UI (Pro/Easy/Chat), gamepad navigation, real-time WebSocket updates
  • Bootable ISO installer (image-recipe/), Android companion app

Further Documentation

Doc Purpose
ROADMAP.md Shipped / in-progress / planned
developer-guide.md Dev setup, workflow, code conventions
api-reference.md RPC endpoint reference
app-developer-guide.md Building and publishing apps
app-manifest-spec.md The manifest.yml schema
user-walkthrough.md End-user installation and usage guide
troubleshooting.md Diagnostic scenarios and solutions
multi-node-architecture.md Federation protocol design
marketplace-protocol.md Decentralized app discovery via Nostr
archive/ Historical audits, session logs, shipped designs