upleb.uk

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

summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/learnings/grasp-audit.md46
1 files changed, 32 insertions, 14 deletions
diff --git a/docs/learnings/grasp-audit.md b/docs/learnings/grasp-audit.md
index 531ebda..14e5a2b 100644
--- a/docs/learnings/grasp-audit.md
+++ b/docs/learnings/grasp-audit.md
@@ -18,6 +18,7 @@
18**Decision:** Build `grasp-audit` as a separate crate from `ngit-grasp` 18**Decision:** Build `grasp-audit` as a separate crate from `ngit-grasp`
19 19
20**Why:** 20**Why:**
21
211. **Parallel Development**: Can build tests before implementation 221. **Parallel Development**: Can build tests before implementation
222. **Isolated Testing**: Tests run in isolation (CI/CD safe) 232. **Isolated Testing**: Tests run in isolation (CI/CD safe)
233. **Production Auditing**: Can audit live production services 243. **Production Auditing**: Can audit live production services
@@ -43,6 +44,7 @@
43``` 44```
44 45
45**Benefits:** 46**Benefits:**
47
46- ✅ **Queryable**: Can find all audit events via tag filter 48- ✅ **Queryable**: Can find all audit events via tag filter
47- ✅ **Isolated**: Each test run has unique run ID 49- ✅ **Isolated**: Each test run has unique run ID
48- ✅ **Self-cleaning**: Cleanup timestamp indicates when to delete 50- ✅ **Self-cleaning**: Cleanup timestamp indicates when to delete
@@ -56,10 +58,12 @@
56### Standard "t" Tags vs Custom Tags 58### Standard "t" Tags vs Custom Tags
57 59
58**Evolution:** 60**Evolution:**
61
591. **Original**: Custom single-letter tags (`g`, `r`, `c`) 621. **Original**: Custom single-letter tags (`g`, `r`, `c`)
602. **Current**: Standard NIP-01 "t" tags with prefixed values 632. **Current**: Standard NIP-01 "t" tags with prefixed values
61 64
62**Why we changed:** 65**Why we changed:**
66
63- ❌ Custom tags could conflict with other systems 67- ❌ Custom tags could conflict with other systems
64- ✅ "t" tag is standard for categorization/topics 68- ✅ "t" tag is standard for categorization/topics
65- ✅ Multiple "t" tags are expected and supported 69- ✅ Multiple "t" tags are expected and supported
@@ -78,17 +82,18 @@
78use grasp_audit::audit::AuditConfig; 82use grasp_audit::audit::AuditConfig;
79 83
80// CI mode - isolated test runs 84// CI mode - isolated test runs
81let config = AuditConfig::ci(); 85let config = AuditConfig::isolated();
82// Generates UUID run ID: "ci-{uuid}" 86// Generates UUID run ID: "ci-{uuid}"
83// Cleanup after 1 hour 87// Cleanup after 1 hour
84 88
85// Production mode - persistent run ID 89// Production mode - persistent run ID
86let config = AuditConfig::production("prod-server-1"); 90let config = AuditConfig::shared();
87// Uses provided run ID 91// Uses provided run ID
88// Cleanup after 24 hours 92// Cleanup after 24 hours
89``` 93```
90 94
91**When to use:** 95**When to use:**
96
92- **CI mode**: Automated testing, parallel runs, temporary 97- **CI mode**: Automated testing, parallel runs, temporary
93- **Production mode**: Manual audits, monitoring, persistent 98- **Production mode**: Manual audits, monitoring, persistent
94 99
@@ -100,7 +105,7 @@ let config = AuditConfig::production("prod-server-1");
100use grasp_audit::audit::{AuditConfig, AuditEventBuilder}; 105use grasp_audit::audit::{AuditConfig, AuditEventBuilder};
101use nostr_sdk::prelude::*; 106use nostr_sdk::prelude::*;
102 107
103let config = AuditConfig::ci(); 108let config = AuditConfig::isolated();
104let keys = Keys::generate(); 109let keys = Keys::generate();
105 110
106// Create audit event 111// Create audit event
@@ -121,7 +126,7 @@ let event = AuditEventBuilder::new(&config, Kind::TextNote, "test content")
121use grasp_audit::client::AuditClient; 126use grasp_audit::client::AuditClient;
122use grasp_audit::audit::AuditConfig; 127use grasp_audit::audit::AuditConfig;
123 128
124let config = AuditConfig::ci(); 129let config = AuditConfig::isolated();
125let client = AuditClient::new(config, keys); 130let client = AuditClient::new(config, keys);
126 131
127// Connect to relay 132// Connect to relay
@@ -144,14 +149,15 @@ let events = client.query().await?;
144 149
145```rust 150```rust
146// CI mode generates unique UUID per run 151// CI mode generates unique UUID per run
147let config1 = AuditConfig::ci(); 152let config1 = AuditConfig::isolated();
148let config2 = AuditConfig::ci(); 153let config2 = AuditConfig::isolated();
149 154
150// config1.run_id != config2.run_id 155// config1.run_id != config2.run_id
151// Tests won't interfere with each other 156// Tests won't interfere with each other
152``` 157```
153 158
154**Benefits:** 159**Benefits:**
160
155- ✅ Parallel CI/CD runs don't conflict 161- ✅ Parallel CI/CD runs don't conflict
156- ✅ Can run multiple test suites simultaneously 162- ✅ Can run multiple test suites simultaneously
157- ✅ Easy to identify which run created which events 163- ✅ Easy to identify which run created which events
@@ -194,18 +200,20 @@ grasp-audit/src/specs/
194### Unit vs Integration Tests 200### Unit vs Integration Tests
195 201
196**Unit Tests** (no relay required): 202**Unit Tests** (no relay required):
203
197```rust 204```rust
198#[cfg(test)] 205#[cfg(test)]
199mod tests { 206mod tests {
200 #[test] 207 #[test]
201 fn test_audit_config() { 208 fn test_audit_config() {
202 let config = AuditConfig::ci(); 209 let config = AuditConfig::isolated();
203 assert!(config.run_id.starts_with("ci-")); 210 assert!(config.run_id.starts_with("ci-"));
204 } 211 }
205} 212}
206``` 213```
207 214
208**Integration Tests** (relay required): 215**Integration Tests** (relay required):
216
209```rust 217```rust
210#[cfg(test)] 218#[cfg(test)]
211mod tests { 219mod tests {
@@ -218,6 +226,7 @@ mod tests {
218``` 226```
219 227
220**Running tests:** 228**Running tests:**
229
221```bash 230```bash
222# Unit tests (fast, no dependencies) 231# Unit tests (fast, no dependencies)
223cargo test --lib 232cargo test --lib
@@ -248,7 +257,7 @@ for result in &results {
248// Summary 257// Summary
249let passed = results.iter().filter(|r| r.is_pass()).count(); 258let passed = results.iter().filter(|r| r.is_pass()).count();
250let total = results.len(); 259let total = results.len();
251println!("Results: {}/{} passed ({:.1}%)", 260println!("Results: {}/{} passed ({:.1}%)",
252 passed, total, (passed as f64 / total as f64) * 100.0); 261 passed, total, (passed as f64 / total as f64) * 100.0);
253``` 262```
254 263
@@ -300,6 +309,7 @@ grasp-audit audit --relay ws://localhost:7000
300**Impact:** Events created with old tags won't be found by new queries. 309**Impact:** Events created with old tags won't be found by new queries.
301 310
302**Mitigation:** 311**Mitigation:**
312
303- ✅ Accept breaking changes in alpha stage 313- ✅ Accept breaking changes in alpha stage
304- ✅ Document migration clearly 314- ✅ Document migration clearly
305- ✅ Old events auto-expire via cleanup 315- ✅ Old events auto-expire via cleanup
@@ -316,6 +326,7 @@ grasp-audit audit --relay ws://localhost:7000
316**Solution:** Built-in cleanup strategy from day one. 326**Solution:** Built-in cleanup strategy from day one.
317 327
318**Implementation:** 328**Implementation:**
329
319- Every event has cleanup timestamp 330- Every event has cleanup timestamp
320- Relay can cleanup expired events 331- Relay can cleanup expired events
321- No deletion event pollution (direct DB cleanup) 332- No deletion event pollution (direct DB cleanup)
@@ -329,9 +340,10 @@ grasp-audit audit --relay ws://localhost:7000
329**Benefit:** CI/CD can run multiple test suites simultaneously. 340**Benefit:** CI/CD can run multiple test suites simultaneously.
330 341
331**Pattern:** 342**Pattern:**
343
332```rust 344```rust
333// Each CI run gets unique ID 345// Each CI run gets unique ID
334let config = AuditConfig::ci(); 346let config = AuditConfig::isolated();
335// run_id = "ci-{uuid}" 347// run_id = "ci-{uuid}"
336 348
337// Tests isolated by run ID 349// Tests isolated by run ID
@@ -346,6 +358,7 @@ let events = client.query().await?;
346**Lesson:** Using standard NIP-01 "t" tags instead of custom tags. 358**Lesson:** Using standard NIP-01 "t" tags instead of custom tags.
347 359
348**Benefits:** 360**Benefits:**
361
349- ✅ No conflicts with other systems 362- ✅ No conflicts with other systems
350- ✅ Standard relay filtering works 363- ✅ Standard relay filtering works
351- ✅ Better interoperability 364- ✅ Better interoperability
@@ -382,11 +395,13 @@ let events = client.query().await?;
382**Symptoms:** Tests timeout or fail to connect 395**Symptoms:** Tests timeout or fail to connect
383 396
384**Causes:** 397**Causes:**
398
3851. No relay running 3991. No relay running
3862. Wrong relay URL 4002. Wrong relay URL
3873. Firewall blocking connection 4013. Firewall blocking connection
388 402
389**Solution:** 403**Solution:**
404
390```bash 405```bash
391# Start relay 406# Start relay
392docker run --rm -p 7000:7000 scsibug/nostr-rs-relay 407docker run --rm -p 7000:7000 scsibug/nostr-rs-relay
@@ -405,14 +420,16 @@ cargo test -- --ignored
405**Symptoms:** Query returns empty even though events were sent 420**Symptoms:** Query returns empty even though events were sent
406 421
407**Causes:** 422**Causes:**
423
4081. Wrong run ID (querying different run) 4241. Wrong run ID (querying different run)
4092. Connection timing (query before event propagated) 4252. Connection timing (query before event propagated)
4103. Tag mismatch (uppercase vs lowercase) 4263. Tag mismatch (uppercase vs lowercase)
411 427
412**Solution:** 428**Solution:**
429
413```rust 430```rust
414// Use same config for send and query 431// Use same config for send and query
415let config = AuditConfig::ci(); 432let config = AuditConfig::isolated();
416 433
417// Wait for event to propagate 434// Wait for event to propagate
418tokio::time::sleep(Duration::from_millis(500)).await; 435tokio::time::sleep(Duration::from_millis(500)).await;
@@ -430,6 +447,7 @@ let t_tag = SingleLetterTag::lowercase(Alphabet::T); // Lowercase!
430**Cause:** Not in Nix dev environment 447**Cause:** Not in Nix dev environment
431 448
432**Solution:** 449**Solution:**
450
433```bash 451```bash
434# Enter Nix environment first 452# Enter Nix environment first
435cd grasp-audit 453cd grasp-audit
@@ -447,10 +465,10 @@ cargo build
447 465
448```rust 466```rust
449// CI mode 467// CI mode
450let config = AuditConfig::ci(); 468let config = AuditConfig::isolated();
451 469
452// Production mode 470// Production mode
453let config = AuditConfig::production("run-id"); 471let config = AuditConfig::shared();
454``` 472```
455 473
456### Event Creation 474### Event Creation
@@ -494,5 +512,5 @@ cargo run -- audit --relay ws://localhost:7000
494 512
495--- 513---
496 514
497*Last updated: November 4, 2025* 515_Last updated: November 4, 2025_
498*Status: Living document - update as grasp-audit evolves* 516_Status: Living document - update as grasp-audit evolves_