upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/config.rs
AgeCommit message (Collapse)Author
2026-01-10Implement relay naughty list featureDanConwayDev
Add naughty list tracking for relays with persistent infrastructure issues (DNS failures, TLS certificate errors, protocol violations) to reduce log noise and provide better visibility via metrics. Key features: - Classify errors into naughty (persistent) vs transient (temporary) - Track naughty relays with category, reason, and occurrence count - Log WARN on first naughty occurrence, DEBUG on repeats - Automatic expiration after 12 hours (configurable) - Prometheus metrics for monitoring naughty relays by category - Periodic cleanup task integrated with health checker Components added: - src/sync/naughty_list.rs: Core naughty list tracker with error classification - NaughtyListTracker integration in RelayHealthTracker - Connection error handling updates in sync manager - Naughty list metrics (total by category, detailed info per relay) - Config option for naughty_list_expiration_hours (default: 12) Closes DNS lookup failures and TLS certificate errors tracking issues.
2026-01-09chore: cargo fmtDanConwayDev
2026-01-09feat: Switch SyncManager to use two-tier RejectedEventsIndexDanConwayDev
Replaces the simple HashSet<EventId> with the sophisticated two-tier RejectedEventsIndex from PR1, enabling future immediate re-processing when maintainer dependencies resolve. ## Changes ### Config (src/config.rs) - Add `rejected_hot_cache_duration_secs` (default: 120 = 2 minutes) - Add `rejected_cold_index_expiry_secs` (default: 604800 = 7 days) - Both configurable via CLI flags or environment variables ### SyncManager (src/sync/mod.rs) **Type Change:** - Before: `Arc<RwLock<HashSet<EventId>>>` (simple event ID set) - After: `Arc<RejectedEventsIndex>` (two-tier storage) **Initialization:** - Pass config durations to RejectedEventsIndex::new() - Creates hot cache (2 min) + cold index (7 days) **Event Processing (process_event_static):** - Extract identifier from 'd' tag - Determine rejection reason from error message - Call `add_announcement()` with full event + metadata - Stores in both hot cache and cold index **Negentropy Sync (derive_relay_targets):** - Call `get_all_event_ids()` to get rejected IDs - Returns union of hot cache + cold index event IDs - Excludes from negentropy reconciliation **Event Loop (relay_connection):** - Use `contains()` method instead of direct HashSet access - Simpler API, same skip-rejected behavior ### RejectedEventsIndex (src/sync/rejected_index.rs) **New Method:** - `get_all_event_ids()`: Returns HashSet<EventId> from both tiers - Used for negentropy exclusion (replaces direct HashSet access) ### Tests Updated **test_rejected_events_index_tracks_announcements:** - Create RejectedEventsIndex with config durations - Add 'd' tag to test announcement - Use `add_announcement()` with full event - Verify both hot cache and cold index populated - Check lengths with `hot_cache_len()` and `cold_index_len()` **test_rejected_events_excluded_from_negentropy:** - Create RejectedEventsIndex instead of HashSet - Build full event with 'd' tag - Add to index with `add_announcement()` - Get IDs with `get_all_event_ids()` - Verify excluded from reconciliation ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ SyncManager │ │ │ │ rejected_events_index: Arc<RejectedEventsIndex> │ │ ├─ Hot Cache (2 min): Full events for re-processing │ │ └─ Cold Index (7 days): Metadata for dedup │ └─────────────────────────────────────────────────────────────┘ │ │ On rejection ▼ ┌─────────────────────────────────────────────────────────────┐ │ add_announcement(event, pubkey, identifier, reason) │ │ ├─ Store full event in hot cache │ │ └─ Store metadata in cold index │ └─────────────────────────────────────────────────────────────┘ │ │ On negentropy sync ▼ ┌─────────────────────────────────────────────────────────────┐ │ get_all_event_ids() → HashSet<EventId> │ │ ├─ Union of hot cache IDs │ │ └─ Union of cold index IDs │ └─────────────────────────────────────────────────────────────┘ ``` ## Benefits ### Immediate - **Better tracking**: Store rejection reason + metadata - **Configurable**: Tune cache/index durations per deployment - **Observable**: Separate hot/cold metrics (future PR4) ### Future (PR3) - **Immediate re-processing**: Get events from hot cache when valid - **No 24h delay**: Maintainer announcements accepted in <1 second - **Automatic recovery**: Hot cache for immediate, cold index for later ## Backward Compatibility **No breaking changes:** - Same rejection behavior (skip events in index) - Same negentropy exclusion (union with purgatory IDs) - Default config values match previous implicit behavior **Migration:** - Existing deployments continue working with defaults - Optional: Tune durations via new config flags ## Testing All tests passing: - ✅ 9 rejected_index tests (hot cache, cold index, two-tier) - ✅ 139 sync module tests (including updated integration tests) - ✅ 247 total library tests ## Next Steps **PR3: Add invalidation + immediate re-processing** - Invalidate cold index when owner announcement accepted - Get events from hot cache for re-processing - Recursive call to process_event_static - Integration tests for <1s maintainer acceptance **PR4: Add cleanup + metrics** - Hot cache cleanup task (every 60s) - Cold index cleanup task (daily) - Prometheus metrics for both tiers - Monitor hot cache hits vs misses ## Configuration Examples ```bash # Default (2 min hot cache, 7 day cold index) ngit-grasp # Longer hot cache for slow relays ngit-grasp --rejected-hot-cache-duration-secs 300 # Shorter cold index for memory-constrained systems ngit-grasp --rejected-cold-index-expiry-secs 86400 # Environment variables export NGIT_REJECTED_HOT_CACHE_DURATION_SECS=180 export NGIT_REJECTED_COLD_INDEX_EXPIRY_SECS=259200 ngit-grasp ``` Part of: Maintainer chain discovery fix See: work/SOLUTION-SUMMARY-V2.md for full design Previous: PR1 (rejected_index.rs implementation) Next: PR3 (invalidation + re-processing)
2026-01-09feat: replace owner-npub with relay-owner-nsec for persistent operator identityDanConwayDev
Replace the owner-npub configuration option with relay-owner-nsec to provide a persistent cryptographic identity for the relay operator. This addresses NIP-42 authentication requirements discovered during sync debugging. Motivation: - Some relays (e.g., relay.damus.io) require NIP-42 authentication for advanced features like NIP-77 negentropy sync - Previously used random ephemeral keys per connection, providing no persistent identity - Other relays can now recognize us by pubkey for reputation-based rate limiting - Ensures consistency between NIP-11 pubkey and authentication key Changes: - Config: relay_owner_nsec with auto-load/generate from .relay-owner.nsec - NIP-11: Pubkey derived from nsec instead of separate npub field - Sync: RelayConnection now uses operator keys for NIP-42 auth - Docs: Updated README, .env.example, and added .relay-owner.nsec to gitignore Key Features: - Auto-generates key on first run and saves to .relay-owner.nsec - Loads existing key from file on subsequent runs - Can override via CLI flag or environment variable - Enables reputation building across relay network - Future-ready for event signing and WoT calculations Testing: - 225/232 tests passing (7 pre-existing purgatory failures unrelated) - Verified key generation, loading, and NIP-11 derivation - Release build successful Related: work/sync-debug-analysis.md, work/relay-owner-nsec-implementation.md
2026-01-08fix: sync-bootstrap-relay-url scheme optionalDanConwayDev
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-11sync: test sync works without negentropy and add disable option in syncDanConwayDev
2025-12-11chore: remove unused sync config fieldsDanConwayDev
Remove 4 config fields that were defined but never used: - sync_startup_delay_secs - sync_reconnect_delay_secs - sync_reconnect_lookback_days - sync_startup_jitter_ms These fields were added during GRASP-02 planning but the implementation took a different approach (using hardcoded constants for quick reconnect windows and batch window via env var).
2025-12-11sync: add sync_base_backoff_secs config for better testingDanConwayDev
2025-12-11fix(sync): improve metrics recording and connection failure detectionDanConwayDev
Changes: - Fix connection attempt metrics: record success/failure based on actual connection result instead of pre-emptively recording failure - Add health tracker integration on connection failure: call record_failure() and record_health_state() in error path - Add connection verification in relay_connection.rs: wait 500ms after connect() then verify is_connected() to detect silent failures - Add configurable disconnect check interval via NGIT_SYNC_DISCONNECT_CHECK_INTERVAL_SECS env var - Update TestRelay with fast test settings: startup_delay=0, jitter=0, disconnect_check_interval=1s - Add debug output to metrics tests for investigation Note: Tests may still fail due to 5-second base backoff in health tracker. A follow-up task will add NGIT_SYNC_BASE_BACKOFF_SECS config parameter to allow faster test cycles. Related: metrics-wiring-plan.md Tasks 1 & 2
2025-12-05rename sunc_bootstrap_relay_urlDanConwayDev
2025-12-05fix basic sync testsDanConwayDev
2025-12-04feat(sync): Phase 5 - negentropy catchup (NIP-77)DanConwayDev
- Add NegentropyService for set reconciliation - Implement startup catchup with warm-up delay - Implement reconnect catchup (last 3 days) - Add daily catchup schedule with stagger
2025-12-04feat(sync): Phase 3 - resilience and health trackingDanConwayDev
- Add RelayHealthTracker with DashMap - Implement exponential backoff (5s -> 1h max) - Handle dead relays (24h failures -> daily retry) - Add startup jitter to prevent thundering herd - Add NGIT_SYNC_MAX_BACKOFF_SECS config
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-04add prometheus metricsDanConwayDev
2025-12-03improved settings cli flags > env vars > defaultsDanConwayDev
2025-12-01fix cargo clippy and fmt warningsDanConwayDev
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-19fix some clippy fmt warningsDanConwayDev
2025-11-04feat: implement NIP-01 compliant Nostr relayDanConwayDev
- WebSocket-based relay using tokio-tungstenite - Full NIP-01 protocol support (EVENT, REQ, CLOSE) - Event validation (signature and ID) - In-memory event storage - Filter support (IDs, authors, kinds, since/until) - Configuration via environment variables - Nix flake for reproducible builds - Test automation script All 6 NIP-01 smoke tests passing (100%)