upleb.uk

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

summaryrefslogtreecommitdiff
path: root/docs/archive/2025-11-05-grasp01-test-plan.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/archive/2025-11-05-grasp01-test-plan.md')
-rw-r--r--docs/archive/2025-11-05-grasp01-test-plan.md752
1 files changed, 752 insertions, 0 deletions
diff --git a/docs/archive/2025-11-05-grasp01-test-plan.md b/docs/archive/2025-11-05-grasp01-test-plan.md
new file mode 100644
index 0000000..4148f1d
--- /dev/null
+++ b/docs/archive/2025-11-05-grasp01-test-plan.md
@@ -0,0 +1,752 @@
1# GRASP-01 Test Plan
2
3**Date:** November 5, 2025
4**Status:** Planning Phase
5**Scope:** Complete test coverage for GRASP-01 Core Service Requirements
6
7---
8
9## Overview
10
11This document outlines all tests needed to validate GRASP-01 compliance. Each test maps directly to requirements in `../grasp/01.md`.
12
13**Test Strategy:**
141. Build tests against ngit-relay reference implementation FIRST
152. Each requirement = one or more test functions
163. All tests reference specific spec line numbers
174. Tests organized by spec sections
18
19---
20
21## Test Organization
22
23```
24grasp-audit/src/specs/
25├── mod.rs # Export all test modules
26├── nip01_smoke.rs # ✅ DONE - Basic relay functionality
27├── grasp01_nostr_relay.rs # NEW - Nostr relay requirements
28├── grasp01_git_http.rs # NEW - Git Smart HTTP requirements
29└── grasp01_cors.rs # NEW - CORS requirements
30```
31
32---
33
34## 1. NIP-01 Smoke Tests (✅ COMPLETE)
35
36**File:** `grasp-audit/src/specs/nip01_smoke.rs`
37
38**Status:** Already implemented and working
39
40**Coverage:**
41- ✅ WebSocket connection
42- ✅ Send/receive events
43- ✅ Subscriptions (REQ/CLOSE)
44- ✅ Event validation (signatures, IDs)
45
46**Note:** These are smoke tests only. We don't comprehensively test NIP-01 since rust-nostr already has 1000+ tests.
47
48---
49
50## 2. GRASP-01 Nostr Relay Tests (🔜 TO DO)
51
52**File:** `grasp-audit/src/specs/grasp01_nostr_relay.rs`
53
54**Spec Reference:** Lines 1-14 of `../grasp/01.md`
55
56### Test Functions to Implement:
57
58#### 2.1 Repository Announcement Acceptance
59
60```rust
61/// Test: Accept valid repository announcements
62/// Spec: Lines 3-5
63/// Requirement: MUST accept repo announcements listing service in clone & relays tags
64async fn test_accept_valid_repo_announcement()
65```
66
67**Test Details:**
68- Create kind 30617 event with valid tags
69- Include service URL in both `clone` and `relays` tags
70- Send to relay
71- Verify acceptance (OK response)
72- Query back to confirm stored
73
74```rust
75/// Test: Reject repo announcements not listing service (unless GRASP-05)
76/// Spec: Line 5
77/// Requirement: MUST reject announcements not listing service
78async fn test_reject_repo_announcement_missing_clone_tag()
79```
80
81**Test Details:**
82- Create kind 30617 event WITHOUT service in `clone` tag
83- Send to relay
84- Verify rejection (error response)
85- Confirm not stored in relay
86
87```rust
88/// Test: Reject repo announcements not listing service in relays tag
89/// Spec: Line 5
90/// Requirement: MUST reject announcements not listing service in relays
91async fn test_reject_repo_announcement_missing_relays_tag()
92```
93
94**Test Details:**
95- Create kind 30617 event WITHOUT service in `relays` tag
96- Send to relay
97- Verify rejection
98- Confirm not stored
99
100#### 2.2 Repository State Announcement Acceptance
101
102```rust
103/// Test: Accept valid repository state announcements
104/// Spec: Line 3
105/// Requirement: MUST accept repo state announcements
106async fn test_accept_valid_repo_state_announcement()
107```
108
109**Test Details:**
110- First send valid kind 30617 (repo announcement)
111- Then send kind 30618 (state announcement) with matching `d` tag
112- Include `refs/heads/main` and `HEAD` tags
113- Verify acceptance
114- Query back to confirm
115
116```rust
117/// Test: Accept state announcement with multiple refs
118/// Spec: Line 3
119/// Requirement: MUST accept state announcements with multiple refs
120async fn test_accept_state_announcement_multiple_refs()
121```
122
123**Test Details:**
124- Send kind 30618 with multiple `refs/heads/*` tags
125- Include `refs/tags/*` tags
126- Verify all refs are stored
127
128```rust
129/// Test: Accept state announcement with no refs (stop tracking)
130/// Spec: NIP-34 spec
131/// Requirement: Support stopping state tracking
132async fn test_accept_state_announcement_no_refs()
133```
134
135**Test Details:**
136- Send kind 30618 with only `d` tag (no refs)
137- Verify acceptance (allows author to stop tracking)
138
139#### 2.3 Related Event Acceptance
140
141```rust
142/// Test: Accept events tagging accepted repo announcements
143/// Spec: Lines 7-9
144/// Requirement: MUST accept events that tag accepted repo announcements
145async fn test_accept_event_tagging_repo_announcement()
146```
147
148**Test Details:**
149- Create and accept kind 30617 (repo announcement)
150- Create kind 1621 (issue) with `a` tag pointing to repo
151- Verify issue is accepted
152
153```rust
154/// Test: Accept events tagged by repo announcements
155/// Spec: Lines 7-9
156/// Requirement: MUST accept events tagged by accepted announcements
157async fn test_accept_event_tagged_by_repo()
158```
159
160**Test Details:**
161- Create event (e.g., kind 1 note)
162- Create kind 30617 that tags the note
163- Verify note is accepted/retained
164
165```rust
166/// Test: Accept patches (kind 1617) for accepted repos
167/// Spec: Lines 8-9
168/// Requirement: MUST accept patches for accepted repos
169async fn test_accept_patch_for_repo()
170```
171
172**Test Details:**
173- Create kind 30617 repo announcement
174- Create kind 1617 patch with `a` tag to repo
175- Verify patch acceptance
176
177```rust
178/// Test: Accept pull requests (kind 1618) for accepted repos
179/// Spec: Lines 8-9
180/// Requirement: MUST accept PRs for accepted repos
181async fn test_accept_pull_request_for_repo()
182```
183
184**Test Details:**
185- Create kind 30617 repo announcement
186- Create kind 1618 PR with `a` tag to repo
187- Include required tags: `c` (commit), `clone`, etc.
188- Verify PR acceptance
189
190```rust
191/// Test: Accept issues (kind 1621) for accepted repos
192/// Spec: Lines 8-9
193/// Requirement: MUST accept issues for accepted repos
194async fn test_accept_issue_for_repo()
195```
196
197**Test Details:**
198- Create kind 30617 repo announcement
199- Create kind 1621 issue with `a` tag to repo
200- Verify issue acceptance
201
202```rust
203/// Test: Accept replies to accepted patches/PRs/issues
204/// Spec: Lines 8-9
205/// Requirement: MUST accept replies to accepted events
206async fn test_accept_reply_to_issue()
207```
208
209**Test Details:**
210- Create kind 1621 issue
211- Create NIP-22 comment (kind 1111) replying to issue
212- Verify reply acceptance
213
214#### 2.4 NIP-11 Relay Information
215
216```rust
217/// Test: Serve NIP-11 document at /.well-known/nostr.json
218/// Spec: Line 11
219/// Requirement: MUST serve NIP-11 document
220async fn test_nip11_document_exists()
221```
222
223**Test Details:**
224- HTTP GET to `/.well-known/nostr.json` or `https://domain/` with `Accept: application/nostr+json`
225- Verify 200 response
226- Verify valid JSON
227
228```rust
229/// Test: NIP-11 includes supported_grasps field
230/// Spec: Line 12
231/// Requirement: MUST list supported GRASPs as string array
232async fn test_nip11_supported_grasps_field()
233```
234
235**Test Details:**
236- Fetch NIP-11 document
237- Verify `supported_grasps` field exists
238- Verify it's a string array
239- Verify includes "GRASP-01"
240- Format check: each entry matches `GRASP-XX` pattern
241
242```rust
243/// Test: NIP-11 includes repo_acceptance_criteria field
244/// Spec: Line 13
245/// Requirement: MUST list repository acceptance criteria
246async fn test_nip11_repo_acceptance_criteria_field()
247```
248
249**Test Details:**
250- Fetch NIP-11 document
251- Verify `repo_acceptance_criteria` field exists
252- Verify it's a human-readable string
253- Verify non-empty
254
255```rust
256/// Test: NIP-11 curation field handling
257/// Spec: Line 14
258/// Requirement: MUST include curation if curated, omit otherwise
259async fn test_nip11_curation_field()
260```
261
262**Test Details:**
263- Fetch NIP-11 document
264- If `curation` field exists, verify it's a non-empty string
265- Document behavior (present or absent is both valid)
266
267#### 2.5 Event Rejection Policies
268
269```rust
270/// Test: MAY reject based on custom criteria
271/// Spec: Line 6
272/// Requirement: Document that custom rejection is allowed
273async fn test_custom_rejection_allowed()
274```
275
276**Test Details:**
277- This is a policy test, not a functional test
278- Verify relay can reject for reasons like:
279 - Pre-payment required
280 - Quota exceeded
281 - WoT filtering
282 - Whitelist
283 - SPAM prevention
284- Document in test that this is implementation-specific
285
286```rust
287/// Test: MAY reject/delete for SPAM prevention
288/// Spec: Line 10
289/// Requirement: Generic SPAM prevention allowed
290async fn test_spam_prevention_allowed()
291```
292
293**Test Details:**
294- Document that relay may reject/delete for SPAM
295- This is permissive, not mandatory
296- Test should document the policy, not enforce specific behavior
297
298---
299
300## 3. GRASP-01 Git Smart HTTP Tests (🔜 TO DO)
301
302**File:** `grasp-audit/src/specs/grasp01_git_http.rs`
303
304**Spec Reference:** Lines 15-31 of `../grasp/01.md`
305
306### Test Functions to Implement:
307
308#### 3.1 Repository Serving
309
310```rust
311/// Test: Serve git repo at /<npub>/<identifier>.git
312/// Spec: Line 17
313/// Requirement: MUST serve git repo at correct path
314async fn test_serve_git_repo_at_correct_path()
315```
316
317**Test Details:**
318- Create kind 30617 announcement with `d` tag = "test-repo"
319- Push git data to repository
320- HTTP GET to `/<npub>/test-repo.git/info/refs?service=git-upload-pack`
321- Verify 200 response
322- Verify git smart HTTP response format
323
324```rust
325/// Test: Unauthenticated git-upload-pack (clone/fetch)
326/// Spec: Line 17
327/// Requirement: MUST allow unauthenticated clone/fetch
328async fn test_unauthenticated_clone()
329```
330
331**Test Details:**
332- Create and push repository
333- Perform git clone without authentication
334- Verify clone succeeds
335- Verify repository contents match
336
337```rust
338/// Test: Repository only served for accepted announcements
339/// Spec: Line 17
340/// Requirement: Only serve repos with accepted announcements
341async fn test_no_git_repo_without_announcement()
342```
343
344**Test Details:**
345- Try to access `/<npub>/nonexistent.git/info/refs`
346- Verify 404 response
347- Verify no git data served
348
349#### 3.2 Push Authorization
350
351```rust
352/// Test: Accept push matching latest state announcement
353/// Spec: Line 19
354/// Requirement: MUST accept pushes matching state announcement
355async fn test_accept_push_matching_state()
356```
357
358**Test Details:**
359- Create kind 30617 repo announcement
360- Create kind 30618 state with `refs/heads/main` = commit A
361- Attempt git push updating main to commit B (child of A)
362- Verify push accepted
363- Verify repository updated
364
365```rust
366/// Test: Reject push not matching state announcement
367/// Spec: Line 19
368/// Requirement: Implicit - only accept matching pushes
369async fn test_reject_push_not_matching_state()
370```
371
372**Test Details:**
373- Create kind 30618 state with `refs/heads/main` = commit A
374- Attempt git push updating main to commit X (unrelated)
375- Verify push rejected
376- Verify repository unchanged
377
378```rust
379/// Test: Respect recursive maintainer set
380/// Spec: Line 19
381/// Requirement: MUST respect recursive maintainer set
382async fn test_push_authorization_maintainer_set()
383```
384
385**Test Details:**
386- Create repo announcement by user A
387- Add user B to `maintainers` tag
388- User B creates state announcement
389- User B pushes matching state
390- Verify push accepted
391- Test recursion: B lists C as maintainer, C can push
392
393```rust
394/// Test: Reject push from non-maintainer
395/// Spec: Line 19 (implicit)
396/// Requirement: Only maintainers can push
397async fn test_reject_push_from_non_maintainer()
398```
399
400**Test Details:**
401- Create repo announcement by user A
402- User B (not in maintainers) creates state announcement
403- User B attempts push
404- Verify push rejected
405
406#### 3.3 HEAD Management
407
408```rust
409/// Test: Set HEAD per state announcement
410/// Spec: Line 21
411/// Requirement: MUST set HEAD when git data received
412async fn test_set_head_from_state_announcement()
413```
414
415**Test Details:**
416- Create kind 30618 with `HEAD = ref: refs/heads/develop`
417- Push git data for develop branch
418- Clone repository
419- Verify HEAD points to develop (not main)
420
421```rust
422/// Test: Update HEAD when state changes
423/// Spec: Line 21
424/// Requirement: Update HEAD as soon as git data available
425async fn test_update_head_when_state_changes()
426```
427
428**Test Details:**
429- Initial state: HEAD = main
430- Push new state: HEAD = develop
431- Push git data for develop
432- Verify HEAD updates to develop
433
434#### 3.4 Pull Request Refs
435
436```rust
437/// Test: Accept push to refs/nostr/<event-id>
438/// Spec: Line 23
439/// Requirement: MUST accept pushes to PR refs
440async fn test_accept_push_to_pr_ref()
441```
442
443**Test Details:**
444- Create kind 1618 PR event
445- Push to `refs/nostr/<pr-event-id>`
446- Verify push accepted
447- Verify ref exists in repository
448
449```rust
450/// Test: Reject PR ref if event has different tip
451/// Spec: Line 23
452/// Requirement: SHOULD reject if tip mismatch
453async fn test_reject_pr_ref_tip_mismatch()
454```
455
456**Test Details:**
457- Create kind 1618 PR with `c` tag = commit A
458- Push to `refs/nostr/<pr-event-id>` with commit B
459- Verify push rejected (or document if accepted)
460
461```rust
462/// Test: Delete PR ref if no event within 20 minutes
463/// Spec: Line 23
464/// Requirement: SHOULD delete orphaned PR refs
465async fn test_delete_orphaned_pr_ref()
466```
467
468**Test Details:**
469- Push to `refs/nostr/<event-id>`
470- Wait 20+ minutes without sending kind 1618/1619 event
471- Check if ref is deleted
472- Note: This is SHOULD, not MUST - document behavior
473
474```rust
475/// Test: Keep PR ref if event exists
476/// Spec: Line 23 (implicit)
477/// Requirement: Keep ref if valid PR/update event exists
478async fn test_keep_pr_ref_with_event()
479```
480
481**Test Details:**
482- Push to `refs/nostr/<event-id>`
483- Send kind 1618 PR event with matching `c` tag
484- Wait 20+ minutes
485- Verify ref still exists
486
487#### 3.5 Git Protocol Features
488
489```rust
490/// Test: Advertise allow-reachable-sha1-in-want
491/// Spec: Line 25
492/// Requirement: MUST advertise and serve capability
493async fn test_advertise_reachable_sha1_in_want()
494```
495
496**Test Details:**
497- GET `/repo.git/info/refs?service=git-upload-pack`
498- Parse git protocol response
499- Verify `allow-reachable-sha1-in-want` in capabilities
500
501```rust
502/// Test: Advertise allow-tip-sha1-in-want
503/// Spec: Line 25
504/// Requirement: MUST advertise and serve capability
505async fn test_advertise_tip_sha1_in_want()
506```
507
508**Test Details:**
509- GET `/repo.git/info/refs?service=git-upload-pack`
510- Parse git protocol response
511- Verify `allow-tip-sha1-in-want` in capabilities
512
513```rust
514/// Test: Serve available OIDs by SHA1
515/// Spec: Line 25
516/// Requirement: MUST serve available OIDs
517async fn test_serve_oids_by_sha1()
518```
519
520**Test Details:**
521- Push repository with known commits
522- Perform git fetch with specific SHA1 want
523- Verify server provides the object
524
525#### 3.6 Web Interface
526
527```rust
528/// Test: Serve webpage at repo endpoint
529/// Spec: Line 27
530/// Requirement: SHOULD serve webpage with links
531async fn test_serve_webpage_at_repo_endpoint()
532```
533
534**Test Details:**
535- HTTP GET to `/<npub>/<identifier>.git` with `Accept: text/html`
536- Verify HTML response (not git protocol)
537- Verify links to git nostr clients (optional check)
538
539```rust
540/// Test: Serve 404 for non-existent repos
541/// Spec: Line 27
542/// Requirement: SHOULD serve 404 for missing repos
543async fn test_serve_404_for_missing_repo()
544```
545
546**Test Details:**
547- HTTP GET to `/<npub>/nonexistent.git` with `Accept: text/html`
548- Verify 404 response
549- Verify helpful error message
550
551---
552
553## 4. GRASP-01 CORS Tests (🔜 TO DO)
554
555**File:** `grasp-audit/src/specs/grasp01_cors.rs`
556
557**Spec Reference:** Lines 32-40 of `../grasp/01.md`
558
559### Test Functions to Implement:
560
561```rust
562/// Test: Access-Control-Allow-Origin on all responses
563/// Spec: Line 35
564/// Requirement: MUST set ACAO: * on ALL responses
565async fn test_cors_allow_origin_on_all_responses()
566```
567
568**Test Details:**
569- Test multiple endpoints:
570 - WebSocket upgrade (Nostr relay)
571 - Git HTTP endpoints (info/refs, upload-pack, receive-pack)
572 - NIP-11 endpoint
573 - Web interface
574- Verify ALL include `Access-Control-Allow-Origin: *`
575
576```rust
577/// Test: Access-Control-Allow-Methods on all responses
578/// Spec: Line 36
579/// Requirement: MUST set ACAM: GET, POST on ALL responses
580async fn test_cors_allow_methods_on_all_responses()
581```
582
583**Test Details:**
584- Test same endpoints as above
585- Verify ALL include `Access-Control-Allow-Methods: GET, POST`
586
587```rust
588/// Test: Access-Control-Allow-Headers on all responses
589/// Spec: Line 37
590/// Requirement: MUST set ACAH: Content-Type on ALL responses
591async fn test_cors_allow_headers_on_all_responses()
592```
593
594**Test Details:**
595- Test same endpoints as above
596- Verify ALL include `Access-Control-Allow-Headers: Content-Type`
597
598```rust
599/// Test: OPTIONS requests return 204 No Content
600/// Spec: Line 38
601/// Requirement: MUST respond to OPTIONS with 204
602async fn test_cors_options_request()
603```
604
605**Test Details:**
606- Send OPTIONS request to various endpoints
607- Verify 204 No Content response
608- Verify CORS headers present on OPTIONS response
609
610```rust
611/// Test: CORS headers on error responses
612/// Spec: Line 35 (ALL responses)
613/// Requirement: CORS headers even on errors
614async fn test_cors_headers_on_error_responses()
615```
616
617**Test Details:**
618- Trigger various error conditions:
619 - 404 not found
620 - 403 forbidden (unauthorized push)
621 - 400 bad request
622- Verify CORS headers present on all error responses
623
624```rust
625/// Test: Preflight request handling
626/// Spec: Lines 35-38
627/// Requirement: Full preflight support for web clients
628async fn test_cors_preflight_request()
629```
630
631**Test Details:**
632- Send OPTIONS with Origin and Access-Control-Request-Method headers
633- Verify proper preflight response
634- Verify subsequent actual request succeeds
635
636---
637
638## Implementation Priority
639
640### Phase 1: Core Nostr Relay Tests (Complete these first)
6411. ✅ NIP-01 smoke tests (DONE)
6422. Repository announcement acceptance/rejection
6433. Repository state announcement acceptance
6444. NIP-11 relay information document
6455. Related event acceptance (issues, patches, PRs)
646
647### Phase 2: Git Smart HTTP Tests
6481. Repository serving at correct paths
6492. Unauthenticated clone/fetch
6503. Push authorization and maintainer sets
6514. HEAD management
6525. Git protocol features (SHA1 capabilities)
653
654### Phase 3: Advanced Git Features
6551. Pull request refs (refs/nostr/<event-id>)
6562. PR ref lifecycle (creation, validation, deletion)
6573. Web interface (optional)
658
659### Phase 4: CORS Tests
6601. CORS headers on all endpoints
6612. OPTIONS request handling
6623. Preflight requests
6634. Error response CORS
664
665---
666
667## Test Execution Plan
668
669### Against ngit-relay Reference Implementation
670
671```bash
672# 1. Start ngit-relay
673cd ../ngit-relay
674docker-compose up -d
675
676# 2. Run tests
677cd ../ngit-grasp/grasp-audit
678cargo test --lib # Unit tests
679
680# Run integration tests by category
681cargo test --test grasp01_nostr_relay
682cargo test --test grasp01_git_http
683cargo test --test grasp01_cors
684
685# 3. Run full audit
686cargo run -- --url ws://localhost:8081
687```
688
689### Test Data Requirements
690
691For comprehensive testing, we need:
692- Multiple test keypairs (maintainers, contributors, non-maintainers)
693- Sample git repositories with known commit history
694- Valid NIP-34 event templates
695- Test data for edge cases
696
697---
698
699## Success Criteria
700
701- [ ] All GRASP-01 requirements have corresponding tests
702- [ ] All tests reference specific spec line numbers
703- [ ] All tests pass against ngit-relay reference implementation
704- [ ] Tests are organized logically by spec sections
705- [ ] Clear test output shows what requirement is being tested
706- [ ] Tests can be run individually or as full suite
707- [ ] Documentation explains what each test validates
708
709---
710
711## Notes
712
713### Spec Line Number References
714
715When implementing tests, use this format:
716
717```rust
718/// Test: <Short description>
719/// Spec: Lines X-Y of ../grasp/01.md
720/// Requirement: <Exact quote or paraphrase from spec>
721async fn test_name() {
722 // Implementation
723}
724```
725
726### Test Naming Convention
727
728- `test_accept_*` - Tests that verify acceptance of valid input
729- `test_reject_*` - Tests that verify rejection of invalid input
730- `test_serve_*` - Tests that verify correct serving of data
731- `test_cors_*` - Tests for CORS functionality
732- `test_nip11_*` - Tests for NIP-11 relay information
733
734### Edge Cases to Consider
735
7361. **Concurrent updates** - Multiple maintainers pushing simultaneously
7372. **Large repositories** - Performance with large git data
7383. **Invalid git data** - Corrupted pack files, invalid refs
7394. **Event ordering** - State announcement before repo announcement
7405. **Deleted events** - What happens when announcement is deleted?
7416. **Network failures** - Partial push, interrupted clone
7427. **Recursive maintainers** - Deep maintainer chains, circular references
743
744---
745
746**Next Steps:**
7471. Implement Phase 1 tests (Nostr relay)
7482. Run against ngit-relay to validate
7493. Fix any failing tests
7504. Move to Phase 2 (Git HTTP)
7515. Iterate until all tests pass
752