# Archipelago — contributor guide This file orients anyone (human or AI) working in this repository: the invariants that must hold, how to build and verify, and where the deeper design docs live. The authoritative behaviour is always the code in `core/`. Start with [`AGENTS.md`](AGENTS.md) for the current workflow and authority, [`docs/README.md`](docs/README.md) for the documentation index, and [`Release & Testing/README.md`](Release%20%26%20Testing/README.md) for current release scope. [`docs/ROADMAP.md`](docs/ROADMAP.md) is a dated public overview. The north star: a world-class, **developer-ready app platform** — every app manifest-driven, rootless, secure, and 100%-uptime-capable, with third-party developers publishing via an external/decentralized registry. Detailed sub-plans: - Current app packaging contract → [`docs/app-developer-guide.md`](docs/app-developer-guide.md) and [`docs/app-manifest-spec.md`](docs/app-manifest-spec.md) - Registry-distributed manifests → [`docs/registry-manifest-design.md`](docs/registry-manifest-design.md) - External/decentralized marketplace for devs → [`docs/marketplace-protocol.md`](docs/marketplace-protocol.md) - App manifest schema → [`docs/app-manifest-spec.md`](docs/app-manifest-spec.md) - Production test gate → [`tests/lifecycle/TESTING.md`](tests/lifecycle/TESTING.md) ## Preserve work and follow publication authority - Keep focused commits and a clear checkpoint for unfinished work. Follow [`AGENTS.md`](AGENTS.md) for review, mirror and publication gates; a commit does not by itself authorize a push, merge or release. - Preserve other contributors' dirty work and recorded failures. Do not create a WIP commit merely to make a shared tree clean. - **Stage explicitly by path** (`git add `) when another contributor's uncommitted work shares the tree — never `git add -A` / `git commit -a`, which clobbers or entangles their changes. - **Never commit secrets** (mnemonics, private keys, API tokens). Signing is done offline; artifacts (catalog/manifest) are signed, not the keys. ## UI/UX changes need maintainer UAT Any PR that touches UI (`neode-ui/`, `web/`, locale strings, styles, app launch surfaces, or backend changes to UI-visible text, settings, states or errors) must start its description with this line, verbatim: `Requires UI/UX UAT approval from the maintainer`. It must then list the screens and flows to review. It is not merged until the maintainer approves. [`AGENTS.md`](AGENTS.md) has the full rule and what the list must cover. ## Invariants (never violate) - **Rootless Podman only.** No rootful, no Docker-socket mounts, no privileged containers unless explicitly approved. - **No per-app Rust installers / no OS-level reliance.** Apps are declarative; the orchestrator owns the lifecycle. A hardcoded `podman run` + `sudo chown` installer is the anti-pattern being deleted, not a template. - **Secrets are manifest-declared** (`generated_secrets`, materialised by `container::secrets`, 0600/rootless) — never hardcoded, per-app, or logged. - **Migrations never destroy data** — preserve `/var/lib/archipelago/`, secrets, credentials, ports, and adoption container names; keep a rollback path. - **Verify on a real node before any release tag.** ## Build / verify - Rust workspace root is `core/` (no Cargo.toml at repo root). Run `cargo` from `core/`. - If a `cargo test`/build hits `rust-lld: undefined hidden symbol`, it's incremental-cache corruption — rebuild with `CARGO_INCREMENTAL=0`. - Frontend: `neode-ui/` → `npm run build` outputs to `web/dist/neode-ui/`. Grep the built bundle for new strings before shipping (the build can silently no-op). - App manifests are delivered inside the **signed catalog** (`releases/app-catalog.json`), whose entry overrides the on-disk `/opt/archipelago/apps/*/manifest.yml` (origin-wins; disk is the fallback). Editing a disk manifest alone does **not** change a catalog-covered app — regenerate and re-sign the catalog. ## Production test gate (definition of done) `tests/lifecycle/run-gate.sh` must be green across install / UI / stop / start / restart / reinstall / reboot-survive / archipelago-restart-survive / uninstall. **Run the gate on the node** (it uses local podman/systemctl/bitcoin probes), not via RPC from another host, and re-run it after any orchestrator/lifecycle change. Multinode / fleet testing is a separate pass. See [`tests/lifecycle/TESTING.md`](tests/lifecycle/TESTING.md).