diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-04 08:50:29 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-04 09:23:48 +0000 |
| commit | b3031800cd95601c2d9cd2d24034364d1496b073 (patch) | |
| tree | de91247ecaef26dd59d209ea2d7df3e1772a4c62 | |
| parent | 15d3b0f859c2c5bc74ac602159c26fbccf475cb4 (diff) | |
Migrate to standard NIP-01 't' tags for audit events
- Changed from custom single-letter tags (g, r, c) to standard 't' tags
- Tag values now use descriptive prefixes:
- 'grasp-audit-test-event' (marker tag)
- 'audit-{run-id}' (run identification)
- 'audit-cleanup-after-{timestamp}' (cleanup time)
- Updated audit_tags() in src/audit.rs
- Updated query filtering in src/client.rs
- Updated all tests to verify 't' tag usage
- All tests passing: 12/12 unit tests, 1/1 integration test
- CLI verified working with new tag scheme
This follows standard Nostr conventions and avoids potential
conflicts with other uses of single-letter tags. The 't' tag
is specifically designed for categorization/topics per NIP-01.
| -rw-r--r-- | TAG_MIGRATION_COMPLETE.md | 256 | ||||
| -rw-r--r-- | TAG_MIGRATION_SUMMARY.md | 54 | ||||
| -rw-r--r-- | grasp-audit/TAG_MIGRATION.md | 151 | ||||
| -rw-r--r-- | grasp-audit/src/audit.rs | 54 | ||||
| -rw-r--r-- | grasp-audit/src/client.rs | 13 |
5 files changed, 489 insertions, 39 deletions
diff --git a/TAG_MIGRATION_COMPLETE.md b/TAG_MIGRATION_COMPLETE.md new file mode 100644 index 0000000..c2fdbfc --- /dev/null +++ b/TAG_MIGRATION_COMPLETE.md | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | # ✅ Tag Migration Complete | ||
| 2 | |||
| 3 | **Date:** November 4, 2025 | ||
| 4 | **Task:** Migrate audit tags to standard NIP-01 "t" tags | ||
| 5 | **Status:** ✅ **COMPLETE** | ||
| 6 | |||
| 7 | --- | ||
| 8 | |||
| 9 | ## Summary | ||
| 10 | |||
| 11 | Successfully migrated the audit system from custom single-letter tags (`g`, `r`, `c`) to standard NIP-01 "t" tags (hashtags) to avoid conflicts and follow Nostr conventions. | ||
| 12 | |||
| 13 | --- | ||
| 14 | |||
| 15 | ## What Changed | ||
| 16 | |||
| 17 | ### Tag Structure | ||
| 18 | |||
| 19 | **Before (Custom Tags):** | ||
| 20 | ```rust | ||
| 21 | // "g" tag for marker | ||
| 22 | Tag::custom(TagKind::SingleLetter(g_tag), vec!["grasp-audit"]) | ||
| 23 | |||
| 24 | // "r" tag for run ID | ||
| 25 | Tag::custom(TagKind::SingleLetter(r_tag), vec![run_id]) | ||
| 26 | |||
| 27 | // "c" tag for cleanup | ||
| 28 | Tag::custom(TagKind::SingleLetter(c_tag), vec![timestamp]) | ||
| 29 | ``` | ||
| 30 | |||
| 31 | **After (Standard "t" Tags):** | ||
| 32 | ```rust | ||
| 33 | // "t" tag with descriptive value | ||
| 34 | Tag::custom(TagKind::SingleLetter(t_tag), vec!["grasp-audit-test-event"]) | ||
| 35 | |||
| 36 | // "t" tag with prefixed run ID | ||
| 37 | Tag::custom(TagKind::SingleLetter(t_tag), vec![format!("audit-{}", run_id)]) | ||
| 38 | |||
| 39 | // "t" tag with prefixed cleanup time | ||
| 40 | Tag::custom(TagKind::SingleLetter(t_tag), vec![format!("audit-cleanup-after-{}", timestamp)]) | ||
| 41 | ``` | ||
| 42 | |||
| 43 | ### Tag Value Mapping | ||
| 44 | |||
| 45 | | Purpose | Old Tag | Old Value | New Tag | New Value | | ||
| 46 | |---------|---------|-----------|---------|-----------| | ||
| 47 | | Marker | `g` | `grasp-audit` | `t` | `grasp-audit-test-event` | | ||
| 48 | | Run ID | `r` | `{run-id}` | `t` | `audit-{run-id}` | | ||
| 49 | | Cleanup | `c` | `{timestamp}` | `t` | `audit-cleanup-after-{timestamp}` | | ||
| 50 | |||
| 51 | ### Example Event | ||
| 52 | |||
| 53 | ```json | ||
| 54 | { | ||
| 55 | "kind": 1, | ||
| 56 | "content": "test event", | ||
| 57 | "tags": [ | ||
| 58 | ["t", "grasp-audit-test-event"], | ||
| 59 | ["t", "audit-ci-a1b2c3d4-e5f6-7890-abcd-ef1234567890"], | ||
| 60 | ["t", "audit-cleanup-after-1730707200"] | ||
| 61 | ] | ||
| 62 | } | ||
| 63 | ``` | ||
| 64 | |||
| 65 | --- | ||
| 66 | |||
| 67 | ## Why This Change? | ||
| 68 | |||
| 69 | ### 1. Standards Compliance | ||
| 70 | - "t" tag is the standard NIP-01 mechanism for topics/categories | ||
| 71 | - Follows established Nostr conventions | ||
| 72 | - Better interoperability with other tools | ||
| 73 | |||
| 74 | ### 2. Conflict Avoidance | ||
| 75 | - Custom single-letter tags (`g`, `r`, `c`) could conflict with other uses | ||
| 76 | - "t" tag is specifically designed for categorization | ||
| 77 | - Multiple "t" tags are expected and supported | ||
| 78 | |||
| 79 | ### 3. Self-Documenting | ||
| 80 | - Tag values now clearly indicate their purpose | ||
| 81 | - `grasp-audit-test-event` vs `grasp-audit` | ||
| 82 | - `audit-ci-{uuid}` vs just `{uuid}` | ||
| 83 | - `audit-cleanup-after-{timestamp}` vs just `{timestamp}` | ||
| 84 | |||
| 85 | ### 4. Better Namespacing | ||
| 86 | - All values prefixed with `audit-` or `grasp-audit-` | ||
| 87 | - Reduces chance of collision with other systems | ||
| 88 | - Makes it clear these are audit-related tags | ||
| 89 | |||
| 90 | --- | ||
| 91 | |||
| 92 | ## Files Modified | ||
| 93 | |||
| 94 | ### `grasp-audit/src/audit.rs` | ||
| 95 | - ✅ Updated `audit_tags()` to use "t" tags | ||
| 96 | - ✅ Updated tests to verify "t" tag kind | ||
| 97 | - ✅ All tag values now have descriptive prefixes | ||
| 98 | |||
| 99 | ### `grasp-audit/src/client.rs` | ||
| 100 | - ✅ Updated `query()` to filter by "t" tags | ||
| 101 | - ✅ Changed from multiple single-letter tags to "t" tag with multiple values | ||
| 102 | |||
| 103 | ### `grasp-audit/TAG_MIGRATION.md` | ||
| 104 | - ✅ Comprehensive documentation of the migration | ||
| 105 | - ✅ Rationale, examples, and verification steps | ||
| 106 | |||
| 107 | --- | ||
| 108 | |||
| 109 | ## Testing Results | ||
| 110 | |||
| 111 | ### Unit Tests: 12/12 ✅ | ||
| 112 | ``` | ||
| 113 | ✓ audit::tests::test_ci_config | ||
| 114 | ✓ audit::tests::test_production_config | ||
| 115 | ✓ audit::tests::test_audit_tags | ||
| 116 | ✓ audit::tests::test_audit_event_builder | ||
| 117 | ✓ client::tests::test_client_creation | ||
| 118 | ✓ client::tests::test_event_builder | ||
| 119 | ✓ isolation::tests::test_generate_ci_run_id | ||
| 120 | ✓ isolation::tests::test_generate_prod_run_id | ||
| 121 | ✓ isolation::tests::test_generate_test_id | ||
| 122 | ✓ result::tests::test_audit_result | ||
| 123 | ✓ result::tests::test_result_pass | ||
| 124 | ✓ result::tests::test_result_fail | ||
| 125 | ``` | ||
| 126 | |||
| 127 | ### Integration Tests: 1/1 ✅ | ||
| 128 | ``` | ||
| 129 | ✓ specs::nip01_smoke::tests::test_smoke_tests_against_relay | ||
| 130 | ``` | ||
| 131 | |||
| 132 | ### CLI Verification: ✅ | ||
| 133 | ```bash | ||
| 134 | $ nix develop -c cargo run -- audit \ | ||
| 135 | --relay ws://localhost:7000 \ | ||
| 136 | --mode ci \ | ||
| 137 | --spec nip01-smoke | ||
| 138 | |||
| 139 | Results: 6/6 passed (100.0%) | ||
| 140 | ✅ All tests passed! | ||
| 141 | ``` | ||
| 142 | |||
| 143 | All smoke tests pass: | ||
| 144 | - ✅ websocket_connection | ||
| 145 | - ✅ send_receive_event | ||
| 146 | - ✅ create_subscription | ||
| 147 | - ✅ close_subscription | ||
| 148 | - ✅ reject_invalid_signature | ||
| 149 | - ✅ reject_invalid_event_id | ||
| 150 | |||
| 151 | --- | ||
| 152 | |||
| 153 | ## Breaking Changes | ||
| 154 | |||
| 155 | ⚠️ **Note:** This is a breaking change for event queries. | ||
| 156 | |||
| 157 | Events created with the old tag scheme will not be found by new queries. This is acceptable because: | ||
| 158 | |||
| 159 | 1. **Alpha Status**: System is in development | ||
| 160 | 2. **Test Data Only**: Old events are just test data | ||
| 161 | 3. **Auto Cleanup**: Events expire via cleanup timestamps | ||
| 162 | 4. **No Production Use**: No production deployments exist | ||
| 163 | |||
| 164 | --- | ||
| 165 | |||
| 166 | ## Benefits Achieved | ||
| 167 | |||
| 168 | ✅ **Standards Compliance**: Uses NIP-01 standard hashtag mechanism | ||
| 169 | ✅ **No Conflicts**: "t" tag is designed for categorization | ||
| 170 | ✅ **Better Namespacing**: Values prefixed to avoid collisions | ||
| 171 | ✅ **Queryable**: Standard filtering works as expected | ||
| 172 | ✅ **Self-Documenting**: Tag values clearly indicate purpose | ||
| 173 | ✅ **Maintainable**: Follows established patterns | ||
| 174 | |||
| 175 | --- | ||
| 176 | |||
| 177 | ## Commit | ||
| 178 | |||
| 179 | ``` | ||
| 180 | commit 820fa67 | ||
| 181 | Author: [automated] | ||
| 182 | Date: November 4, 2025 | ||
| 183 | |||
| 184 | Migrate to standard NIP-01 't' tags for audit events | ||
| 185 | |||
| 186 | - Changed from custom single-letter tags (g, r, c) to standard 't' tags | ||
| 187 | - Tag values now use descriptive prefixes | ||
| 188 | - Updated audit_tags() in src/audit.rs | ||
| 189 | - Updated query filtering in src/client.rs | ||
| 190 | - Updated all tests to verify 't' tag usage | ||
| 191 | - All tests passing: 12/12 unit tests, 1/1 integration test | ||
| 192 | - CLI verified working with new tag scheme | ||
| 193 | ``` | ||
| 194 | |||
| 195 | --- | ||
| 196 | |||
| 197 | ## Verification Commands | ||
| 198 | |||
| 199 | ```bash | ||
| 200 | # Build | ||
| 201 | cd grasp-audit | ||
| 202 | nix develop -c cargo build | ||
| 203 | |||
| 204 | # Unit tests | ||
| 205 | nix develop -c cargo test --lib | ||
| 206 | |||
| 207 | # Integration tests (requires relay) | ||
| 208 | docker run --rm -p 7000:7000 scsibug/nostr-rs-relay | ||
| 209 | nix develop -c cargo test -- --ignored | ||
| 210 | |||
| 211 | # CLI test | ||
| 212 | nix develop -c cargo run -- audit \ | ||
| 213 | --relay ws://localhost:7000 \ | ||
| 214 | --mode ci \ | ||
| 215 | --spec nip01-smoke | ||
| 216 | ``` | ||
| 217 | |||
| 218 | --- | ||
| 219 | |||
| 220 | ## Next Steps | ||
| 221 | |||
| 222 | The audit system is now ready for: | ||
| 223 | |||
| 224 | ### Path 2: GRASP-01 Test Suite | ||
| 225 | - [ ] Create `src/specs/grasp_01_relay.rs` | ||
| 226 | - [ ] Implement repository announcement tests | ||
| 227 | - [ ] Implement state event tests | ||
| 228 | - [ ] Implement maintainer validation tests | ||
| 229 | - [ ] Test against mock relay | ||
| 230 | |||
| 231 | ### Future Enhancements | ||
| 232 | - [ ] Add tag validation helpers | ||
| 233 | - [ ] Document tag format in API docs | ||
| 234 | - [ ] Add examples showing tag usage | ||
| 235 | - [ ] Consider tag versioning for future changes | ||
| 236 | |||
| 237 | --- | ||
| 238 | |||
| 239 | ## References | ||
| 240 | |||
| 241 | - **NIP-01**: https://github.com/nostr-protocol/nips/blob/master/01.md | ||
| 242 | - **SESSION_CONTINUATION_COMPLETE.md**: Previous session work | ||
| 243 | - **TAG_MIGRATION.md**: Detailed migration documentation | ||
| 244 | - **Commit 8190a3a**: Previous tag implementation (g/r/c tags) | ||
| 245 | - **Commit 820fa67**: Current implementation (t tags) | ||
| 246 | |||
| 247 | --- | ||
| 248 | |||
| 249 | **Status:** ✅ **COMPLETE** | ||
| 250 | **All Tests:** 🟢 **PASSING** (13/13) | ||
| 251 | **CLI:** 🟢 **WORKING** | ||
| 252 | **Ready for:** Path 2 (GRASP-01 Test Suite) | ||
| 253 | |||
| 254 | --- | ||
| 255 | |||
| 256 | *Migration completed: November 4, 2025* | ||
diff --git a/TAG_MIGRATION_SUMMARY.md b/TAG_MIGRATION_SUMMARY.md new file mode 100644 index 0000000..34d4ff0 --- /dev/null +++ b/TAG_MIGRATION_SUMMARY.md | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | # 🏷️ Tag Migration Summary | ||
| 2 | |||
| 3 | ## Before → After | ||
| 4 | |||
| 5 | ```diff | ||
| 6 | - ["g", "grasp-audit"] | ||
| 7 | - ["r", "ci-a1b2c3d4-..."] | ||
| 8 | - ["c", "1730707200"] | ||
| 9 | |||
| 10 | + ["t", "grasp-audit-test-event"] | ||
| 11 | + ["t", "audit-ci-a1b2c3d4-..."] | ||
| 12 | + ["t", "audit-cleanup-after-1730707200"] | ||
| 13 | ``` | ||
| 14 | |||
| 15 | ## Why? | ||
| 16 | |||
| 17 | ✅ Standard NIP-01 hashtag mechanism | ||
| 18 | ✅ Avoids conflicts with other single-letter tags | ||
| 19 | ✅ Self-documenting tag values | ||
| 20 | ✅ Better namespacing with prefixes | ||
| 21 | |||
| 22 | ## Status | ||
| 23 | |||
| 24 | | Component | Status | Tests | | ||
| 25 | |-----------|--------|-------| | ||
| 26 | | Tag Generation | ✅ Working | 12/12 pass | | ||
| 27 | | Tag Filtering | ✅ Working | 1/1 pass | | ||
| 28 | | CLI | ✅ Working | 6/6 smoke tests | | ||
| 29 | | Documentation | ✅ Complete | TAG_MIGRATION.md | | ||
| 30 | |||
| 31 | ## Test Results | ||
| 32 | |||
| 33 | ``` | ||
| 34 | Unit Tests: 12/12 ✅ | ||
| 35 | Integration: 1/1 ✅ | ||
| 36 | CLI Smoke: 6/6 ✅ | ||
| 37 | Total: 19/19 ✅ | ||
| 38 | ``` | ||
| 39 | |||
| 40 | ## Files Changed | ||
| 41 | |||
| 42 | - `src/audit.rs` - Tag generation | ||
| 43 | - `src/client.rs` - Query filtering | ||
| 44 | - `TAG_MIGRATION.md` - Documentation | ||
| 45 | |||
| 46 | ## Commit | ||
| 47 | |||
| 48 | ``` | ||
| 49 | 820fa67 - Migrate to standard NIP-01 't' tags for audit events | ||
| 50 | ``` | ||
| 51 | |||
| 52 | --- | ||
| 53 | |||
| 54 | **Ready for:** GRASP-01 Test Suite Development | ||
diff --git a/grasp-audit/TAG_MIGRATION.md b/grasp-audit/TAG_MIGRATION.md new file mode 100644 index 0000000..aaba729 --- /dev/null +++ b/grasp-audit/TAG_MIGRATION.md | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | # Tag Migration to Standard NIP-01 "t" Tags | ||
| 2 | |||
| 3 | **Date:** November 4, 2025 | ||
| 4 | **Status:** ✅ Complete | ||
| 5 | |||
| 6 | ## Overview | ||
| 7 | |||
| 8 | Migrated audit system tags from custom single-letter tags (`g`, `r`, `c`) to standard NIP-01 "t" tags (hashtags) to avoid conflicts and follow Nostr conventions. | ||
| 9 | |||
| 10 | ## Motivation | ||
| 11 | |||
| 12 | The previous tag scheme used: | ||
| 13 | - `g` tag for `grasp-audit` marker | ||
| 14 | - `r` tag for `audit-run-id` | ||
| 15 | - `c` tag for `audit-cleanup` timestamp | ||
| 16 | |||
| 17 | However, this could conflict with other uses of these single-letter tags. The "t" tag is the standard NIP-01 tag type for categorization/topics, making it the appropriate choice for audit event tagging. | ||
| 18 | |||
| 19 | ## Changes Made | ||
| 20 | |||
| 21 | ### Tag Structure | ||
| 22 | |||
| 23 | **Before:** | ||
| 24 | ```rust | ||
| 25 | vec![ | ||
| 26 | Tag::custom(TagKind::SingleLetter(g_tag), vec!["grasp-audit"]), | ||
| 27 | Tag::custom(TagKind::SingleLetter(r_tag), vec![run_id]), | ||
| 28 | Tag::custom(TagKind::SingleLetter(c_tag), vec![cleanup_timestamp]), | ||
| 29 | ] | ||
| 30 | ``` | ||
| 31 | |||
| 32 | **After:** | ||
| 33 | ```rust | ||
| 34 | vec![ | ||
| 35 | Tag::custom(TagKind::SingleLetter(t_tag), vec!["grasp-audit-test-event"]), | ||
| 36 | Tag::custom(TagKind::SingleLetter(t_tag), vec![format!("audit-{}", run_id)]), | ||
| 37 | Tag::custom(TagKind::SingleLetter(t_tag), vec![format!("audit-cleanup-after-{}", timestamp)]), | ||
| 38 | ] | ||
| 39 | ``` | ||
| 40 | |||
| 41 | ### Tag Values | ||
| 42 | |||
| 43 | | Purpose | Old Tag | Old Value | New Tag | New Value | | ||
| 44 | |---------|---------|-----------|---------|-----------| | ||
| 45 | | Marker | `g` | `grasp-audit` | `t` | `grasp-audit-test-event` | | ||
| 46 | | Run ID | `r` | `ci-{uuid}` | `t` | `audit-ci-{uuid}` | | ||
| 47 | | Cleanup | `c` | `{timestamp}` | `t` | `audit-cleanup-after-{timestamp}` | | ||
| 48 | |||
| 49 | ### Example Event Tags | ||
| 50 | |||
| 51 | ```json | ||
| 52 | [ | ||
| 53 | ["t", "grasp-audit-test-event"], | ||
| 54 | ["t", "audit-ci-a1b2c3d4-e5f6-7890-abcd-ef1234567890"], | ||
| 55 | ["t", "audit-cleanup-after-1730707200"] | ||
| 56 | ] | ||
| 57 | ``` | ||
| 58 | |||
| 59 | ## Files Modified | ||
| 60 | |||
| 61 | ### `src/audit.rs` | ||
| 62 | - Updated `audit_tags()` to use "t" tags | ||
| 63 | - Updated tests to check for "t" tag kind | ||
| 64 | - All values now prefixed for clarity | ||
| 65 | |||
| 66 | ### `src/client.rs` | ||
| 67 | - Updated `query()` to filter by "t" tags | ||
| 68 | - Changed from `.custom_tag(g_tag, ...)` to `.custom_tag(t_tag, ...)` | ||
| 69 | |||
| 70 | ## Benefits | ||
| 71 | |||
| 72 | 1. **Standards Compliance**: Uses standard NIP-01 hashtag mechanism | ||
| 73 | 2. **No Conflicts**: "t" tag is designed for categorization | ||
| 74 | 3. **Better Namespacing**: Values prefixed with `audit-` to avoid collisions | ||
| 75 | 4. **Queryable**: Standard tag filtering works as expected | ||
| 76 | 5. **Self-Documenting**: Tag values clearly indicate their purpose | ||
| 77 | |||
| 78 | ## Testing | ||
| 79 | |||
| 80 | All tests pass with the new tag scheme: | ||
| 81 | |||
| 82 | ```bash | ||
| 83 | # Unit tests | ||
| 84 | ✓ 12/12 tests passing | ||
| 85 | |||
| 86 | # Integration tests | ||
| 87 | ✓ 1/1 test passing (NIP-01 smoke tests) | ||
| 88 | |||
| 89 | # CLI verification | ||
| 90 | ✓ All 6 smoke tests pass | ||
| 91 | ``` | ||
| 92 | |||
| 93 | ## Backwards Compatibility | ||
| 94 | |||
| 95 | ⚠️ **Breaking Change**: Events created with old tags will not be found by new queries. | ||
| 96 | |||
| 97 | This is acceptable because: | ||
| 98 | - System is in alpha/development | ||
| 99 | - Old events are test data only | ||
| 100 | - Cleanup happens automatically via timestamps | ||
| 101 | - No production deployments exist yet | ||
| 102 | |||
| 103 | ## Migration Path | ||
| 104 | |||
| 105 | For future tag changes: | ||
| 106 | 1. Consider versioning in tag values (e.g., `grasp-audit-v2-test-event`) | ||
| 107 | 2. Support querying both old and new tags during transition | ||
| 108 | 3. Document breaking changes clearly | ||
| 109 | 4. Provide migration tools if needed | ||
| 110 | |||
| 111 | ## References | ||
| 112 | |||
| 113 | - **NIP-01**: https://github.com/nostr-protocol/nips/blob/master/01.md | ||
| 114 | - **Tag Standardization**: "t" tags for topics/categories | ||
| 115 | - **Previous Implementation**: Commit `8190a3a` (custom g/r/c tags) | ||
| 116 | - **Current Implementation**: Uses standard "t" tags | ||
| 117 | |||
| 118 | ## Verification | ||
| 119 | |||
| 120 | To verify the new tag structure: | ||
| 121 | |||
| 122 | ```bash | ||
| 123 | # Run tests | ||
| 124 | nix develop -c cargo test --lib | ||
| 125 | nix develop -c cargo test -- --ignored | ||
| 126 | |||
| 127 | # Run CLI | ||
| 128 | nix develop -c cargo run -- audit \ | ||
| 129 | --relay ws://localhost:7000 \ | ||
| 130 | --mode ci \ | ||
| 131 | --spec nip01-smoke | ||
| 132 | |||
| 133 | # Check event structure (example) | ||
| 134 | # Events will have tags like: | ||
| 135 | # ["t", "grasp-audit-test-event"] | ||
| 136 | # ["t", "audit-ci-{uuid}"] | ||
| 137 | # ["t", "audit-cleanup-after-{timestamp}"] | ||
| 138 | ``` | ||
| 139 | |||
| 140 | ## Next Steps | ||
| 141 | |||
| 142 | - [ ] Update documentation to reflect new tag scheme | ||
| 143 | - [ ] Consider adding tag validation helpers | ||
| 144 | - [ ] Document tag format in API/spec documentation | ||
| 145 | - [ ] Add examples showing tag usage | ||
| 146 | |||
| 147 | --- | ||
| 148 | |||
| 149 | **Status:** ✅ Migration complete and verified | ||
| 150 | **All tests passing:** 13/13 (12 unit + 1 integration) | ||
| 151 | **CLI verified:** ✅ Working correctly | ||
diff --git a/grasp-audit/src/audit.rs b/grasp-audit/src/audit.rs index e902ace..fad4bf2 100644 --- a/grasp-audit/src/audit.rs +++ b/grasp-audit/src/audit.rs | |||
| @@ -65,22 +65,21 @@ impl AuditConfig { | |||
| 65 | pub fn audit_tags(&self) -> Vec<Tag> { | 65 | pub fn audit_tags(&self) -> Vec<Tag> { |
| 66 | use nostr_sdk::prelude::{Alphabet, SingleLetterTag}; | 66 | use nostr_sdk::prelude::{Alphabet, SingleLetterTag}; |
| 67 | 67 | ||
| 68 | // Use "t" tags for categorization (standard NIP-01 hashtag type) | ||
| 69 | let t_tag = SingleLetterTag::lowercase(Alphabet::T); | ||
| 70 | |||
| 68 | vec![ | 71 | vec![ |
| 69 | // Use single-letter tags for filtering support | ||
| 70 | // "g" = grasp-audit marker | ||
| 71 | Tag::custom( | 72 | Tag::custom( |
| 72 | TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::G)), | 73 | TagKind::SingleLetter(t_tag), |
| 73 | vec!["grasp-audit"] | 74 | vec!["grasp-audit-test-event"] |
| 74 | ), | 75 | ), |
| 75 | // "r" = audit run ID | ||
| 76 | Tag::custom( | 76 | Tag::custom( |
| 77 | TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::R)), | 77 | TagKind::SingleLetter(t_tag), |
| 78 | vec![self.run_id.clone()] | 78 | vec![format!("audit-{}", self.run_id)] |
| 79 | ), | 79 | ), |
| 80 | // "c" = cleanup timestamp | ||
| 81 | Tag::custom( | 80 | Tag::custom( |
| 82 | TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::C)), | 81 | TagKind::SingleLetter(t_tag), |
| 83 | vec![self.cleanup_after.to_string()] | 82 | vec![format!("audit-cleanup-after-{}", self.cleanup_after.as_u64())] |
| 84 | ), | 83 | ), |
| 85 | ] | 84 | ] |
| 86 | } | 85 | } |
| @@ -159,35 +158,30 @@ mod tests { | |||
| 159 | 158 | ||
| 160 | assert_eq!(tags.len(), 3); | 159 | assert_eq!(tags.len(), 3); |
| 161 | 160 | ||
| 162 | let g_tag = SingleLetterTag::lowercase(Alphabet::G); | 161 | let t_tag = SingleLetterTag::lowercase(Alphabet::T); |
| 163 | let r_tag = SingleLetterTag::lowercase(Alphabet::R); | ||
| 164 | let c_tag = SingleLetterTag::lowercase(Alphabet::C); | ||
| 165 | 162 | ||
| 166 | // Check "g" tag (grasp-audit marker) | 163 | // All tags should be "t" tags (hashtags) |
| 167 | assert!(tags.iter().any(|t| { | 164 | for tag in &tags { |
| 168 | if let TagKind::SingleLetter(letter) = t.kind() { | 165 | if let TagKind::SingleLetter(letter) = tag.kind() { |
| 169 | letter == g_tag | 166 | assert_eq!(letter, t_tag); |
| 170 | } else { | 167 | } else { |
| 171 | false | 168 | panic!("Expected SingleLetter tag"); |
| 172 | } | 169 | } |
| 170 | } | ||
| 171 | |||
| 172 | // Check for "t" tag with "grasp-audit-test-event" | ||
| 173 | assert!(tags.iter().any(|t| { | ||
| 174 | t.content() == Some("grasp-audit-test-event") | ||
| 173 | })); | 175 | })); |
| 174 | 176 | ||
| 175 | // Check "r" tag (audit run ID) | 177 | // Check for "t" tag with "audit-{run_id}" |
| 176 | assert!(tags.iter().any(|t| { | 178 | assert!(tags.iter().any(|t| { |
| 177 | if let TagKind::SingleLetter(letter) = t.kind() { | 179 | t.content().map(|c| c.starts_with("audit-ci-")).unwrap_or(false) |
| 178 | letter == r_tag | ||
| 179 | } else { | ||
| 180 | false | ||
| 181 | } | ||
| 182 | })); | 180 | })); |
| 183 | 181 | ||
| 184 | // Check "c" tag (cleanup timestamp) | 182 | // Check for "t" tag with "audit-cleanup-after-{timestamp}" |
| 185 | assert!(tags.iter().any(|t| { | 183 | assert!(tags.iter().any(|t| { |
| 186 | if let TagKind::SingleLetter(letter) = t.kind() { | 184 | t.content().map(|c| c.starts_with("audit-cleanup-after-")).unwrap_or(false) |
| 187 | letter == c_tag | ||
| 188 | } else { | ||
| 189 | false | ||
| 190 | } | ||
| 191 | })); | 185 | })); |
| 192 | } | 186 | } |
| 193 | 187 | ||
diff --git a/grasp-audit/src/client.rs b/grasp-audit/src/client.rs index d78b33c..4831d3f 100644 --- a/grasp-audit/src/client.rs +++ b/grasp-audit/src/client.rs | |||
| @@ -95,16 +95,11 @@ impl AuditClient { | |||
| 95 | 95 | ||
| 96 | if self.config.mode == AuditMode::CI { | 96 | if self.config.mode == AuditMode::CI { |
| 97 | // In CI mode, only see our own audit events | 97 | // In CI mode, only see our own audit events |
| 98 | // Filter by "g" tag (grasp-audit marker) and "r" tag (run ID) | 98 | // Filter by "t" tags (hashtags) |
| 99 | let t_tag = SingleLetterTag::lowercase(Alphabet::T); | ||
| 99 | filter = filter | 100 | filter = filter |
| 100 | .custom_tag( | 101 | .custom_tag(t_tag, "grasp-audit-test-event") |
| 101 | SingleLetterTag::lowercase(Alphabet::G), | 102 | .custom_tag(t_tag, format!("audit-{}", self.config.run_id)); |
| 102 | "grasp-audit" | ||
| 103 | ) | ||
| 104 | .custom_tag( | ||
| 105 | SingleLetterTag::lowercase(Alphabet::R), | ||
| 106 | &self.config.run_id | ||
| 107 | ); | ||
| 108 | } | 103 | } |
| 109 | // In Production mode, see all events (no filter modification) | 104 | // In Production mode, see all events (no filter modification) |
| 110 | 105 | ||