Desktop PDS — System Architecture#
v8 — Mobile-First Reconciliation · Four-Phase Milestones
Sovereign AT Protocol PDS on macOS via Tauri + Repo Engine + Iroh
Milestone Legend#
v0.1 — Mobile-Only PDS · relay is full PDS
v0.2 — Desktop Enrollment · relay as proxy+signer
v1.0 — Public Launch · product-ready
LATER — Designed, built post-launch
Changelog#
v8 Changes — Mobile-First Reconciliation#
Architecture reconciled with mobile architecture spec v1.2 (canonical). The relay is no longer just a tunnel+proxy — in the mobile-only phase, it IS the PDS.
- NEW Four-phase milestone model (v0.1 / v0.2 / v1.0 / v2.0+)
- NEW Phase 0: Mobile-Only lifecycle (relay as full PDS)
- FIX Signing model: relay always signs, device constructs unsigned commits
- FIX Tier model: Free/Pro/Business + BYO as deployment model
- FIX Firehose: native emission (mobile-only) vs proxy (desktop-enrolled)
- FIX Shamir: basic share generation moves to v0.1 (required at onboarding)
- FIX DID keystore: Shamir split required at account creation, not v1.0
- REF See unified-milestone-map.md for phase details
Previous Versions#
v2: Corrected relay model (outbound only). v3: Shamir key recovery + repo snapshots. v4: Conformance strategy. v5: Custom PDS shell + atrium/rsky deps. v6: GeoDNS + BYO relay. v7: Milestone scoping + runtime threats.
Device Lifecycle Phases#
The product launches mobile-first. The relay is a full PDS before any desktop is involved.
Phase: Mobile-Only (v0.1)
- Relay behavior: Full PDS — hosts repo, serves XRPC, signs commits, emits firehose
- Repo location: Relay (primary and only copy)
- Phone role: Identity wallet (key management, device admin)
- Desktop: Does not exist yet
Phase: Desktop-Enrolled (v0.2)
- Relay behavior: XRPC proxy + signer — forwards writes to desktop, signs commits, serves reads from cache
- Repo location: Desktop (primary), relay (cache)
- Phone role: Identity wallet + device manager
- Desktop: Runs repo engine, constructs unsigned commits
Phase: Desktop-Offline (v0.2+)
- Relay behavior: Serves reads from cache, 503 on writes
- Repo location: Desktop (authoritative but unreachable)
- Phone role: Same as desktop-enrolled
- Desktop: Sleeping / powered off
Layer 01 — Device Layer (Desktop, v0.2+)#
In v0.1 (Mobile-Only), there is no device layer. All operations run on the relay.
Tauri Shell#
v0.2
🖥️ Native macOS app. Process lifecycle, auto-updates, system tray. Minimal IPC allowlist — webview cannot access filesystem, shell, or network directly.
Repo Engine#
v0.2
📦 Purpose-built repo construction engine. SQLite-backed, local-first. Builds MST structures, constructs unsigned commits, manages collection storage. In desktop-enrolled mode, the relay proxies XRPC writes here, then signs the resulting commits. Does not serve XRPC directly to the network — the relay is always the network-facing endpoint.
Dependency Stack#
v0.1
🧩 atrium-api — XRPC types, lexicon defs (auto-generated). atrium-repo — MST read/write, CAR export. rsky-crypto — P-256/K-256 commit signing.
Iroh Endpoint#
v0.1
🔗 QUIC-based tunnel to relay. NAT traversal, connection resumption on wake. Pushes unsigned repo commits to relay for signing when online.
DID Keystore#
v0.1
🔐 Signing keys in macOS Keychain (desktop) / Secure Enclave (phone). At account creation, root rotation key is split via 2-of-3 Shamir: Share 1 = iCloud Keychain, Share 2 = relay escrow, Share 3 = user's choice (device-local or BIP-39 paper backup). Basic key management for v0.1. Full recovery UI in v1.0.
Recovery Share Manager#
v1.0
🛟 Full UI for Shamir share management and recovery ceremony. View share status, rotate shares, initiate recovery from device loss. Note: basic share GENERATION happens at v0.1 (during account creation). This component adds the management and recovery interface.
Compat Warning Banner#
v1.0
⚠️ Non-blocking in-app warning when spec drift detected. Links to update. Never blocks launch.
XRPC Hardening#
v1.0
🛡️ Request size limits on all endpoints. Rate limiting at relay. cargo-fuzz targets for CBOR/CAR/MST parsing paths. Adversarial MST key distribution testing per ATProto spec guidance.
REMOVED: rsky-pds (fork) — Replaced by repo engine in v5. Now tracking a spec, not a codebase.
Layer 02 — Relay Layer (Managed + BYO)#
Managed Relay (Your Infrastructure)#
Iroh Relay Node#
v0.1
🚇 Single-region for v0.1. Always-on tunnel endpoint. In mobile-only mode, serves as full PDS — no tunnel needed, relay handles all XRPC directly. In desktop-enrolled mode, acts as tunnel endpoint for device ↔ relay communication. Receives unsigned commits from device, constructs signed commits, proxies XRPC repo reads.
requestCrawl Trigger#
v0.1
📣 On device reconnect, pings BGS requestCrawl so new content propagates immediately.
Firehose Emitter#
v0.1
📡 Native com.atproto.sync.subscribeRepos WebSocket endpoint. Required for federation — every PDS must emit a firehose. In mobile-only mode, the relay is the PDS and emits directly. In desktop-enrolled mode, emits commits as they're signed.
Firehose Proxy#
v0.2
📡 Maintains persistent BGS WebSocket on behalf of sleeping desktop. Replays commits from buffer when desktop reconnects. Ensures BGS sees continuous uptime even when desktop is offline. Desktop-enrolled feature — not applicable in mobile-only mode. Pro/Business tier on managed relay.
Commit Buffer#
v0.2
💾 Rolling log of signed repo commits. Feeds firehose proxy during offline. Tiered retention: 7d free, 30d paid, 90d business.
Provisioning API#
v0.1
⚙️ Account setup, domain linking, relay config. Onboarding flow for new connections. Core provisioning needed from day one.
Key Share Escrow#
v0.1
🔏 Holds one encrypted Shamir share. Cannot reconstruct alone. Encrypted at rest, access-logged. Relay holds Share 2 from account creation.
Health Monitor#
v1.0
💓 Device liveness, relay uptime, ATProto spec compat. Includes canary account for silent federation failure detection.
GeoDNS Multi-Region#
LATER
🌎 2–3 relay nodes, route to nearest healthy. Simple failover with brief firehose gap. Cross-region replication interface designed but not built.
Repo Snapshot#
LATER
🗄️ Full repo backup on relay. Incremental from commit buffer. Pro+ feature. Enables one-click device migration.
CDN / Public Cache#
LATER
🌐 Serves public repo content during offline windows.
BYO Relay (User-Hosted, Free)#
Relay Binary#
v1.0
📦 Open-source. Nix flake (source of truth) → Docker image + NixOS module. Tunnel + commit forwarding + requestCrawl. No firehose proxy, no snapshots.
Device-Relay Protocol Spec#
v1.0
📜 Documented contract: handshake/auth, commit push, health ping, optional feature negotiation. Includes commit ack for future trust verification.
Feature Negotiation#
v1.0
🔌 App queries relay capabilities on connect. Gracefully degrades when extended features unavailable. Suggests upgrade for missing features.
REMOVED: Inbound Message Queue — Not needed. ATProto records live in author's repo.
Data Flow#
Desktop-Enrolled Write Path#
- App creates record via XRPC (Tauri webview → Rust backend)
- Repo Engine constructs MST diff + unsigned commit
- Unsigned commit sent to relay via Iroh tunnel
- Relay signs commit with P-256 signing key
- Relay stores signed commit in buffer
- Relay emits to firehose / serves via XRPC
Mobile-Only Write Path (v0.1)#
- Third-party app (e.g. Bluesky) calls relay XRPC directly
- Relay constructs record, MST diff, signs commit
- Relay stores and emits to firehose
Desktop-Offline Read Path#
- XRPC read request hits relay
- Relay serves from commit buffer / repo cache
- Writes return 503 (relay cannot construct commits from stale state)
Data Flow — How Bob's Post Reaches the Network#
Current scenario showing firehose proxy operation during v0.2+:
Bob's Mac (Repo Engine constructs unsigned commit) → Iroh tunnel → Relay (Signs commit with P-256 key) → Commit Buffer (Persists signed commit) → Firehose Proxy (Stable WebSocket) → subscribeRepos → BGS (Network firehose) → indexes → AppView (Bluesky etc.)
If Bob's Mac is asleep → relay serves reads from cache, returns 503 on writes. Commit buffer feeds firehose proxy from stored commits on wake.
Recovery Flow — Device Migration / Dead SSD (v1.0+)#
New Mac (Installs Tauri app) → authenticates → 2-of-3 Shares (iCloud + relay escrow) → reconstructs → Rotation Key (Shamir recombination) → did:plc op → Key Rotation (New signing key) → syncs → Repo Snapshot (Full repo restore)
Share sources (any 2 of 3):
- ① iCloud Keychain
- ② Relay escrow
- ③ Exported recovery file
- Future: ④ Trusted contact (social recovery) — interface designed, not yet shipped
Layer 03 — Infrastructure (ATProto Network)#
Federation#
v0.1
🌍 PDS participates in ATProto network via relay. DID document points to relay URL as canonical PDS endpoint.
DNS / Domain Automation#
v1.0
🔤 Handle-as-domain resolution. Automated DNS config for custom domain handles.
DID Resolution#
v0.1
🪪 did:plc or did:web pointing to relay endpoint. Relay always reachable, DID resolution never fails due to offline device.
Layer 04 — Ops (Security, Conformance & Updates)#
Update & Supply Chain Security#
2-of-3 Threshold Signing#
v1.0
🔑 CI key + offline engineer key + cold storage. Compromised CI alone cannot ship malicious updates.
Transparency Log#
LATER
📋 Sigstore-backed. Every release publicly logged.
Apple Notarization#
v1.0
🍎 First verification layer via Tauri build pipeline.
Responsible Disclosure#
v1.0
📬 security@ + published PGP key from day one.
cargo-audit in CI#
v0.1
📦 Dependency vulnerability scanning on every build. Pin exact versions in Cargo.lock. Review diffs on dep updates. Verify atrium codegen input against upstream lexicons.
Conformance Testing#
L1: Interop Test Vectors#
v0.1
🧪 Every commit. Official atproto-interop-tests + interop-test-files. Byte-level checks for MST, CAR, CBOR, CID, commit proofs. Strict MST validation.
L2: Oracle Compat Suite#
v1.0
🔬 Nightly CI. Docker Compose: reference TypeScript PDS vs your Rust PDS. Compare CAR output, firehose events, MST roots.
L3: Production Canary#
v1.0
🐤 Live account on real Bluesky via your relay. Health monitor verifies posts appear in AppView. Catches silent federation failures.
Runtime Threat Mitigations#
XRPC Input Hardening#
v1.0
🔒 Request size limits per endpoint. Rate limiting at relay layer. cargo-fuzz targets for CBOR/CAR/MST parsing. Adversarial MST key testing per spec DoS guidance.
Tauri IPC Lockdown#
v0.1
🏗️ Minimal allowlist: create/list/get records + status. Webview cannot access filesystem, shell, HTTP, or crypto. All sensitive ops in Rust backend only.
Relay Trust Verification#
LATER
🤝 Device verifies commits appear in firehose. Protocol designed now (commit ack with seq number), verification logic built later. Protects against censorship by relay.
Relay Tier Pricing — v1.0 Launch#
Free#
$0/mo
- Iroh tunnel (NAT traversal)
- Basic XRPC proxy
- 7-day commit buffer
- Key share escrow (1 share)
- Apple notarized updates
- No firehose proxy — BGS drops on sleep
- See "BYO Relay" section for self-hosted option
Pro#
$X/mo
- Everything in Free
- Stable firehose proxy (always-on WebSocket)
- 30-day commit buffer
- CDN cache for public content
- requestCrawl auto-trigger
- Custom domain handle
- Multi-region GeoDNS (post-launch)
- Full repo snapshot (post-launch)
- One-click device migration
Business#
$XX/mo
- Everything in Pro
- 90-day commit buffer
- Continuous repo snapshot (post-launch)
- Admin dashboard
- Priority support
- Custom relay config
- Audit logs
BYO Relay (Self-Hosted)#
Not a subscription tier — an alternative deployment model. Operators run their own relay binary (distributed via Nix flake or Docker image).
Includes:
- Full relay functionality (identical binary to managed relay)
- SQLite or PostgreSQL backend (operator's choice)
- Local or S3-compatible blob storage
- No subscription fees — operator provides their own infrastructure
- No managed monitoring or support
Available at v1.0 launch.
All Questions Resolved#
✅ Availability — v0.1+#
Firehose emitter for native federation. Firehose proxy + commit buffer for v0.2+. In mobile-only phase, relay is the PDS. In desktop-enrolled, relay maintains persistent connection for sleeping device.
✅ Durability — v1.0+#
2-of-3 Shamir key recovery. Tiered repo snapshots. iCloud + file export + relay escrow.
✅ Spec Drift — v0.1+#
Repo Engine (atrium + rsky-crypto). 3-layer conformance: interop vectors → oracle → canary.
✅ Relay Redundancy — v1.0+#
GeoDNS multi-region + BYO relay (Nix/Docker, free). Device-relay protocol spec. Feature negotiation.
✅ Runtime Threats — v1.0+#
XRPC fuzzing + size limits. Tauri IPC lockdown. Commit ack protocol (designed). cargo-audit. Relay trust verification (designed, deferred).
✅ Mobile-First Architecture — v8#
Relay is full PDS in v0.1. Desktop enrolls in v0.2 as repo construction engine. Four-phase milestones reconcile mobile and desktop workflows.
Milestone Summary — Four Phases#
v0.1 — Mobile-Only PDS (~3–4 months)#
Goal: User creates ATProto identity from iPhone, logs into Bluesky. Relay is a full PDS. No desktop involved.
Relay: Axum + SQLite + repo engine + signing + XRPC + firehose emitter OAuth: atproto-oauth-axum integration (blocks Bluesky login) Blobs: upload/serve with local storage Identity: DID creation + Shamir split at onboarding Federation: 25 XRPC endpoints (see unified-milestone-map.md §2.1) Testing: L1 interop tests + cargo-audit
v0.2 — Desktop Enrollment (~2–3 months)#
Goal: User pairs desktop Mac, relay becomes proxy+signer.
Device pairing: via QR code + desktop promotion XRPC write proxying: relay → desktop → relay signs Firehose proxy: for sleeping desktop Blob forwarding: via Iroh Desktop offline: → 503 on writes, reads from cache
v1.0 — Production Launch (~3–4 months)#
Goal: Production-ready product with recovery and self-hosting.
Shamir recovery ceremony: + full share management UI Tier pricing: Free/Pro/Business BYO relay binary: Nix/Docker S3 blob backend: + CDN PostgreSQL option: for scale L2 oracle suite + L3 canary XRPC hardening: + rate limiting
v2.0+ — Signing Sovereignty (TBD)#
Goal: User's hardware signs commits directly. Contingent on: ATProto protocol evolution (multi-key support).