# GRASP Mirror Daemon — Implementation Plan A Rust daemon that discovers repos from watched npubs and mirrors git data + Nostr events across all known GRASP servers for redundancy. ## Phase 1: Core (MVP) ### Infrastructure - [x] Cargo.toml with dependencies - [x] Project directory structure - [x] PLAN.md (this file) - [ ] config.example.toml - [ ] .env.example - [ ] SQLite migration schema ### Source Modules - [ ] `config.rs` — TOML config + .env loading, npub parsing, server list - [ ] `db.rs` — SQLite state tracking (repos, sync status, event dedup) - [ ] `health.rs` — NIP-11 GRASP server verification and health checks - [ ] `discovery.rs` — Relay subscriptions for kind:30617/10317/30618, repo parsing - [ ] `git_mirror.rs` — Bare clone + `git push --mirror` to missing GRASP servers - [ ] `nostr_mirror.rs` — Forward Nostr events to all GRASP server relays - [ ] `signing.rs` — Optional: update announcements to include mirrored servers - [ ] `main.rs` — CLI entry point, daemon loop, signal handling ## Phase 2: Resilience - [ ] Continuous state sync (watch kind:30618, push new refs to missing servers) - [ ] Periodic NIP-11 health checks on all known GRASP servers - [ ] Auto-discover new GRASP servers from indexer kind:10317 events - [ ] Retry with exponential backoff for failed mirrors - [ ] SIGHUP hot-reload of npub list from .env ## Phase 3: Advanced - [ ] Per-npub / per-repo server allowlists and blocklists - [ ] Prometheus metrics endpoint - [ ] CLI status subcommand (show mirror health per repo/server) - [ ] Web dashboard ## Known GRASP Servers | Server | Software | GRASP Support | |--------|----------|---------------| | `relay.ngit.dev` | ngit-grasp 1.1.0 | 01/02/06 | | `gitnostr.com` | ngit-grasp 1.0.2 | 01/02/06 | | `git.orangesync.tech` | ngit-grasp 0.1.0 | 01/02/05 | | `ngit.danconwaydev.com` | ngit-grasp 1.0.2 | 01/02/06 | | `git.shakespeare.diy` | ngit-grasp 1.0.1 | 01/02 | | `git.upleb.uk` | ngit-grasp 1.0.2 | 01/02 | | `grasp.budabit.club` | ngit-grasp 1.0.2 | 01/02 | | `git.uid.ovh` | ngit-grasp 1.0.2 | 01/02 | | `git.vps.satsnode.xyz` | ngit-grasp 1.0.1 | 01/02 | ## Architecture ``` ┌─────────────────────────────────────────────────────┐ │ grasp-mirror │ │ │ │ ┌────────────────┐ ┌─────────────────────────┐ │ │ │ Discovery │ │ Mirror Engine │ │ │ │ ──────────── │ │ ──────────────────── │ │ │ │ • Index relay │────▶│ For each repo: │ │ │ │ • GRASP relays│ │ 1. git clone --bare │ │ │ │ • kind:30617 │ │ from any source │ │ │ │ • kind:10317 │ │ 2. git push --mirror │ │ │ │ • kind:30618 │ │ to missing servers │ │ │ │ │ │ 3. Republish nostr │ │ │ └────────────────┘ │ events to all relays │ │ │ └─────────────────────────┘ │ │ ┌────────────────┐ ┌─────────────────────────┐ │ │ │ Config │ │ State DB (SQLite) │ │ │ │ ──────────── │ │ ──────────────────── │ │ │ │ config.toml │ │ • repos seen │ │ │ │ .env (npubs) │ │ • last sync per server │ │ │ │ [optional] │ │ • sync status/errors │ │ │ │ nsec for │ │ • event ids processed │ │ │ │ signing │ └─────────────────────────┘ │ │ └────────────────┘ │ └─────────────────────────────────────────────────────┘ ``` ## Data Flow 1. **Discovery**: Subscribe to index relay for kind:30617 from watched npubs 2. **Parse**: Extract repo identifier, clone URLs, relay URLs from each announcement 3. **Diff**: Compare clone URLs against known GRASP servers to find missing mirrors 4. **Mirror Git**: - `git clone --bare` from any available clone URL - For each missing GRASP server: publish announcement to its relay (triggers repo creation), then `git push --mirror` 5. **Mirror Nostr**: Forward all related events (issues, comments, state) to all GRASP server relays 6. **Track**: Record mirror status in SQLite, skip already-mirrored repos on restart