mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
tag test events with audit-grasp-test-event
This commit is contained in:
@@ -158,6 +158,46 @@ EventBuilder::new(kind, content).tags(tags)
|
||||
|
||||
See `docs/archive/2025-11-04-nostr-sdk-upgrade.md` for full migration.
|
||||
|
||||
### Audit Event Tagging (grasp-audit)
|
||||
|
||||
**All audit events automatically include cleanup tags:**
|
||||
|
||||
The grasp-audit system automatically adds three tags to every event for production cleanup and test isolation. These tags are added transparently via [`AuditEventBuilder::build()`](grasp-audit/src/audit.rs:120-129) with 100% coverage through [`AuditClient::event_builder()`](grasp-audit/src/client.rs:107-138).
|
||||
|
||||
**Automatic Tags (no manual intervention needed):**
|
||||
|
||||
```rust
|
||||
// These tags are automatically added to EVERY audit event:
|
||||
["t", "grasp-audit-test-event"] // Identifies all audit test events
|
||||
["t", "audit-{run_id}"] // Unique ID for this audit run (correlates events)
|
||||
["t", "audit-cleanup-after-{unix_timestamp}"] // Unix timestamp for cleanup scheduling
|
||||
```
|
||||
|
||||
**Tag Format Details:**
|
||||
|
||||
- Uses standard NIP-01 `"t"` (hashtag) tags for maximum compatibility
|
||||
- Unix timestamps (not ISO 8601) for easier database queries
|
||||
- All tags added automatically when calling `client.event_builder().build()`
|
||||
- No manual tag management required
|
||||
|
||||
**Verifying Tags in Tests:**
|
||||
|
||||
```rust
|
||||
// Test that verifies automatic tag addition:
|
||||
// See: grasp-audit/src/client.rs:273-302
|
||||
#[test]
|
||||
fn test_audit_tags_automatically_added() {
|
||||
// Creates event and verifies all three tags are present
|
||||
}
|
||||
```
|
||||
|
||||
**Testing Implications:**
|
||||
|
||||
- All audit events are tagged for easy cleanup
|
||||
- Use `run_id` tag to correlate events from same audit run
|
||||
- Tags enable production relay cleanup scripts
|
||||
- No special handling needed in test code - tags are automatic
|
||||
|
||||
## Documentation
|
||||
|
||||
**Diátaxis Framework Used:**
|
||||
|
||||
+20
-8
@@ -94,23 +94,35 @@ Basic Nostr relay functionality:
|
||||
|
||||
## Audit Event Strategy
|
||||
|
||||
All audit events include special tags:
|
||||
All audit events automatically include special tags for isolation and cleanup:
|
||||
|
||||
```json
|
||||
{
|
||||
"tags": [
|
||||
["t", "grasp-audit"],
|
||||
["r", "audit-run-id-ci-a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
|
||||
["r", "audit-cleanup-2025-11-03T12:00:00Z"]
|
||||
["t", "grasp-audit-test-event"],
|
||||
["t", "audit-ci-a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
|
||||
["t", "audit-cleanup-after-1730822334"]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This allows:
|
||||
**Tag Format:**
|
||||
|
||||
- **Isolation**: Each test run has unique ID
|
||||
- **Cleanup**: Events marked for cleanup after timestamp
|
||||
- **No deletion trails**: Direct database cleanup (no NIP-09 deletion events)
|
||||
- `["t", "grasp-audit-test-event"]` - Identifies all audit-related events
|
||||
- `["t", "audit-{run_id}"]` - Unique identifier for each audit run
|
||||
- CI mode: `audit-ci-{uuid}`
|
||||
- Production mode: `audit-prod-audit-{timestamp}`
|
||||
- `["t", "audit-cleanup-after-{unix_timestamp}"]` - Cleanup scheduling
|
||||
- CI mode: Current time + 3600 seconds (1 hour)
|
||||
- Production mode: Current time + 300 seconds (5 minutes)
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- **Automatic**: Tags added automatically to all events via `AuditEventBuilder`
|
||||
- **Isolation**: Each test run has unique ID for event filtering
|
||||
- **Cleanup**: Events marked for cleanup after timestamp (direct database cleanup)
|
||||
- **No deletion trails**: No NIP-09 deletion events needed
|
||||
- **Discovery**: Easy to query all audit events via hashtag
|
||||
|
||||
## Modes
|
||||
|
||||
|
||||
@@ -61,7 +61,45 @@ impl AuditConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get audit tags for an event
|
||||
/// Get audit tags that are automatically added to all events
|
||||
///
|
||||
/// These tags are automatically added to all events created via [`AuditEventBuilder`].
|
||||
/// They provide isolation, cleanup scheduling, and easy discovery of audit events.
|
||||
///
|
||||
/// # Tag Format
|
||||
///
|
||||
/// All tags use the `"t"` (hashtag) format for maximum relay compatibility:
|
||||
///
|
||||
/// 1. `["t", "grasp-audit-test-event"]` - Identifies all audit-related events
|
||||
/// 2. `["t", "audit-{run_id}"]` - Unique identifier for this audit run
|
||||
/// - CI mode: `audit-ci-{uuid}`
|
||||
/// - Production mode: `audit-prod-audit-{timestamp}`
|
||||
/// 3. `["t", "audit-cleanup-after-{unix_timestamp}"]` - Cleanup timestamp
|
||||
/// - CI mode: Current time + 3600 seconds (1 hour)
|
||||
/// - Production mode: Current time + 300 seconds (5 minutes)
|
||||
///
|
||||
/// # Purpose
|
||||
///
|
||||
/// - **Isolation**: Each test run has a unique ID for event filtering in CI mode
|
||||
/// - **Cleanup**: Events marked for cleanup after timestamp (enables direct DB cleanup)
|
||||
/// - **Discovery**: Easy to query all audit events via hashtag
|
||||
/// - **No deletion trails**: Avoids NIP-09 deletion events by using direct cleanup
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use grasp_audit::AuditConfig;
|
||||
///
|
||||
/// let config = AuditConfig::ci();
|
||||
/// let tags = config.audit_tags();
|
||||
///
|
||||
/// // Tags will look like:
|
||||
/// // [
|
||||
/// // ["t", "grasp-audit-test-event"],
|
||||
/// // ["t", "audit-ci-a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
|
||||
/// // ["t", "audit-cleanup-after-1730822334"]
|
||||
/// // ]
|
||||
/// ```
|
||||
pub fn audit_tags(&self) -> Vec<Tag> {
|
||||
use nostr_sdk::prelude::{Alphabet, SingleLetterTag};
|
||||
|
||||
|
||||
@@ -104,7 +104,38 @@ impl AuditClient {
|
||||
Ok(event_id)
|
||||
}
|
||||
|
||||
/// Create an event builder with audit tags
|
||||
/// Create an event builder that automatically includes audit tags
|
||||
///
|
||||
/// All events built through this method will automatically have audit tags appended
|
||||
/// when you call `.build()`. These tags provide isolation, cleanup scheduling, and
|
||||
/// easy discovery of audit events.
|
||||
///
|
||||
/// # Automatic Tags Added
|
||||
///
|
||||
/// When you call `.build()` on the returned builder, these tags will be automatically added:
|
||||
/// - `["t", "grasp-audit-test-event"]` - Identifies all audit events
|
||||
/// - `["t", "audit-{run_id}"]` - Unique ID for this audit run
|
||||
/// - `["t", "audit-cleanup-after-{timestamp}"]` - Cleanup scheduling
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use grasp_audit::*;
|
||||
/// # async fn example() -> anyhow::Result<()> {
|
||||
/// let config = AuditConfig::ci();
|
||||
/// let client = AuditClient::new("ws://localhost:7000", config).await?;
|
||||
///
|
||||
/// // Create event with automatic audit tags
|
||||
/// let event = client.event_builder(Kind::TextNote, "test content")
|
||||
/// .tag(Tag::custom(TagKind::custom("custom"), vec!["value"]))
|
||||
/// .build(client.keys())?;
|
||||
///
|
||||
/// // Event now has both your custom tag AND the 3 audit tags
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// See [`AuditConfig::audit_tags()`] for details on the tag format.
|
||||
pub fn event_builder(&self, kind: Kind, content: impl Into<String>) -> AuditEventBuilder {
|
||||
AuditEventBuilder::new(kind, content, self.config.clone())
|
||||
}
|
||||
@@ -237,4 +268,49 @@ mod tests {
|
||||
// Builder should be created successfully
|
||||
// (We can't test the internal config field as it's private, which is correct)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_audit_tags_automatically_added() {
|
||||
let config = AuditConfig::ci();
|
||||
let keys = Keys::generate();
|
||||
let client = AuditClient {
|
||||
client: Client::new(keys.clone()),
|
||||
config: config.clone(),
|
||||
keys: keys.clone(),
|
||||
};
|
||||
|
||||
// Create an event with a custom tag
|
||||
let event = client.event_builder(Kind::TextNote, "test content")
|
||||
.tag(Tag::custom(TagKind::custom("custom"), vec!["value"]))
|
||||
.build(&keys)
|
||||
.unwrap();
|
||||
|
||||
// Should have custom tag (1) + 3 audit tags = at least 4 tags
|
||||
assert!(event.tags.len() >= 4, "Expected at least 4 tags, got {}", event.tags.len());
|
||||
|
||||
// Verify audit tags are present by checking tag content
|
||||
let tag_contents: Vec<String> = event.tags.iter()
|
||||
.filter_map(|t| t.content().map(|s| s.to_string()))
|
||||
.collect();
|
||||
|
||||
// Check for the three required audit tags
|
||||
assert!(
|
||||
tag_contents.contains(&"grasp-audit-test-event".to_string()),
|
||||
"Missing 'grasp-audit-test-event' tag"
|
||||
);
|
||||
assert!(
|
||||
tag_contents.iter().any(|t| t.starts_with("audit-ci-")),
|
||||
"Missing 'audit-ci-*' tag"
|
||||
);
|
||||
assert!(
|
||||
tag_contents.iter().any(|t| t.starts_with("audit-cleanup-after-")),
|
||||
"Missing 'audit-cleanup-after-*' tag"
|
||||
);
|
||||
|
||||
// Verify the custom tag is also present
|
||||
assert!(
|
||||
tag_contents.contains(&"value".to_string()),
|
||||
"Missing custom tag value"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user