# Archipelago ## What This Is Archipelago is a self-hosted personal-server platform: a Rust daemon (workspace at `core/`) plus a Vue 3 frontend (`neode-ui/`, built to `web/dist/neode-ui/`) running on Debian nodes with rootless Podman, managing ~40 declarative, manifest-driven apps (Bitcoin, Lightning, mesh/LoRa, federation, media, and more). It ships as OTA-updated releases to a live fleet and is actively shipping v1.7.x alpha releases. This milestone drives it to the **developer-ready app platform** north star. ## Core Value A third-party developer can publish an app via the signed/decentralized registry and a user can install it on their node — every app manifest-driven, manifests shipped via the signed registry (not OTA disk files), all rootless, secure, robust, and 100%-uptime-capable. ## Current State (brownfield baseline, 2026-07-29) - Single-node production gate is **GREEN** (5/5 on .228, 2026-06-23) — that exit criterion is met. - ~40 apps are manifest-based and Quadlet-migrated; all multi-container stacks use the orchestrator stack pattern; the legacy per-app installer anti-pattern is deleted. - Workstream B (registry-distributed manifests) phases 1+2 are code-complete; the signing ceremony is done (release-root pinned in `anchor.rs`); the fleet flip is not yet authorized. - Workstream C (marketplace) is design-only (`docs/marketplace-protocol.md`); no tooling or trust UX built. Developer CLI suite (`archy app …`) does not exist yet. - Phase-3 Quadlet default-flip is validated opt-in on .228/.198 but not default. - Declared next exit criteria: the multinode pass (`docs/multinode-testing-plan.md`) and the remaining workstreams. ## Requirements ### Validated - ✓ Single-node lifecycle gate green 5× on .228 (install/UI/stop/start/restart/reinstall/ reboot-survive/daemon-restart-survive/uninstall) — 2026-06-23 - ✓ Manifest-driven app packaging for all ~40 apps incl. multi-container stacks (workstream A) - ✓ Signed catalog + release-root signing ceremony (workstream B phases 1+2, code-complete) ### Active See `.planning/REQUIREMENTS.md` — 20 v1 requirements across MNODE / LIFE / REG / SEC / DEV / MKT, all mapped to phases in `.planning/ROADMAP.md`. ### Out of Scope - Rootful containers, Docker, privileged containers — invariant (ADR-001/ADR-009) - Per-app Rust installers / OS-level provisioning — the anti-pattern being deleted - Centralized gatekept app store — decentralized Nostr marketplace instead (ADR-006) - Web5 DWN spec compliance — deprioritized after TBD shutdown (ADR-011) - Custom live voice-call protocol — deprioritized per user 2026-07-01; revisit later - DHT/iroh distribution backbone (workstream D) — design-only, tracker-marked backlog; v2 ## Context - Repo: `core/` Rust workspace (no root Cargo.toml), `neode-ui/` Vue frontend, `apps/` manifests, `tests/lifecycle/` + `tests/multinode/` gates, `docs/` authoritative plans. - Authoritative narrative: `docs/PRODUCTION-MASTER-PLAN.md`; day-to-day open list: `docs/UNIFIED-TASK-TRACKER.md`. Codebase map: `.planning/codebase/ARCHITECTURE.md` + `.planning/codebase/CONCERNS.md`. - Known debt informing this milestone (from CONCERNS.md): federation tombstone-write errors swallowed; reconciler has no flap observability and no failed-unit self-healing; generated AppArmor profiles are never applied; multinode test harness curl calls lack timeouts; SPEC validation is narrower than ADR-009's mandates (non-root UID, pinned tags, seccomp). - Fleet is live and OTA-updated; all destructive verification happens on designated test nodes per the deploy roster — never uninvited on in-use nodes. ## Constraints - **Security**: Rootless Podman only; manifest-declared secrets (0600, never logged); mandatory container security defaults enforced at manifest level (ADR-009) - **Data safety**: Migrations never destroy data — preserve `/var/lib/archipelago/`, secrets, credentials, ports, adoption container names; always a rollback path - **Verification**: Real-node verification before any tag; lifecycle gate runs ON the node, not via RPC; mesh changes need real-RF E2E tests; re-run the gate after orchestrator changes - **Process**: Commit + push every unit of work (`git push gitea-ai main`); stage by explicit path; deploy to the dev pair before any OTA; never commit secrets - **Tech stack**: Rust (Tokio/Hyper, JSON-RPC 2.0) backend; Vue 3 + Pinia frontend; Quadlet/systemd-user container units; Ed25519-signed release artifacts ## Key Decisions All ten ADRs below are **locked** (Status: Accepted; ingest source `docs/adr/*.md`). They are non-negotiable inputs to planning and cannot be overridden without a new ADR. | ID | Decision | Scope | |----|----------|-------| | ADR-001 | Podman over Docker — rootless, daemonless, systemd-native; `archy-net` for inter-container DNS | Container runtime | | ADR-002 | `did:key` (Ed25519) node identity — self-contained, offline-capable; gaps mitigated via federation trust lists | Identity | | ADR-003 | Nostr relays (NIP-78, kind 30078) for node + app discovery — multi-relay query, 15-min cache, trust scoring, Tor-compatible | Discovery | | ADR-004 | Tor hidden services for inter-node RPC/control plane — bulk data via registries, not Tor | Federation transport | | ADR-005 | ChaCha20-Poly1305 + Argon2id (64MB, 3 iter) for backup encryption | Backups | | ADR-006 | Nostr relays for marketplace discovery — DID-signed manifests, trust tiers (Verified/Community/Unverified), signature verification before install | Marketplace | | ADR-007 | Bilateral DID federation trust via single-use invite codes; Trusted/Observer/Untrusted levels | Federation trust | | ADR-008 | Dual keys from one master seed — Ed25519 canonical identity, secp256k1 for Nostr/Bitcoin/Lightning, linked via NIP-05 | Keys | | ADR-009 | Manifest-level container security enforcement — readonly_root, no_new_privileges, non-root UID, drop-ALL caps, pinned tags, seccomp; overrides explicit + audited | Container security | | ADR-011 | DWN deprioritized — keep custom `dwn_store.rs`, stop branding as Web5, invest in Nostr + Tor federation instead | Peer data sync | (ADR-010 does not exist in the repo — numbering gap, noted in `.planning/INGEST-CONFLICTS.md`.) Milestone-level decisions: | Decision | Rationale | Outcome | |----------|-----------|---------| | Milestone version = 1.8.0-alpha | Decided 2026-07-08 per tracker | — Pending ship | | Workstream D (DHT) deferred to v2 | Design-only, tracker-marked backlog; not needed for north-star metric | — Pending | | App manifest canonical schema = `core/container/src/manifest.rs` | SPEC self-declares code wins over doc | ✓ Good | | Phase-3 Quadlet flip gated on multinode gate reporting clean | Prior uncommitted-flip confusion; flip fresh as a 2-line change when gate is clean | — Pending | --- *Last updated: 2026-07-29 after intel ingest (10 ADRs + 1 SPEC) + codebase mapping*