upleb.uk

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

summaryrefslogtreecommitdiff
path: root/docs/archive/2025-11-04-evening/review-summary.md
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-11-05 06:37:21 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-11-05 06:37:21 +0000
commit5cd47079ee762125817612d2bf82a0bca07da3ad (patch)
tree89f490b9cb981467c27467a0a826bdbfa229cfd9 /docs/archive/2025-11-04-evening/review-summary.md
parent9ae69e7f6854d44f75ebd16f11ba5c95a45a56bf (diff)
preparing to build grasp-audit against git-relay
Diffstat (limited to 'docs/archive/2025-11-04-evening/review-summary.md')
-rw-r--r--docs/archive/2025-11-04-evening/review-summary.md513
1 files changed, 513 insertions, 0 deletions
diff --git a/docs/archive/2025-11-04-evening/review-summary.md b/docs/archive/2025-11-04-evening/review-summary.md
new file mode 100644
index 0000000..29a3ff4
--- /dev/null
+++ b/docs/archive/2025-11-04-evening/review-summary.md
@@ -0,0 +1,513 @@
1# GRASP Protocol Review Summary
2
3**Date:** November 4, 2025
4**Purpose:** Document key findings from reviewing GRASP protocol and ngit-relay
5
6---
7
8## 🎯 Critical Discoveries
9
10### 1. Single Port Architecture (CRITICAL!)
11
12**Finding:** Git server and Nostr relay MUST run on the SAME port.
13
14**Evidence:**
15```yaml
16# ../ngit-relay/docker-compose.yml
17ports:
18 - "8081:8081" # Single port only!
19```
20
21```nginx
22# ../ngit-relay/src/nginx.conf
23server {
24 listen 8081; # One listener for everything
25
26 location ~ ^/npub1([a-z0-9]+)/([^/]+\.git)(/.*)?$ {
27 # Git HTTP via fcgiwrap
28 }
29
30 location / {
31 # Nostr relay via proxy to localhost:3334
32 }
33}
34```
35
36**Impact:**
37- Our current architecture is WRONG
38- We assumed separate ports (relay on 8080, git on 8081)
39- Must use HTTP router to split traffic by path
40- actix-web can handle this
41
42**Action Required:**
43- Integrate actix-web for HTTP routing
44- Route `/<npub>/<id>.git` to Git handler
45- Route `/` to Nostr relay (WebSocket upgrade)
46- Apply CORS to ALL routes
47
48---
49
50### 2. GRASP-01 Test Requirements
51
52**Finding:** Tests must closely map to GRASP protocol specification.
53
54**GRASP-01 Requirements (from ../grasp/01.md):**
55
56#### Nostr Relay (Lines 1-14)
57- ✅ Serve NIP-01 relay at `/` (WebSocket)
58- ⏳ Accept NIP-34 repository announcements (kind 30617)
59- ⏳ Accept NIP-34 state announcements (kind 30618)
60- ⏳ Reject announcements without service in `clone` and `relays` tags
61- ⏳ Accept events that tag accepted announcements
62- ✅ Serve NIP-11 relay information
63- ⏳ Include `supported_grasps`, `repo_acceptance_criteria`, `curation` in NIP-11
64
65#### Git Smart HTTP (Lines 15-31)
66- ❌ Serve repos at `/<npub>/<identifier>.git`
67- ❌ Accept pushes matching state announcements
68- ❌ Respect recursive maintainer sets
69- ❌ Set HEAD per state announcement
70- ❌ Accept pushes to `refs/nostr/<event-id>` for PRs
71- ❌ Include `allow-reachable-sha1-in-want` and `allow-tip-sha1-in-want`
72- ❌ Serve webpage for browsers
73
74#### CORS Support (Lines 32-40)
75- ❌ `Access-Control-Allow-Origin: *` on ALL responses
76- ❌ `Access-Control-Allow-Methods: GET, POST` on ALL responses
77- ❌ `Access-Control-Allow-Headers: Content-Type` on ALL responses
78- ❌ Respond to OPTIONS with 204 No Content
79
80**Action Required:**
81- Create test for each requirement
82- Reference GRASP-01 line numbers in test comments
83- Example:
84 ```rust
85 #[tokio::test]
86 async fn test_git_http_basic() {
87 // Reference: ../grasp/01.md line 15
88 // MUST serve git repository via unauthenticated git smart http
89 // ...
90 }
91 ```
92
93---
94
95### 3. Environment Variables
96
97**Finding:** ngit-relay uses specific environment variables we should match.
98
99**From ../ngit-relay/.env.example:**
100
101```bash
102# Service Configuration
103NGIT_DOMAIN=example.com # For announcement validation
104NGIT_INTERNAL_RELAY_PORT_FOR_SSL_PROXY=8081 # We don't need this
105
106# Relay Information (NIP-11)
107NGIT_RELAY_NAME="..."
108NGIT_RELAY_DESCRIPTION="..."
109NGIT_OWNER_NPUB="..."
110
111# Features
112NGIT_PROACTIVE_SYNC_GIT=true # GRASP-02 (future)
113NGIT_PROACTIVE_SYNC_BLOSSOM=true # Not in GRASP
114NGIT_PROACTIVE_SYNC_NOSTR=true # GRASP-02 (future)
115
116# Blossom Settings
117NGIT_BLOSSOM_MAX_FILE_SIZE_MB=100 # Not in GRASP
118NGIT_BLOSSOM_MAX_CAPACITY_GB=50 # Not in GRASP
119
120# Logging
121NGIT_LOG_DIR=/var/log/ngit-relay
122NGIT_LOG_LEVEL=INFO
123NGIT_LOG_MAX_SIZE_MB=20
124NGIT_LOG_MAX_BACKUPS=10
125NGIT_LOG_MAX_AGE_DAYS=30
126```
127
128**Our Environment Variables:**
129
130```bash
131# Service Configuration
132NGIT_DOMAIN=example.com # REQUIRED - for announcement validation
133NGIT_BIND_ADDRESS=127.0.0.1:8080 # REQUIRED - single port
134
135# Relay Information (NIP-11)
136NGIT_RELAY_NAME="ngit-grasp instance"
137NGIT_RELAY_DESCRIPTION="Rust GRASP implementation"
138NGIT_OWNER_NPUB="npub1..."
139
140# Storage Paths
141NGIT_GIT_DATA_PATH=./data/repos # REQUIRED - where to store Git repos
142NGIT_RELAY_DATA_PATH=./data/relay # REQUIRED - where to store events
143
144# Logging
145NGIT_LOG_LEVEL=INFO
146RUST_LOG=info # Standard Rust logging
147```
148
149**Action Required:**
150- Update `.env.example` with all required fields
151- Add `NGIT_GIT_DATA_PATH` to config
152- Document which fields are required vs. optional
153
154---
155
156### 4. Repository Path Structure
157
158**Finding:** Repository storage follows specific pattern.
159
160**Pattern:** `{GIT_DATA_PATH}/{npub}/{identifier}.git`
161
162**Example:**
163```
164./data/repos/
165├── npub1abc.../
166│ ├── my-project.git/
167│ │ ├── HEAD
168│ │ ├── config
169│ │ ├── objects/
170│ │ └── refs/
171│ └── another-repo.git/
172└── npub1xyz.../
173 └── their-project.git/
174```
175
176**Action Required:**
177- Create repository directory structure
178- Initialize bare repositories (`git init --bare`)
179- Set ownership/permissions correctly
180- Clean up on repository deletion
181
182---
183
184### 5. NIP-11 GRASP Fields
185
186**Finding:** NIP-11 relay information must include GRASP-specific fields.
187
188**From ../grasp/01.md lines 11-14:**
189
190```json
191{
192 "name": "ngit-grasp instance",
193 "description": "Rust GRASP implementation",
194 "pubkey": "...",
195 "contact": "...",
196 "supported_nips": [1, 11, 34],
197 "supported_grasps": ["GRASP-01"], // NEW - array of strings
198 "repo_acceptance_criteria": "...", // NEW - human readable
199 "curation": "WoT-based spam prevention" // NEW - optional
200}
201```
202
203**Action Required:**
204- Add `supported_grasps` field to NIP-11 response
205- Add `repo_acceptance_criteria` field
206- Add `curation` field (optional)
207- Update NIP-11 tests to verify these fields
208
209---
210
211### 6. Announcement Validation
212
213**Finding:** Relay must validate announcements list this service.
214
215**From ../grasp/01.md lines 3-5:**
216
217> MUST reject [git repository announcements] that do not list the service
218> in both `clone` and `relays` tags unless implementing `GRASP-05`.
219
220**NIP-34 Repository Announcement (kind 30617):**
221```json
222{
223 "kind": 30617,
224 "tags": [
225 ["d", "my-project"], // identifier
226 ["name", "My Project"],
227 ["clone", "https://example.com/npub.../my-project.git"],
228 ["clone", "https://github.com/user/my-project"],
229 ["relays", "wss://example.com"],
230 ["relays", "wss://relay.nostr.band"]
231 ]
232}
233```
234
235**Validation Logic:**
236```rust
237fn validate_announcement(event: &Event, our_domain: &str) -> Result<()> {
238 // Check for clone tag with our domain
239 let has_clone = event.tags.iter().any(|tag| {
240 tag.kind() == TagKind::Custom("clone".into()) &&
241 tag.content().map(|c| c.contains(our_domain)).unwrap_or(false)
242 });
243
244 // Check for relays tag with our domain
245 let has_relay = event.tags.iter().any(|tag| {
246 tag.kind() == TagKind::Custom("relays".into()) &&
247 tag.content().map(|c| c.contains(our_domain)).unwrap_or(false)
248 });
249
250 if !has_clone || !has_relay {
251 return Err(anyhow!("Announcement must list this service in both clone and relays tags"));
252 }
253
254 Ok(())
255}
256```
257
258**Action Required:**
259- Implement announcement validation
260- Check both `clone` and `relays` tags
261- Reject if service not listed
262- Add tests for validation
263
264---
265
266### 7. State Announcement Handling
267
268**Finding:** State announcements control repository state.
269
270**NIP-34 Repository State (kind 30618):**
271```json
272{
273 "kind": 30618,
274 "tags": [
275 ["d", "my-project"], // identifier
276 ["refs/heads/main", "abc123..."], // branch → commit
277 ["refs/heads/develop", "def456..."],
278 ["HEAD", "ref: refs/heads/main"], // symbolic ref
279 ["maintainers", "npub1...", "npub2..."] // maintainer set
280 ]
281}
282```
283
284**State Handling:**
2851. When state announcement received:
286 - Update repository HEAD if needed
287 - Store state for push validation
288 - Handle maintainer set
289
2902. When push received:
291 - Query latest state announcement
292 - Validate pusher is in maintainer set (recursive)
293 - Validate ref updates match state
294 - Accept or reject push
295
296**Action Required:**
297- Parse state announcements
298- Update repository HEAD
299- Implement push validation
300- Handle recursive maintainer sets
301
302---
303
304### 8. PR Ref Handling
305
306**Finding:** Special handling for PR refs.
307
308**From ../grasp/01.md lines 22-23:**
309
310> MUST accept pushes via this service to `refs/nostr/<event-id>` but SHOULD
311> reject if event exists on relay listing a different tip and MAY reject based
312> on criteria such as size, SPAM prevention, etc. SHOULD delete and MAY garbage
313> collect these refs if no corresponding [git PR event] or [git PR update event],
314> with a `c` tag that matches the ref tip, is accepted by relay with 20 minutes.
315
316**PR Ref Lifecycle:**
3171. Push to `refs/nostr/<event-id>`
3182. Verify PR event exists on relay
3193. Verify ref tip matches PR event `c` tag
3204. Accept push
3215. After 20 minutes, check if PR event still exists
3226. If not, delete ref and garbage collect
323
324**Action Required:**
325- Accept pushes to `refs/nostr/<event-id>`
326- Validate against PR events
327- Implement 20-minute timeout
328- Implement garbage collection
329
330---
331
332### 9. Git HTTP Protocol Details
333
334**Finding:** Must support specific Git protocol features.
335
336**From ../grasp/01.md lines 25-26:**
337
338> MUST include `allow-reachable-sha1-in-want` and `allow-tip-sha1-in-want`
339> in advertisement and serve available oids.
340
341**Git Capabilities:**
342```
343# info/refs response must include:
344allow-reachable-sha1-in-want
345allow-tip-sha1-in-want
346```
347
348**Action Required:**
349- Configure git-http-backend to advertise these capabilities
350- Ensure Git process is configured correctly
351- Test with actual Git client
352
353---
354
355### 10. CORS Requirements
356
357**Finding:** CORS must be on ALL responses, not just some.
358
359**From ../grasp/01.md lines 32-40:**
360
361```
3621. Set `Access-Control-Allow-Origin: *` on ALL responses
3632. Set `Access-Control-Allow-Methods: GET, POST` on ALL responses
3643. Set `Access-Control-Allow-Headers: Content-Type` on ALL responses
3654. Respond to OPTIONS requests with 204 No Content
366```
367
368**Implementation:**
369```rust
370// In actix-web
371App::new()
372 .wrap(
373 Cors::default()
374 .allow_any_origin()
375 .allowed_methods(vec!["GET", "POST"])
376 .allowed_headers(vec!["Content-Type"])
377 .max_age(3600)
378 )
379 // ... routes
380```
381
382**Action Required:**
383- Add CORS middleware to actix-web
384- Verify headers on all responses
385- Handle OPTIONS requests
386- Test with browser
387
388---
389
390## 📊 Compliance Status
391
392### NIP-01 (Nostr Relay)
393- ✅ WebSocket connection
394- ✅ EVENT message handling
395- ✅ REQ subscription
396- ✅ CLOSE subscription
397- ✅ Event validation
398- ⏳ NIP-11 with GRASP fields
399
400**Status:** ~80% complete
401
402### NIP-34 (Git Announcements)
403- ✅ Store announcements (kind 30617)
404- ✅ Store state events (kind 30618)
405- ⏳ Validate announcements list this service
406- ⏳ Handle maintainer sets
407- ⏳ Accept related events
408
409**Status:** ~40% complete
410
411### GRASP-01 (Core Requirements)
412- ✅ Nostr relay at `/`
413- ❌ Git HTTP at `/<npub>/<id>.git`
414- ❌ Push validation
415- ❌ Repository provisioning
416- ❌ CORS support
417
418**Status:** ~20% complete
419
420---
421
422## 🎯 Immediate Next Steps
423
424### 1. Fix Architecture (CRITICAL)
425- [ ] Add actix-web dependencies
426- [ ] Create HTTP router module
427- [ ] Route Git paths to Git handler
428- [ ] Route `/` to Nostr relay (WebSocket)
429- [ ] Apply CORS to all routes
430
431**Estimated Time:** 2-4 hours
432**Priority:** CRITICAL
433**Blocker:** Nothing else can proceed without this
434
435### 2. Add Git HTTP Backend
436- [ ] Integrate git-http-backend crate
437- [ ] Create Git request handler
438- [ ] Serve from `{GIT_DATA_PATH}/{npub}/{id}.git`
439- [ ] Return 404 for missing repos
440- [ ] Test with `git clone`
441
442**Estimated Time:** 2-3 hours
443**Priority:** HIGH
444**Blocker:** Requires architecture fix
445
446### 3. Repository Provisioning
447- [ ] Create repos when announcements received
448- [ ] Initialize bare repositories
449- [ ] Set up directory structure
450- [ ] Handle repository deletion
451
452**Estimated Time:** 1-2 hours
453**Priority:** HIGH
454**Blocker:** Requires Git HTTP backend
455
456### 4. Update Tests
457- [ ] Add GRASP-01 line number references
458- [ ] Create Git HTTP tests
459- [ ] Create CORS tests
460- [ ] Update NIP-11 tests
461
462**Estimated Time:** 2-3 hours
463**Priority:** MEDIUM
464**Blocker:** None (can start now)
465
466---
467
468## 📚 Key Files to Reference
469
470### GRASP Protocol
471- `../grasp/01.md` - **THE SPEC** - Lines 1-40
472- `../grasp/README.md` - Overview
473- `../grasp/02.md` - GRASP-02 (future)
474- `../grasp/05.md` - GRASP-05 (future)
475
476### Reference Implementation
477- `../ngit-relay/src/nginx.conf` - **ROUTING PATTERN** - Lines 8-94
478- `../ngit-relay/docker-compose.yml` - Port configuration
479- `../ngit-relay/.env.example` - Environment variables
480- `../ngit-relay/README.md` - Architecture overview
481
482### Our Code
483- `tests/nip01_compliance.rs` - Current test approach
484- `tests/common/relay.rs` - TestRelay fixture (already correct!)
485- `src/nostr/relay.rs` - Current relay implementation
486- `src/config.rs` - Configuration (needs Git path)
487
488---
489
490## ✅ Checklist for Next Session
491
492Before starting implementation:
493- [x] Read GRASP-01 specification (../grasp/01.md)
494- [x] Review ngit-relay nginx.conf routing
495- [x] Understand single-port architecture
496- [x] Review environment variables
497- [x] Understand repository path structure
498
499Ready to implement:
500- [ ] Add actix-web dependencies to Cargo.toml
501- [ ] Create src/http/mod.rs module
502- [ ] Create src/http/git.rs handler
503- [ ] Create src/http/nostr.rs handler
504- [ ] Update src/main.rs
505- [ ] Update src/config.rs
506- [ ] Update .env.example
507- [ ] Update tests/common/relay.rs
508- [ ] Create tests/grasp01_git_http.rs
509
510---
511
512**Last Updated:** November 4, 2025
513**Next Review:** After actix-web integration