upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/PLAN.md
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