upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/nostr/builder.rs
AgeCommit message (Collapse)Author
2026-01-09chore: cargo fmtDanConwayDev
2026-01-09feat: implement state event authorization per GRASP-01 specDanConwayDev
Add comprehensive authorization checks to ensure state events are only accepted from maintainers of accepted repository announcements. This implements the core GRASP-01 requirement that pushes must match the latest state announcement "respecting the maintainer set." Changes: 1. StatePolicy authorization (src/nostr/policy/state.rs): - Check authorization BEFORE git data validation (fail-fast) - Reject if no announcement exists for repository - Reject if author not in maintainer set - Use existing helpers: fetch_repository_data() and pubkey_authorised_for_repo_owners() - Structured logging for all rejections 2. Purgatory invalidation (src/nostr/builder.rs): - New method: check_purgatory_state_events_for_identifier() - Called when announcements accepted (Accept and AcceptMaintainer) - Re-evaluates state events in purgatory for the identifier - Processes newly-authorized events (releases from purgatory) - Keeps unauthorized events for natural expiry (30 min) - Enables retroactive authorization when announcements arrive late 3. Purgatory sync authorization (src/git/sync.rs): - Check authorization BEFORE processing git data - Remove unauthorized events from purgatory (permanent rejection) - Prevents processing even if git data arrives first - Structured logging for monitoring 4. Rejected events tracking (src/sync/rejected_index.rs): - Add support for tracking rejected state events - New methods: add_state(), contains_state() - Separate metrics for state rejections - Enables sync to avoid re-fetching rejected states 5. Sync metrics (src/sync/metrics.rs, src/sync/mod.rs): - Add state-specific metrics (hot cache, cold index) - Track rejected states separately from announcements - Support monitoring of authorization rejections 6. Comprehensive tests (tests/state_authorization.rs): - test_reject_state_without_announcement - test_reject_state_from_unauthorized_author - test_accept_state_from_announcement_author - test_accept_state_from_maintainer Security Impact: - Before: State events could be published by anyone - After: Only maintainers can publish state events - Defense-in-depth: Authorization checked at 3 points: 1. On arrival (StatePolicy) 2. On announcement acceptance (purgatory re-evaluation) 3. On git data arrival (purgatory sync) All tests pass: - 248 unit tests - 51 NIP-34 announcement tests - 4 new state authorization tests - 9 rejected index tests Closes: State authorization requirement from GRASP-01 spec
2026-01-08refactor: replace hardcoded Kind constants with rust-nostr variantsDanConwayDev
- Replace KIND_REPOSITORY_ANNOUNCEMENT with Kind::GitRepoAnnouncement - Replace KIND_REPOSITORY_STATE with Kind::RepoState - Replace KIND_PR with Kind::GitPullRequest - Replace KIND_PR_UPDATE with Kind::GitPullRequestUpdate - Replace KIND_USER_GRASP_LIST with Kind::GitUserGraspList - Replace KIND_PATCH with Kind::GitPatch - Replace KIND_ISSUE with Kind::GitIssue - Replace KIND_COMMENT with Kind::Comment - Replace all Kind::Custom(30617|30618|1617|1618|1619|1621|1111|10317) patterns - Remove all hardcoded KIND_* constants from events.rs - Update all match statements to use Kind enum directly - Update all filter builders to use Kind variants - Update all test helpers and assertions Benefits: - Type safety: compiler prevents wrong kind numbers - Readability: Kind::GitRepoAnnouncement is self-documenting - Maintainability: single source of truth (rust-nostr) - IDE support: full autocompletion and refactoring - Standards: aligns with rust-nostr best practices Files modified: 21 Constants removed: 9 Patterns replaced: 100+ Tests passing: 222/222
2026-01-08chore: cargo fmtDanConwayDev
2026-01-08feat(purgatory): track expired events to prevent infinite re-sync loopsDanConwayDev
Adds expired event tracking to prevent proactive sync from repeatedly fetching and re-adding events that expired from purgatory without finding git data. Key features: - Track expired events for 7 days to prevent re-sync loops - Distinguish synced vs user-submitted events (via socket address) - Allow users to retry expired events (git data might now be available) - Reject synced expired events (prevents infinite loop) - Daily cleanup of expired event records older than 7 days Implementation: - Added expired_events: DashMap<EventId, Instant> to Purgatory - Updated event_ids() to include both purgatory + expired events - Added is_expired(), mark_expired(), cleanup_expired_events() - Updated cleanup() to mark expired events automatically - Added is_synced detection in WritePolicy (localhost:0 = synced) - Policy layer checks is_synced && is_expired() before rejecting Behavior: - Negentropy: Filters expired events before fetching (optimal) - REQ+EOSE: Rejects synced expired events at policy layer - User submissions: Always allowed to retry (skip expired check) Testing: - Added 5 new tests for expired event tracking - All 222 tests passing Fixes the infinite re-sync loop where events without git data would expire, get synced again, expire again, repeat forever.
2026-01-05purgatory: git data sync applies state and saves eventDanConwayDev
2026-01-02sync: use purgatoryDanConwayDev
don't save new events destined for purgatory events directly to db or serve on websockets don't download events already in purgatory via negentropy sync
2025-12-31purgatory: fix pr event recieve codeDanConwayDev
2025-12-31purgatory: fix state event receive codeDanConwayDev
2025-12-24feat(purgatory): add broken purgatory implementationDanConwayDev
2025-12-22chore: bump rust-nostr to latest masterDanConwayDev
so we can more easily support grasp purgatory feature
2025-12-22accept all UserGraspList for better discoveryDanConwayDev
2025-12-11fix: resolve all fmt and clippy warningsDanConwayDev
Main lib (src/): - Add #[allow(dead_code)] for build_info field (stored to prevent Prometheus unregistration) - Add #[allow(dead_code)] for first_seen field (reserved for future rate limiting) - Replace .or_insert_with(RelaySyncNeeds::default) with .or_default() - Replace manual div_ceil implementations with .div_ceil(100) Test code (tests/): - Replace .expect(&format!(...)) with .unwrap_or_else(|_| panic!(...)) - Remove needless borrows in fetch_metrics() calls - Add #[allow(dead_code)] and #[allow(unused_imports)] to test helpers module grasp-audit: - Apply cargo fmt to fix formatting
2025-12-05sync fixesDanConwayDev
2025-12-04feat(sync): Phase 2 - multi-relay and complete filtersDanConwayDev
- Add relay discovery from stored announcements - Implement FilterService with three-layer strategy - Support multiple simultaneous relay connections - Filter batching for large tag sets
2025-12-04feat(sync): Phase 1 MVP - single relay proactive syncDanConwayDev
- Add src/sync/ module with SyncManager - Add NGIT_SYNC_RELAY_URL config option - Subscribe to kind 30617 on configured relay - Validate synced events through Nip34WritePolicy - Integration test with two TestRelay instances
2025-12-04refactor: split Nip34WritePolicy into focused sub-policiesDanConwayDev
Split the ~900 line Nip34WritePolicy into focused sub-policies for improved testability and maintainability: - AnnouncementPolicy - Repository announcement validation - StatePolicy - State event validation + ref alignment - PrEventPolicy - PR/PR Update validation - RelatedEventPolicy - Forward/backward reference checking The main Nip34WritePolicy now delegates to these sub-policies via a shared PolicyContext that provides domain, database, and git_data_path. Also updates: - README.md: Accurate project structure reflecting actual implementation - docs/learnings: Marks this technical debt item as complete
2025-12-03feat: accept maintainer announcements without service listingDanConwayDev
2025-12-03improved settings cli flags > env vars > defaultsDanConwayDev
2025-12-03feat: implement LMDB database backendDanConwayDev
- Add nostr-lmdb dependency (v0.44) for persistent storage - Create SharedDatabase type alias for database abstraction - Update all database-related functions to use trait object - Support runtime selection via NGIT_DATABASE_BACKEND env var Database backends: - memory: In-memory (default, fastest, no persistence) - lmdb: LMDB backend (persistent, general purpose) All 34 tests pass with the new implementation.
2025-12-01try and add / update / delete refs on state updateDanConwayDev
if we have the OIDs
2025-12-01fix cargo clippy and fmt warningsDanConwayDev
2025-12-01reject push when refs/nostr/<event-id> doesnt match known event and delete ↵DanConwayDev
incorrect ref on event receive
2025-11-28fix maintainer recursionDanConwayDev
2025-11-28sync HEAD on state event and git data pushDanConwayDev
2025-11-21remove initial blank commit on bare repo creationDanConwayDev
we dont need it
2025-11-21fixed http cloneDanConwayDev
but do we really nedd to create a blank commit? I dont think ngit-relay does that. Do we need to se the default branch or is this automatic?
2025-11-21add repository creationDanConwayDev
2025-11-21feat: add database backend configuration optionsDanConwayDev
Add environment variable configuration for database backend selection: - Added DatabaseBackend enum (memory, nostrdb, lmdb) in src/config.rs - Updated relay builder to use configured backend in src/nostr/builder.rs - Added NGIT_DATABASE_BACKEND to .env.example with documentation - Updated docs/reference/configuration.md with backend comparison table NostrDB and LMDB backends prepared for future implementation when nostr-relay-builder adds support. Currently defaults to in-memory database with warning logs when persistent backends are selected.
2025-11-21fix: correct addressable event format for regular replaceable eventsDanConwayDev
- Fixed bug where regular replaceable events (10000-19999) were using wrong address format (3 colons instead of 2) - Regular replaceable now use kind:pubkey format (1 colon) - Parameterized replaceable (30000-39999) correctly use kind:pubkey:d-identifier (2 colons) - Refactored to eliminate code duplication between both replaceable event types - Updated documentation to reflect correct addressing for both types
2025-11-21refactor: optimize is_referenced_by_accepted for addressable eventsDanConwayDev
- Remove uppercase 'Q' tag (not in Nostr spec) - Add support for addressable references in 'q' tags - Optimize queries based on event type: - Addressable events (kind >= 30000): only check a, A, q with coordinates - Regular events: only check e, E, q with event IDs - Handle addressable events without 'd' tag (empty identifier) - Reduce query count from up to 6 to maximum 3 per event type
2025-11-21Optimize database queries in admit_event filterDanConwayDev
- Replace individual queries with batched operations - Group addressable references by kind to reduce queries - Query all event IDs in single batch operation - Reduces N+M queries to ~K+1 queries (75% reduction typical case) - All 37 tests passing, functionality preserved
2025-11-21Implement GRASP-01 stateful write policy with database queriesDanConwayDev
- Add Nip34WritePolicy with Arc<MemoryDatabase> for stateful event validation - Implement full GRASP-01 event acceptance policy: * Accept events referencing accepted repositories (via a, A, q tags) * Accept events referencing accepted events (transitive, via e, E, q tags) * Support forward references (events referenced by accepted events) * Reject orphan events with no valid references - Extract and validate all reference tag types (a, A, q, e, E) - Query database for repository and event existence checks - Implement fail-secure error handling for database query failures Test improvements: - Fix send_and_verify_rejected to handle relay rejection errors properly - Fix RepoWithIssue fixture usage in forward reference tests - Add database synchronization polling for race condition mitigation - Achieve 94% test pass rate (16/17 integration tests passing)
2025-11-19add landing page and nostr-relay-builder relay on same portDanConwayDev