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/architecture-diagram.md
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-12-03 11:19:40 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-12-03 11:19:40 +0000
commit2eaff5b79fed364d5eba5eb38e4b7bf76326884d (patch)
treedeacd6294f8860096ee82ee76930204efd65e33c /docs/archive/2025-11-04-evening/architecture-diagram.md
parent57bc8cd9c021feaf08e139e8fb62800bc476068e (diff)
remove docs archive
Diffstat (limited to 'docs/archive/2025-11-04-evening/architecture-diagram.md')
-rw-r--r--docs/archive/2025-11-04-evening/architecture-diagram.md442
1 files changed, 0 insertions, 442 deletions
diff --git a/docs/archive/2025-11-04-evening/architecture-diagram.md b/docs/archive/2025-11-04-evening/architecture-diagram.md
deleted file mode 100644
index 056e551..0000000
--- a/docs/archive/2025-11-04-evening/architecture-diagram.md
+++ /dev/null
@@ -1,442 +0,0 @@
1# ngit-grasp Architecture Diagram
2
3**Date:** November 4, 2025
4**Purpose:** Visual reference for single-port architecture
5
6---
7
8## Current Architecture (WRONG ❌)
9
10```
11┌─────────────────────────────────────────┐
12│ Port 8080 │
13│ ┌───────────────────────────────────┐ │
14│ │ Nostr Relay (WebSocket) │ │
15│ │ - NIP-01 protocol │ │
16│ │ - Event storage │ │
17│ │ - Subscriptions │ │
18│ └───────────────────────────────────┘ │
19└─────────────────────────────────────────┘
20
21┌─────────────────────────────────────────┐
22│ Port 8081 (WRONG!) │
23│ ┌───────────────────────────────────┐ │
24│ │ Git HTTP Server │ │
25│ │ - Not implemented │ │
26│ └───────────────────────────────────┘ │
27└─────────────────────────────────────────┘
28```
29
30**Problem:** GRASP-01 requires single port!
31
32---
33
34## Target Architecture (CORRECT ✅)
35
36```
37┌─────────────────────────────────────────────────────────────┐
38│ Single Port (8080) │
39│ │
40│ ┌───────────────────────────────────────────────────────┐ │
41│ │ actix-web HTTP Server │ │
42│ │ │ │
43│ │ ┌──────────────────────────────────────────────────┐ │ │
44│ │ │ CORS Middleware (ALL requests) │ │ │
45│ │ │ - Access-Control-Allow-Origin: * │ │ │
46│ │ │ - Access-Control-Allow-Methods: GET, POST │ │ │
47│ │ │ - Access-Control-Allow-Headers: Content-Type │ │ │
48│ │ └──────────────────────────────────────────────────┘ │ │
49│ │ │ │
50│ │ ┌──────────────────────────────────────────────────┐ │ │
51│ │ │ HTTP Router │ │ │
52│ │ │ │ │ │
53│ │ │ Path Pattern Matching: │ │ │
54│ │ │ - /<npub>/<identifier>.git/* → Git Handler │ │ │
55│ │ │ - /* → Nostr Handler │ │ │
56│ │ └──────────────────────────────────────────────────┘ │ │
57│ │ │ │
58│ │ ┌────────────────────┐ ┌─────────────────────────┐ │ │
59│ │ │ Git HTTP Handler │ │ Nostr Relay Handler │ │ │
60│ │ │ │ │ │ │ │
61│ │ │ ┌──────────────┐ │ │ ┌──────────────────┐ │ │ │
62│ │ │ │ git-http- │ │ │ │ WebSocket Upgrade│ │ │ │
63│ │ │ │ backend │ │ │ │ │ │ │ │
64│ │ │ │ │ │ │ │ ┌──────────────┐ │ │ │ │
65│ │ │ │ - info/refs │ │ │ │ │ NIP-01 │ │ │ │ │
66│ │ │ │ - upload-pack│ │ │ │ │ - EVENT │ │ │ │ │
67│ │ │ │ - receive-pack │ │ │ │ - REQ │ │ │ │ │
68│ │ │ │ │ │ │ │ │ - CLOSE │ │ │ │ │
69│ │ │ │ Authorization: │ │ │ └──────────────┘ │ │ │ │
70│ │ │ │ - Query state│ │ │ │ │ │ │ │
71│ │ │ │ - Validate │ │ │ │ ┌──────────────┐ │ │ │ │
72│ │ │ │ - Accept/ │ │ │ │ │ NIP-11 │ │ │ │ │
73│ │ │ │ Reject │ │ │ │ │ - GRASP fields│ │ │ │ │
74│ │ │ └──────────────┘ │ │ │ └──────────────┘ │ │ │ │
75│ │ │ │ │ │ │ │ │ │
76│ │ │ Repository: │ │ │ ┌──────────────┐ │ │ │ │
77│ │ │ {GIT_DATA_PATH}/ │ │ │ │ NIP-34 │ │ │ │ │
78│ │ │ {npub}/ │ │ │ │ - Announce │ │ │ │ │
79│ │ │ {identifier}.git │ │ │ │ - State │ │ │ │ │
80│ │ │ │ │ │ │ - Validate │ │ │ │ │
81│ │ └────────────────────┘ │ │ └──────────────┘ │ │ │ │
82│ │ │ │ │ │ │ │
83│ │ │ │ HTTP Root: │ │ │ │
84│ │ │ │ - Serve HTML │ │ │ │
85│ │ │ │ - NIP-11 JSON │ │ │ │
86│ │ │ └──────────────────┘ │ │ │
87│ │ │ │ │ │
88│ └───────────────────────────┴─────────────────────────┘ │ │
89│ │
90│ ┌───────────────────────────────────────────────────────┐ │
91│ │ Storage Layer │ │
92│ │ │ │
93│ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │
94│ │ │ Git Repositories │ │ Nostr Events DB │ │ │
95│ │ │ │ │ │ │ │
96│ │ │ {GIT_DATA_PATH}/ │ │ {RELAY_DATA_PATH}/ │ │ │
97│ │ │ ├── npub1.../ │ │ - Announcements │ │ │
98│ │ │ │ ├── repo1.git/ │ │ - State events │ │ │
99│ │ │ │ └── repo2.git/ │ │ - Issues/Patches │ │ │
100│ │ │ └── npub2.../ │ │ - Other events │ │ │
101│ │ │ └── repo3.git/ │ │ │ │ │
102│ │ └──────────────────────┘ └──────────────────────┘ │ │
103│ └───────────────────────────────────────────────────────┘ │
104└─────────────────────────────────────────────────────────────┘
105```
106
107---
108
109## Request Flow Examples
110
111### Example 1: Git Clone
112
113```
114Client: git clone http://localhost:8080/npub1abc.../my-repo.git
115
116actix-web receives HTTP GET request
117
118CORS middleware adds headers
119
120Router matches path: /npub1abc.../my-repo.git
121
122Git Handler receives request
123
124git-http-backend processes:
125 - GET /npub1abc.../my-repo.git/info/refs?service=git-upload-pack
126
127Response includes:
128 - CORS headers
129 - Git protocol data
130 - Capabilities: allow-reachable-sha1-in-want, allow-tip-sha1-in-want
131
132Client receives data and clones repository
133```
134
135### Example 2: Git Push
136
137```
138Client: git push http://localhost:8080/npub1abc.../my-repo.git main
139
140actix-web receives HTTP POST request
141
142CORS middleware adds headers
143
144Router matches path: /npub1abc.../my-repo.git
145
146Git Handler receives request
147
148BEFORE spawning git-receive-pack:
149 1. Parse ref updates from request body
150 2. Query latest state announcement from relay
151 3. Validate pusher in maintainer set
152 4. Validate ref updates match state
153
154If validation passes:
155 - Spawn git-receive-pack
156 - Stream response back to client
157
158If validation fails:
159 - Return HTTP 403 Forbidden
160 - Include error message
161
162Client receives success/failure
163```
164
165### Example 3: WebSocket Connection (Nostr)
166
167```
168Client: new WebSocket('ws://localhost:8080/')
169
170actix-web receives HTTP GET with Upgrade: websocket
171
172CORS middleware adds headers
173
174Router matches path: /
175
176Nostr Handler receives request
177
178Upgrade to WebSocket
179
180Client sends: ["EVENT", {...}]
181
182Nostr Handler processes EVENT
183
184If kind 30617 (announcement):
185 - Validate clone/relays tags
186 - Provision Git repository
187 - Store event
188
189Response: ["OK", event_id, true, ""]
190
191Client receives confirmation
192```
193
194### Example 4: NIP-11 Request
195
196```
197Client: fetch('http://localhost:8080/', {
198 headers: { 'Accept': 'application/nostr+json' }
199})
200
201actix-web receives HTTP GET with Accept header
202
203CORS middleware adds headers
204
205Router matches path: /
206
207Nostr Handler checks Accept header
208
209Returns NIP-11 JSON:
210{
211 "name": "ngit-grasp instance",
212 "description": "Rust GRASP implementation",
213 "supported_nips": [1, 11, 34],
214 "supported_grasps": ["GRASP-01"],
215 "repo_acceptance_criteria": "Must list this service in clone and relays tags",
216 "curation": "Basic spam prevention"
217}
218
219Client receives relay information
220```
221
222### Example 5: CORS Preflight (OPTIONS)
223
224```
225Browser: OPTIONS http://localhost:8080/
226Headers:
227 - Origin: https://example.com
228 - Access-Control-Request-Method: POST
229
230actix-web receives OPTIONS request
231
232CORS middleware handles preflight
233
234Returns 204 No Content with headers:
235 - Access-Control-Allow-Origin: *
236 - Access-Control-Allow-Methods: GET, POST
237 - Access-Control-Allow-Headers: Content-Type
238 - Access-Control-Max-Age: 3600
239
240Browser caches preflight response
241
242Browser proceeds with actual request
243```
244
245---
246
247## Component Responsibilities
248
249### actix-web HTTP Server
250- Listen on single port
251- Route requests by path
252- Handle WebSocket upgrades
253- Apply CORS to all requests
254
255### CORS Middleware
256- Add headers to ALL responses
257- Handle OPTIONS preflight
258- Allow any origin (GRASP-01 requirement)
259
260### HTTP Router
261- Match `/npub.../repo.git` → Git Handler
262- Match `/` → Nostr Handler
263- Pass through to appropriate handler
264
265### Git Handler
266- Serve Git Smart HTTP protocol
267- Read from `{GIT_DATA_PATH}/{npub}/{id}.git`
268- Validate pushes before accepting
269- Return 404 for missing repos
270
271### Nostr Handler
272- Upgrade HTTP to WebSocket
273- Process NIP-01 messages
274- Store/query events
275- Serve NIP-11 for HTTP requests
276- Provision repos from announcements
277
278### Storage Layer
279- Git repositories (bare)
280- Nostr events (database)
281- Separate paths for each
282
283---
284
285## Configuration Flow
286
287```
288Environment Variables
289
290.env file (optional)
291
292Config::from_env()
293
294Config struct:
295 - bind_address: "127.0.0.1:8080"
296 - domain: "example.com"
297 - git_data_path: "./data/repos"
298 - relay_data_path: "./data/relay"
299 - relay_name: "..."
300 - relay_description: "..."
301 - owner_npub: "..."
302
303Passed to:
304 - HTTP server (bind address)
305 - Git handler (git_data_path, domain)
306 - Nostr handler (relay_data_path, domain, NIP-11 info)
307 - Storage layer (both paths)
308```
309
310---
311
312## Test Architecture
313
314```
315Integration Test
316
317TestRelay::start()
318
319Spawns ngit-grasp process:
320 - NGIT_BIND_ADDRESS=127.0.0.1:{random_port}
321 - NGIT_DOMAIN=127.0.0.1:{random_port}
322 - NGIT_GIT_DATA_PATH=./test-data/repos
323 - NGIT_RELAY_DATA_PATH=./test-data/relay
324
325Process starts:
326 - actix-web listens on random port
327 - Both Git and Nostr available
328
329Test runs:
330 - Uses grasp-audit library
331 - Connects to ws://127.0.0.1:{port}/
332 - Runs compliance tests
333
334TestRelay::stop()
335
336Process killed
337
338Test data cleaned up
339```
340
341---
342
343## File Structure
344
345```
346ngit-grasp/
347├── src/
348│ ├── main.rs # Entry point
349│ ├── config.rs # Configuration
350│ ├── http/ # NEW - HTTP server
351│ │ ├── mod.rs # Server setup
352│ │ ├── git.rs # Git HTTP handler
353│ │ └── nostr.rs # Nostr WebSocket handler
354│ ├── nostr/
355│ │ ├── mod.rs
356│ │ ├── relay.rs # Relay logic (reused)
357│ │ └── events.rs # Event handling
358│ └── storage/
359│ ├── mod.rs
360│ └── repository.rs # Git repo management
361├── tests/
362│ ├── common/
363│ │ ├── mod.rs
364│ │ └── relay.rs # TestRelay fixture
365│ ├── nip01_compliance.rs # NIP-01 tests
366│ ├── nip34_announcements.rs # NIP-34 tests
367│ └── grasp01_git_http.rs # NEW - GRASP-01 Git tests
368├── data/ # Runtime data (gitignored)
369│ ├── repos/ # Git repositories
370│ └── relay/ # Nostr events
371└── test-data/ # Test data (gitignored)
372 ├── repos/
373 └── relay/
374```
375
376---
377
378## Comparison: ngit-relay vs ngit-grasp
379
380### ngit-relay (Go + nginx)
381
382```
383nginx (Port 8081)
384 ├── Git HTTP → fcgiwrap → git-http-backend
385 │ ↓
386 │ pre-receive hook (Go)
387 │ ↓
388 │ Khatru relay (HTTP API)
389
390 └── Nostr → proxy → Khatru relay (Port 3334)
391
392 on_event hook (Go)
393
394 provision repos
395```
396
397**Components:**
398- nginx (routing)
399- fcgiwrap (CGI wrapper)
400- git-http-backend (Git protocol)
401- pre-receive hook (Go, validates pushes)
402- post-receive hook (Go, updates HEAD)
403- Khatru relay (Go, Nostr protocol)
404- on_event hook (Go, provisions repos)
405- supervisord (process management)
406
407### ngit-grasp (Rust)
408
409```
410actix-web (Port 8080)
411 ├── Git HTTP → git-http-backend crate
412 │ ↓
413 │ inline authorization
414 │ ↓
415 │ Storage (query state)
416
417 └── Nostr → WebSocket upgrade
418
419 nostr-sdk relay
420
421 on_event (provision repos)
422
423 Storage (store events)
424```
425
426**Components:**
427- actix-web (routing + HTTP + WebSocket)
428- git-http-backend crate (Git protocol)
429- nostr-sdk (Nostr protocol)
430- Storage (unified storage layer)
431
432**Advantages:**
433- Single binary
434- No external processes
435- Inline authorization (better errors)
436- Pure Rust (memory safety)
437- Easier testing
438
439---
440
441**Last Updated:** November 4, 2025
442**Purpose:** Reference for implementation