blob: 1911a20172593f78d66c26c5479915d60bfbec7b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# grasp-mirror Plan
## Completed
- [x] Fix `push_mirror` in `src/git_mirror.rs` — reuse existing `push_target` remote via `remote_set_url`
- [x] Fix `mirror_cycle` in `src/main.rs` — make per-repo errors non-fatal
- [x] Add HTTP health endpoint (`/health`, `/api/mirror-health`) on port 7335
- [x] Mirror repos from 3 npubs
- [x] Ansible role, playbook, systemd unit, config templates
- [x] Dashboard integration on `services.orangesync.tech`
- [x] Watchdog integration
## Phase 3: NIP-46 Remote Signing via Amber
### Problem
GRASP servers reject unauthenticated git pushes. Authorization requires a `kind:30618` state event signed by a maintainer's key. The daemon needs to sign these events but should never hold raw nsec keys.
### Solution
NIP-46 (Nostr Connect) remote signing via Amber on the user's phone. The daemon acts as a NIP-46 client, sends `sign_event:30618` requests to Amber, and waits for approval before pushing.
### Architecture
```
VPS: grasp-mirror ←→ relays ←→ Amber (phone)
- discovers repos - NIP-46 kind:24133
- builds state events - sign_event:30618
- queues signing - user approves
- publishes event - returns signature
- git push
services.orangesync.tech
- pairing UI + QR codes
- status display
```
### Config
```toml
[nip46]
relays = ["wss://relay.orangesync.tech", "wss://ngit.orangesync.tech"]
signing_timeout_secs = 604800 # 7 days
```
### Checklist
- [ ] Add `nip46_sessions` and `signing_queue` tables to `src/db.rs`
- [ ] Build `src/nip46.rs` — NIP-46 client with session management
- Generate client keypair per npub, persist to SQLite
- Build `nostrconnect://` URIs with `perms=sign_event:30618`
- Listen for `kind:24133` events on configured relays
- Handle connect/get_public_key/sign_event handshake
- `sign_state_event(npub, state_event) -> Result<SignedEvent>` method
- Auto-reconnect on session drop
- [ ] Wire NIP-46 into `src/main.rs` daemon startup — connect sessions for all 3 npubs
- [ ] Modify `src/git_mirror.rs` — before push, build `kind:30618` state event, request signature via NIP-46
- [ ] Add pairing URI + NIP-46 status to health endpoint (`/api/mirror-health`)
- [ ] Update dashboard HTML (`static/services/index.html`) with pairing UI + QR codes
- [ ] Update Ansible config template with `[nip46]` section
- [ ] Add `health_port` to `[storage]` in config template (already done)
- [ ] Rebuild release binary
- [ ] Push to all 9 GRASP servers
- [ ] Redeploy via Ansible
- [ ] End-to-end test: pair npub via Amber, verify signing flow works
|