Archipelago — open-source initial import
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# ADR-001: Podman Over Docker
|
||||
|
||||
**Status**: Accepted
|
||||
**Date**: 2026-03
|
||||
|
||||
## Context
|
||||
|
||||
Archipelago needs a container runtime for running applications. Docker and Podman are the two main options.
|
||||
|
||||
## Decision
|
||||
|
||||
Use Podman as the container runtime instead of Docker.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- **Rootless by default**: Containers run without root privileges, reducing attack surface
|
||||
- **Daemonless**: No persistent daemon process; containers are managed as individual processes under systemd
|
||||
- **Docker-compatible**: Supports Docker images and most Docker CLI commands
|
||||
- **Systemd integration**: Podman containers can be managed as systemd services natively
|
||||
- **No vendor lock-in**: OCI-compliant, works with any container registry
|
||||
|
||||
### Negative
|
||||
- **Smaller ecosystem**: Some Docker-specific tools and compose features require adaptation
|
||||
- **Docker Compose differences**: Podman Compose exists but has occasional compatibility gaps
|
||||
- **Documentation**: Most container documentation assumes Docker; developers need to translate
|
||||
- **Networking**: Podman networking (CNI/netavark) differs from Docker's bridge networking
|
||||
|
||||
### Mitigation
|
||||
- Use `podman` CLI wrapper that provides Docker-compatible interface
|
||||
- Document Podman-specific commands in developer guide
|
||||
- Use `archy-net` custom network for inter-container DNS
|
||||
@@ -0,0 +1,31 @@
|
||||
# ADR-002: DID Key Method for Node Identity
|
||||
|
||||
**Status**: Accepted
|
||||
**Date**: 2026-03
|
||||
|
||||
## Context
|
||||
|
||||
Each Archipelago node needs a cryptographic identity for peer authentication, federation, and verifiable credentials. Multiple DID methods exist (did:web, did:ion, did:key, did:peer).
|
||||
|
||||
## Decision
|
||||
|
||||
Use `did:key` as the primary DID method.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- **Self-contained**: The DID document is derived entirely from the public key — no external resolution needed
|
||||
- **Offline-capable**: Works without internet, aligning with sovereignty principles
|
||||
- **Simple**: No registration, no blockchain, no web server required
|
||||
- **Fast**: DID resolution is a local computation, not a network request
|
||||
- **Ed25519**: Uses Ed25519 keys which are fast, compact, and well-supported
|
||||
|
||||
### Negative
|
||||
- **No key rotation**: The DID is bound to a single key; rotating requires a new DID
|
||||
- **No service endpoints in DID**: Cannot embed service URLs in the DID document itself
|
||||
- **No revocation**: Cannot revoke a did:key without out-of-band mechanisms
|
||||
|
||||
### Mitigation
|
||||
- Use federation trust lists for key management and revocation
|
||||
- Store service endpoints (onion address, pubkey) separately in federation state
|
||||
- Support migration to did:peer or did:web in future versions if key rotation is needed
|
||||
@@ -0,0 +1,35 @@
|
||||
# ADR-003: Nostr Relays for Node and App Discovery
|
||||
|
||||
**Status**: Accepted
|
||||
**Date**: 2026-03
|
||||
|
||||
## Context
|
||||
|
||||
Archipelago nodes need to discover peers and community apps without a central registry. Options: custom P2P protocol, DHT, BitTorrent tracker, Nostr relays, IPFS.
|
||||
|
||||
## Decision
|
||||
|
||||
Use Nostr relays (NIP-78, kind 30078) for both node discovery and marketplace app manifests.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- **Decentralized**: Multiple independent relays; no single point of failure
|
||||
- **Existing infrastructure**: Thousands of Nostr relays already running globally
|
||||
- **Censorship-resistant**: If one relay censors, others still serve events
|
||||
- **Simple protocol**: WebSocket + JSON — easy to implement without heavy dependencies
|
||||
- **Key management**: Nostr uses secp256k1, same curve as Bitcoin — natural fit
|
||||
- **NIP-33 replaceable events**: Latest event replaces previous — clean update model
|
||||
- **Tor-compatible**: WebSocket over Tor SOCKS proxy works natively
|
||||
|
||||
### Negative
|
||||
- **Relay availability varies**: Some relays may be down or rate-limited
|
||||
- **No guaranteed persistence**: Relays may prune old events
|
||||
- **Spam potential**: Open publishing means anyone can publish junk manifests
|
||||
- **Latency**: Querying multiple relays adds latency to discovery
|
||||
|
||||
### Mitigation
|
||||
- Query multiple relays in parallel; deduplicate results
|
||||
- Cache results locally with 15-minute TTL
|
||||
- Use trust scoring to rank manifests (DID verification, relay consensus, federation trust)
|
||||
- Use hashtag filtering (`archipelago-marketplace`) to narrow queries
|
||||
@@ -0,0 +1,35 @@
|
||||
# ADR-004: Tor Hidden Services for Peer Communication
|
||||
|
||||
**Status**: Accepted
|
||||
**Date**: 2026-03
|
||||
|
||||
## Context
|
||||
|
||||
Federated nodes need to communicate directly for state sync, app deployment, and peer verification. Options: direct IP, VPN tunnel, Tor hidden services, I2P.
|
||||
|
||||
## Decision
|
||||
|
||||
Use Tor hidden services (.onion addresses) for all inter-node communication.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- **NAT traversal**: Works behind any firewall or NAT without port forwarding
|
||||
- **IP privacy**: Nodes never expose their real IP addresses to each other
|
||||
- **End-to-end encryption**: Tor provides encryption without additional TLS setup
|
||||
- **Censorship resistance**: Onion routing makes traffic analysis difficult
|
||||
- **Stable addressing**: .onion addresses persist across IP changes and network migrations
|
||||
- **No central infrastructure**: No VPN server, STUN/TURN server, or relay needed
|
||||
|
||||
### Negative
|
||||
- **Latency**: Tor adds 200-500ms per hop; 3 hops per direction = noticeable delay
|
||||
- **Bandwidth**: Tor network has limited bandwidth; not suitable for bulk data transfer
|
||||
- **Reliability**: Tor circuits can break; connections may need retry logic
|
||||
- **Setup complexity**: Requires running a Tor daemon (`archy-tor` container)
|
||||
- **Blocked networks**: Some networks block Tor; bridges can help but add complexity
|
||||
|
||||
### Mitigation
|
||||
- Use Tor only for RPC/control plane; bulk data (container images) pulled from registries
|
||||
- Implement retry with backoff for Tor connections
|
||||
- Container `archy-tor` runs automatically with host networking for hidden service access
|
||||
- Federation sync interval (5 min) tolerates occasional connection failures
|
||||
@@ -0,0 +1,32 @@
|
||||
# ADR-005: ChaCha20-Poly1305 for Backup Encryption
|
||||
|
||||
**Status**: Accepted
|
||||
**Date**: 2026-03
|
||||
|
||||
## Context
|
||||
|
||||
Backups contain sensitive data (keys, credentials, app state) and must be encrypted at rest. Options: AES-256-GCM, ChaCha20-Poly1305, XChaCha20-Poly1305.
|
||||
|
||||
## Decision
|
||||
|
||||
Use ChaCha20-Poly1305 (AEAD) with Argon2id key derivation for backup encryption.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- **Software performance**: ChaCha20 is faster than AES on hardware without AES-NI (common on ARM/SBCs)
|
||||
- **Constant-time**: No timing side channels, unlike some AES implementations
|
||||
- **AEAD**: Authenticated encryption ensures both confidentiality and integrity
|
||||
- **Widely audited**: Used in TLS 1.3, WireGuard, and Signal Protocol
|
||||
- **Simple implementation**: No padding, no CBC/CTR mode complexity
|
||||
- **Argon2id KDF**: Memory-hard key derivation resists GPU/ASIC brute force attacks
|
||||
|
||||
### Negative
|
||||
- **96-bit nonce**: Must ensure nonce uniqueness per encryption (random generation with collision check)
|
||||
- **Not FIPS-certified**: Some enterprise environments require AES (not relevant for personal nodes)
|
||||
- **Less hardware acceleration**: AES-NI on x86 can make AES faster on desktop CPUs
|
||||
|
||||
### Mitigation
|
||||
- Generate random nonce per backup; store nonce alongside ciphertext
|
||||
- Argon2id with high memory cost (64MB) and iterations (3) for password-to-key derivation
|
||||
- Target hardware is mixed x86/ARM; ChaCha20's consistent performance is an advantage
|
||||
@@ -0,0 +1,57 @@
|
||||
# ADR-006: Nostr Relays for Marketplace Discovery
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Archipelago needs a mechanism for users to discover and install third-party applications. The traditional approach is a centralized app store (like Apple App Store, Google Play, or Umbrel's marketplace). However, a centralized store introduces:
|
||||
|
||||
- A single point of failure and censorship
|
||||
- A trust dependency on the store operator
|
||||
- Barriers to entry for app developers (gatekeeping)
|
||||
- Privacy concerns (the store operator knows what every user installs)
|
||||
|
||||
As a sovereign computing platform, Archipelago should align with decentralized principles.
|
||||
|
||||
## Decision
|
||||
|
||||
Use **Nostr relays** (NIP-78 application-specific data, kind 30078 events) for decentralized app manifest discovery instead of a centralized marketplace server.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **App developers** publish signed manifests as Nostr events to public relays
|
||||
2. **Archipelago nodes** query multiple relays for available app manifests
|
||||
3. **Trust scoring** uses verification count across relays, developer reputation (DID-linked), and optional community endorsements
|
||||
4. **Users** see a merged, deduplicated list of available apps with trust indicators
|
||||
|
||||
### Trust Tiers
|
||||
|
||||
- **Verified**: Published by known developers, seen on 3+ relays, DID-verified
|
||||
- **Community**: Seen on 2+ relays, valid manifest, unsigned or new developer
|
||||
- **Unverified**: Single relay, new developer, use at own risk
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- No single point of failure — apps remain discoverable even if relays go offline
|
||||
- No gatekeeping — any developer can publish apps
|
||||
- Privacy-preserving — no central server tracking installs
|
||||
- Censorship-resistant — apps can't be removed by a single entity
|
||||
- Aligns with Nostr ecosystem already used for node identity
|
||||
|
||||
### Negative
|
||||
|
||||
- Discovery can be slower (querying multiple relays)
|
||||
- Quality control relies on trust scoring rather than human curation
|
||||
- Spam/malicious manifests require robust filtering
|
||||
- Users need to understand trust tiers (not a simple "everything is safe" model)
|
||||
|
||||
### Mitigations
|
||||
|
||||
- Cache relay responses locally for fast subsequent loads
|
||||
- Built-in curated app list for essential apps (Bitcoin, LND, etc.)
|
||||
- Container security model (readonly_root, capability dropping) limits damage from malicious apps
|
||||
- Manifest signature verification before installation
|
||||
@@ -0,0 +1,54 @@
|
||||
# ADR-007: DID-Based Federation Trust
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Archipelago supports federation — multiple nodes forming a trusted group for remote monitoring, app deployment, and state synchronization. Federation requires a trust establishment mechanism:
|
||||
|
||||
- **Centralized PKI** (Certificate Authorities): requires internet access, introduces third-party trust
|
||||
- **Pre-shared keys**: simple but doesn't scale, no identity verification
|
||||
- **DID-based bilateral verification**: each node verifies the other's cryptographic identity directly
|
||||
|
||||
## Decision
|
||||
|
||||
Use **bilateral DID-based verification** with single-use invite codes for federation trust establishment.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Node A** generates a single-use invite code containing its DID, .onion address, and a shared secret
|
||||
2. **Node B** receives the code (out-of-band: QR code, message, etc.) and submits it
|
||||
3. **Both nodes** verify each other's DIDs by exchanging signed challenges over Tor
|
||||
4. **Trust is established** — each node stores the other's DID and public key
|
||||
5. **Ongoing communication** uses DID-authenticated messages over Tor hidden services
|
||||
|
||||
### Trust Levels
|
||||
|
||||
- **Trusted**: Full access — can view status, deploy apps, sync state
|
||||
- **Observer**: Read-only access — can view status but not modify
|
||||
- **Untrusted**: Blocked from federation operations
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- No third-party trust dependency (no CA, no central server)
|
||||
- Works fully offline/air-gapped for the verification step
|
||||
- Strong cryptographic identity (Ed25519 keys)
|
||||
- Granular trust levels for different access patterns
|
||||
- Invite codes are single-use (no replay attacks)
|
||||
|
||||
### Negative
|
||||
|
||||
- Requires out-of-band code exchange (can't auto-discover peers for federation)
|
||||
- No revocation mechanism beyond removing the peer from the local trust store
|
||||
- Key rotation requires re-establishing trust with all peers
|
||||
- Trust is bilateral — each node maintains its own trust decisions
|
||||
|
||||
### Mitigations
|
||||
|
||||
- Nostr-based node discovery (ADR-003) handles finding nodes; federation handles trusting them
|
||||
- Tor hidden services provide transport encryption and anonymity
|
||||
- State sync includes heartbeat/health checks to detect unreachable peers
|
||||
@@ -0,0 +1,62 @@
|
||||
# ADR-008: Dual Key Strategy (Ed25519 + Secp256k1)
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Archipelago operates at the intersection of two cryptographic ecosystems:
|
||||
|
||||
- **Web5 / DIDs**: The W3C DID specification and Verifiable Credentials ecosystem predominantly uses **Ed25519** (EdDSA) for digital signatures
|
||||
- **Nostr / Bitcoin**: The Nostr protocol and Bitcoin ecosystem use **secp256k1** (ECDSA/Schnorr) for signatures
|
||||
|
||||
A single key type cannot serve both ecosystems without conversion layers or compatibility issues.
|
||||
|
||||
## Decision
|
||||
|
||||
Maintain **two key pairs per node identity**:
|
||||
|
||||
1. **Ed25519** — Primary identity key for DID documents, verifiable credentials, federation authentication, and backup encryption
|
||||
2. **Secp256k1** — Nostr-compatible key for relay publishing, node discovery, and Lightning Network interactions
|
||||
|
||||
### Key Derivation
|
||||
|
||||
- Both keys are derived from the same master seed during node initialization
|
||||
- The Ed25519 key is the canonical identity (stored in the DID document)
|
||||
- The secp256k1 key is linked to the DID via the Nostr profile (NIP-05 verification)
|
||||
|
||||
### Usage Matrix
|
||||
|
||||
| Operation | Key Used |
|
||||
|-----------|----------|
|
||||
| DID document signing | Ed25519 |
|
||||
| Verifiable credentials | Ed25519 |
|
||||
| Federation auth | Ed25519 |
|
||||
| Backup encryption | Ed25519 (via X25519 DH) |
|
||||
| Nostr event publishing | secp256k1 |
|
||||
| Node discovery | secp256k1 (Nostr) |
|
||||
| Lightning channel auth | secp256k1 |
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Full compatibility with both Web5 and Nostr ecosystems
|
||||
- No conversion layers or compatibility hacks needed
|
||||
- Each key type is used in its native context (maximum security)
|
||||
- Both keys from same seed — single backup protects both
|
||||
- Future-proof: can add new key types without breaking existing ones
|
||||
|
||||
### Negative
|
||||
|
||||
- Two keys to manage instead of one
|
||||
- Users need to understand which pubkey is which (mitigated by UI)
|
||||
- Key rotation must update both key types
|
||||
- Slightly larger DID documents (two verification methods)
|
||||
|
||||
### Mitigations
|
||||
|
||||
- UI presents a unified identity view — users see "My Identity" not "My Ed25519 Key"
|
||||
- Backup system captures the master seed, from which both keys derive
|
||||
- DID document includes both verification methods with clear purpose labels
|
||||
@@ -0,0 +1,77 @@
|
||||
# ADR-009: Manifest-Level Container Security Enforcement
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Archipelago runs third-party applications as containers. Without enforcement, containers could:
|
||||
|
||||
- Run as root and escalate privileges
|
||||
- Access the host filesystem
|
||||
- Modify their own binaries (persistence of malicious code)
|
||||
- Acquire unnecessary Linux capabilities
|
||||
- Use unverified or tampered container images
|
||||
|
||||
Other node OS projects (Umbrel, Start9) vary in their security enforcement. Archipelago targets a higher security bar suitable for handling Bitcoin private keys and personal data.
|
||||
|
||||
## Decision
|
||||
|
||||
Enforce security constraints at the **manifest level**, applied automatically during container creation. Every container MUST comply with these non-negotiable defaults:
|
||||
|
||||
### Mandatory Security Defaults
|
||||
|
||||
| Constraint | Value | Rationale |
|
||||
|-----------|-------|-----------|
|
||||
| `readonly_root` | `true` | Prevents runtime filesystem modification (anti-persistence) |
|
||||
| `no_new_privileges` | `true` | Prevents privilege escalation via setuid/setgid |
|
||||
| `user` | UID > 1000 | Never run as root |
|
||||
| `capabilities` | Drop ALL, add only required | Principle of least privilege |
|
||||
| `image_tag` | Pinned version | No `latest` tags — reproducible deploys |
|
||||
| `seccomp_profile` | Default | Blocks dangerous syscalls |
|
||||
|
||||
### Manifest Enforcement
|
||||
|
||||
The `core/container/` module validates manifests before container creation:
|
||||
|
||||
1. **Parse** the YAML manifest
|
||||
2. **Validate** all required security fields are present
|
||||
3. **Reject** manifests that violate mandatory defaults (e.g., `readonly_root: false` without explicit override)
|
||||
4. **Apply** security context during `podman create`
|
||||
|
||||
### Optional Overrides
|
||||
|
||||
Some apps legitimately need elevated privileges:
|
||||
|
||||
- `readonly_root: false` — Only for apps that must write to their root filesystem (documented reason required)
|
||||
- Additional capabilities (e.g., `NET_ADMIN` for VPN apps) — must be explicitly listed and justified
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Defense in depth — even if a container image is compromised, damage is limited
|
||||
- Consistent security posture across all apps
|
||||
- Transparent — users can inspect any app's security manifest
|
||||
- Aligns with industry best practices (CIS Benchmarks, NIST)
|
||||
|
||||
### Negative
|
||||
|
||||
- Some apps may not work without modifications (e.g., apps expecting root)
|
||||
- Read-only root requires explicit volume mounts for writable directories
|
||||
- Developers must understand and comply with the security model
|
||||
- Slightly more complex manifest format than competitors
|
||||
|
||||
### Mitigations
|
||||
|
||||
- Clear documentation in `docs/app-manifest-spec.md`
|
||||
- Example manifests for common app patterns
|
||||
- Build-time validation catches issues before deployment
|
||||
- Override mechanism for legitimate exceptions (with audit trail)
|
||||
|
||||
## References
|
||||
|
||||
- `docs/app-manifest-spec.md` — Full manifest specification
|
||||
- `core/container/src/` — Container security implementation
|
||||
- `core/security/src/` — AppArmor profiles and secrets management
|
||||
@@ -0,0 +1,31 @@
|
||||
# ADR-011: DWN Deprioritization
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
TBD/Block shut down in November 2024, donating Web5 code to the Decentralized Identity Foundation (DIF). The DWN (Decentralized Web Node) specification was heavily backed by TBD — without their engineering team, the spec has lost momentum:
|
||||
|
||||
- No maintained Rust DWN SDK exists (the `dwn` crate by unavi-xyz is v0.4.0 with 323 downloads)
|
||||
- TBD's reference implementation was TypeScript-only
|
||||
- DIF has not allocated resources to continue DWN development
|
||||
- The spec itself is complex (personal data stores with protocol-based access control)
|
||||
|
||||
Meanwhile, Archipelago's federation over Tor + Nostr relays already serves the core peer data sync use case that DWN was intended for.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **Keep existing DWN store code** in `core/archipelago/src/network/dwn_store.rs` — it works for peer file catalogs and federation state
|
||||
2. **Stop calling it "Web5 DWN"** in user-facing text — it's our custom implementation, not a full DWN spec implementation
|
||||
3. **Do not invest in DWN spec compliance** — the spec is stalled and may not stabilize
|
||||
4. **Prioritize Nostr + federation** for peer discovery and data exchange
|
||||
5. **Re-evaluate if DIF produces a viable Rust SDK** or the spec gains new maintainers
|
||||
|
||||
## Consequences
|
||||
|
||||
- DWN functionality remains available but is not actively developed
|
||||
- Peer sync uses federation + Nostr instead of DWN protocols
|
||||
- Reduces maintenance burden — no need to track a stalled spec
|
||||
- If DWN resurfaces with strong tooling, we can adopt it later
|
||||
Reference in New Issue
Block a user