diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-03 11:19:40 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-03 11:19:40 +0000 |
| commit | 2eaff5b79fed364d5eba5eb38e4b7bf76326884d (patch) | |
| tree | deacd6294f8860096ee82ee76930204efd65e33c /docs/archive/2025-11-04-evening/review-summary.md | |
| parent | 57bc8cd9c021feaf08e139e8fb62800bc476068e (diff) | |
remove docs archive
Diffstat (limited to 'docs/archive/2025-11-04-evening/review-summary.md')
| -rw-r--r-- | docs/archive/2025-11-04-evening/review-summary.md | 513 |
1 files changed, 0 insertions, 513 deletions
diff --git a/docs/archive/2025-11-04-evening/review-summary.md b/docs/archive/2025-11-04-evening/review-summary.md deleted file mode 100644 index 29a3ff4..0000000 --- a/docs/archive/2025-11-04-evening/review-summary.md +++ /dev/null | |||
| @@ -1,513 +0,0 @@ | |||
| 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 | ||
| 17 | ports: | ||
| 18 | - "8081:8081" # Single port only! | ||
| 19 | ``` | ||
| 20 | |||
| 21 | ```nginx | ||
| 22 | # ../ngit-relay/src/nginx.conf | ||
| 23 | server { | ||
| 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 | ||
| 103 | NGIT_DOMAIN=example.com # For announcement validation | ||
| 104 | NGIT_INTERNAL_RELAY_PORT_FOR_SSL_PROXY=8081 # We don't need this | ||
| 105 | |||
| 106 | # Relay Information (NIP-11) | ||
| 107 | NGIT_RELAY_NAME="..." | ||
| 108 | NGIT_RELAY_DESCRIPTION="..." | ||
| 109 | NGIT_OWNER_NPUB="..." | ||
| 110 | |||
| 111 | # Features | ||
| 112 | NGIT_PROACTIVE_SYNC_GIT=true # GRASP-02 (future) | ||
| 113 | NGIT_PROACTIVE_SYNC_BLOSSOM=true # Not in GRASP | ||
| 114 | NGIT_PROACTIVE_SYNC_NOSTR=true # GRASP-02 (future) | ||
| 115 | |||
| 116 | # Blossom Settings | ||
| 117 | NGIT_BLOSSOM_MAX_FILE_SIZE_MB=100 # Not in GRASP | ||
| 118 | NGIT_BLOSSOM_MAX_CAPACITY_GB=50 # Not in GRASP | ||
| 119 | |||
| 120 | # Logging | ||
| 121 | NGIT_LOG_DIR=/var/log/ngit-relay | ||
| 122 | NGIT_LOG_LEVEL=INFO | ||
| 123 | NGIT_LOG_MAX_SIZE_MB=20 | ||
| 124 | NGIT_LOG_MAX_BACKUPS=10 | ||
| 125 | NGIT_LOG_MAX_AGE_DAYS=30 | ||
| 126 | ``` | ||
| 127 | |||
| 128 | **Our Environment Variables:** | ||
| 129 | |||
| 130 | ```bash | ||
| 131 | # Service Configuration | ||
| 132 | NGIT_DOMAIN=example.com # REQUIRED - for announcement validation | ||
| 133 | NGIT_BIND_ADDRESS=127.0.0.1:8080 # REQUIRED - single port | ||
| 134 | |||
| 135 | # Relay Information (NIP-11) | ||
| 136 | NGIT_RELAY_NAME="ngit-grasp instance" | ||
| 137 | NGIT_RELAY_DESCRIPTION="Rust GRASP implementation" | ||
| 138 | NGIT_OWNER_NPUB="npub1..." | ||
| 139 | |||
| 140 | # Storage Paths | ||
| 141 | NGIT_GIT_DATA_PATH=./data/repos # REQUIRED - where to store Git repos | ||
| 142 | NGIT_RELAY_DATA_PATH=./data/relay # REQUIRED - where to store events | ||
| 143 | |||
| 144 | # Logging | ||
| 145 | NGIT_LOG_LEVEL=INFO | ||
| 146 | RUST_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 | ||
| 237 | fn 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:** | ||
| 285 | 1. When state announcement received: | ||
| 286 | - Update repository HEAD if needed | ||
| 287 | - Store state for push validation | ||
| 288 | - Handle maintainer set | ||
| 289 | |||
| 290 | 2. 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:** | ||
| 317 | 1. Push to `refs/nostr/<event-id>` | ||
| 318 | 2. Verify PR event exists on relay | ||
| 319 | 3. Verify ref tip matches PR event `c` tag | ||
| 320 | 4. Accept push | ||
| 321 | 5. After 20 minutes, check if PR event still exists | ||
| 322 | 6. 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: | ||
| 344 | allow-reachable-sha1-in-want | ||
| 345 | allow-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 | ``` | ||
| 362 | 1. Set `Access-Control-Allow-Origin: *` on ALL responses | ||
| 363 | 2. Set `Access-Control-Allow-Methods: GET, POST` on ALL responses | ||
| 364 | 3. Set `Access-Control-Allow-Headers: Content-Type` on ALL responses | ||
| 365 | 4. Respond to OPTIONS requests with 204 No Content | ||
| 366 | ``` | ||
| 367 | |||
| 368 | **Implementation:** | ||
| 369 | ```rust | ||
| 370 | // In actix-web | ||
| 371 | App::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 | |||
| 492 | Before 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 | |||
| 499 | Ready 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 | ||