summaryrefslogtreecommitdiffstats
path: root/internal
Commit message (Collapse)AuthorAgeFilesLines
* refactor: remove frivolous comments from auth validation/credentialsbndw3 days26-3637/+34
| | | | Also removed internal/nostr package - now using northwest.io/nostr library.
* index updatebndw3 days1-1/+1
|
* index updatebndw3 days1-4/+4
|
* Update index pagebndw3 days1-9/+1
|
* refactor: remove frivolous comments from auth and configbndw3 days2-115/+16
| | | | | Removed ~100 lines of obvious comments that just repeated what the code does. Kept only comments that add clarity or valuable detail.
* refactor: restructure auth config for better UXbndw3 days6-151/+242
| | | | | | | | | | | | | | | | | | | | | | | | | | | Changed from flat structure to hierarchical read/write config: Before: auth: enabled: bool required: bool allowed_npubs_read: [] allowed_npubs_write: [] After: auth: read: enabled: bool allowed_npubs: [] write: enabled: bool allowed_npubs: [] Three states per operation: - enabled=false: no auth, allow all - enabled=true, allowed_npubs=[]: auth required, any valid signature - enabled=true, allowed_npubs=[...]: auth required, whitelist only Much clearer semantics and easier to reason about.
* refactor: simplify isWriteMethod to only check actual API methodsbndw3 days2-33/+7
| | | | | Replace pattern-matching with explicit checks for PublishEvent/PublishBatch. API is small and well-defined - no need for extensible pattern matching.
* feat: add separate read/write allowlists for granular access controlbndw3 days6-67/+263
| | | | | | | | | | | | | | - Split allowed_npubs into allowed_npubs_read and allowed_npubs_write - Write operations: Publish, Delete, Create, Update, Insert, Remove, Set, Put - Read operations: everything else (Query, Subscribe, Get, List, etc.) - Auth interceptor checks appropriate list based on method type - Enables common patterns: - Public relay: only some can write, everyone can read - Private relay: restricted read and write - Open relay: everyone can read and write - Updated config, docs, and comprehensive tests Use cases: "only some can write, everyone can read"
* feat: rename allowed_pubkeys to allowed_npubs with normalizationbndw3 days5-14/+159
| | | | | | | | | | | - Config now accepts npub format only (human-readable) - Automatically converts npubs to hex pubkeys at load time - Updated InterceptorOptions.AllowedPubkeys -> AllowedNpubs - Added validation to reject hex format in config (npub only) - Updated documentation to clarify npub-only config - Added comprehensive tests for npub normalization Config is for humans (npub), internal code uses hex pubkeys.
* fix: optimize SQLite connection pooling for single-writer architecturebndw3 days4-22/+14
| | | | | | | | | | | | | | | | | | | | | Remove misleading max_connections config option and properly configure SQLite connection pooling in the storage layer. Changes: - Set MaxOpenConns(1) for optimal SQLite performance - Set MaxIdleConns(1) to keep connection alive - Set ConnMaxLifetime(0) to never close connection - Remove max_connections and max_lifetime from DatabaseConfig - Update docs to clarify SQLite's single-writer architecture Rationale: SQLite is an embedded database with a single-writer lock. Multiple connections cause lock contention and reduce performance. WAL mode allows concurrent reads from the same connection, making connection pooling unnecessary and counterproductive. This change makes the configuration clearer and ensures optimal SQLite performance by using a single long-lived connection.
* feat: add Prometheus metrics and YAML config file supportbndw3 days6-0/+1677
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## Metrics Package Comprehensive Prometheus metrics for production observability: Metrics tracked: - Request rate, latency, size per method (histograms) - Active connections and subscriptions (gauges) - Auth success/failure rates (counters) - Rate limit hits (counters) - Storage stats (event count, DB size) - Standard Go runtime metrics Features: - Automatic gRPC instrumentation via interceptors - Low overhead (~300-500ns per request) - Standard Prometheus client - HTTP /metrics endpoint - Grafana dashboard examples ## Config Package YAML configuration file support with environment overrides: Configuration sections: - Server (addresses, timeouts, public URL) - Database (path, connections, lifetime) - Auth (enabled, required, timestamp window, allowed pubkeys) - Rate limiting (per-method and per-user limits) - Metrics (endpoint, namespace) - Logging (level, format, output) - Storage (compaction, retention) Features: - YAML file loading - Environment variable overrides (MUXSTR_<SECTION>_<KEY>) - Sensible defaults - Validation on load - Duration and list parsing - Save/export configuration Both packages include comprehensive README with examples, best practices, and usage patterns. Config tests verify YAML parsing, env overrides, validation, and round-trip serialization.
* feat: implement per-user rate limiting with token bucket algorithmbndw3 days5-0/+1361
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add comprehensive rate limiting package that works seamlessly with NIP-98 authentication. Features: - Token bucket algorithm (allows bursts, smooth average rate) - Per-pubkey limits for authenticated users - Per-IP limits for unauthenticated users (fallback) - Method-specific overrides (e.g., stricter for PublishEvent) - Per-user custom limits (VIP/admin tiers) - Standard gRPC interceptors (chain after auth) - Automatic cleanup of idle limiters - Statistics tracking (allowed/denied/denial rate) Configuration options: - Default rate limits and burst sizes - Method-specific overrides - User-specific overrides (with method overrides) - Skip methods (health checks, public endpoints) - Skip users (admins, monitoring) - Configurable cleanup intervals Performance: - In-memory (200 bytes per user) - O(1) lookups with sync.RWMutex - ~85ns per rate limit check - Periodic cleanup to free memory Returns gRPC ResourceExhausted (HTTP 429) when limits exceeded. Includes comprehensive tests, benchmarks, and detailed README with usage examples, configuration reference, and security considerations.
* docs: clarify NIP-98 relationship to NIP-42 and write access controlbndw3 days1-4/+60
| | | | | | | | | Explain that the gRPC NIP-98 implementation is effectively NIP-42 for reads (same pattern: authenticate once, stream many events) and adds standardized relay access control for writes (beyond event.sig). Add comparison table showing functional equivalence for streaming reads and the additional benefits for write access control.
* feat: implement NIP-98 HTTP auth for gRPCbndw3 days5-0/+951
| | | | | | | | | | | | | | | | | | | | | | | | | Add comprehensive NIP-98 authentication support following the standard gRPC credentials.PerRPCCredentials pattern. Client-side: - NostrCredentials implements PerRPCCredentials interface - Automatically signs each request with kind 27235 event - Drop-in replacement for OAuth2/JWT in gRPC clients Server-side: - Unary and stream interceptors for validation - Extracts and validates NIP-98 events from Authorization headers - Configurable options (timestamp window, whitelists, skip methods) - Adds authenticated pubkey to request context Security features: - Replay protection via timestamp validation - Optional payload hash verification - Signature verification using schnorr - TLS requirement option Includes comprehensive test coverage and detailed README with usage examples and security considerations.
* refactor: simplify footer text on index pagebndw3 days1-1/+1
|
* refactor: remove PGP signature block from index pagebndw3 days1-8/+0
|
* feat: add muxstr SVG logo to index pagebndw3 days1-11/+16
| | | | | Replace ASCII art banner with SVG logo featuring the muxstr branding. Update page title and background color to match brand identity.
* refactor: rename project from nostr-grpc to muxstrbndw3 days19-33/+33
| | | | | | Update module path from northwest.io/nostr-grpc to northwest.io/muxstr. This includes updating all Go imports, protobuf definitions, generated files, and documentation.
* fix: allow WebSocket upgrades to bypass HTML indexbndw3 days1-2/+3
| | | | | | | | | | WebSocket connections start as GET requests with 'Upgrade: websocket' header. The handler was serving HTML for ALL GET requests, preventing WebSocket upgrades from ever happening. Fix by checking for Upgrade header and only serving HTML/NIP-11 for non-WebSocket GET requests. Now WebSocket connections return status 101 (Switching Protocols) instead of 200 (OK).
* fix: remove duplicate protocol prefix in WebSocket URLbndw3 days1-1/+1
| | | | | | | | | | | The template was hardcoding 'ws://' prefix, but when using --public-url we were already passing 'wss://'. This caused the URL to display as 'ws://wss://domain/'. Fix by: - Removing 'ws://' prefix from template - Always including protocol in the variable (ws:// or wss://) - Also add http:// prefix for local development consistency
* redesign: early web minimalism + cypherpunkbndw3 days1-408/+115
| | | | | | | | | | | | | | | | | | | | | | | | | | | Complete aesthetic reversal - from cyber-brutalist to minimal: AESTHETIC: 1995 web document meets cypherpunks mailing list - Courier New system font (no web fonts) - Black on white for readability - Semantic HTML with minimal CSS - PGP signature blocks (cypherpunk heritage) - Classic underlined blue links - Horizontal rules for section breaks - Looks like a .txt file rendered as HTML PHILOSOPHY: Throwback to when the web was just documents. No animations, no grids, no gradients. Just semantic HTML, monospace type, and information. Fast loading, accessible, timeless. CYPHERPUNK TOUCHES: - PGP signature blocks - Hash fingerprints - Technical language - Cryptographic references - Feels like reading crypto mailing list archives Zero frameworks, zero build tools, maximum signal.
* redesign: cyber-brutalist terminal aestheticbndw3 days1-101/+367
| | | | | | | | | | | | | | | | | | | | | | | | | | Complete visual overhaul with bold conceptual direction: AESTHETIC: Cyber-brutalist terminal interface - JetBrains Mono monospace throughout - Deep black (#0a0e14) with cyan/green accents - ASCII art Nostr logo with glitch animation - Animated grid background (scrolling terminal feel) - Terminal-style status bar with pulse indicators - Protocol cards with scanning line effects - Information-dense but organized layout MOTION & EFFECTS: - Glitching ASCII logo animation - Scanning line on protocol cards - Pulsing status indicators - Animated grid background - Staggered fade-in on page load - Hover effects with glow DIFFERENTIATION: Feels like SSH into a relay node. Unapologetically technical, embracing Nostr's decentralized, cypherpunk ethos. Zero generic design patterns - full commitment to terminal aesthetic.
* feat: add HTML index page for browser viewingbndw3 days2-4/+218
| | | | | | | | | | Add a beautiful HTML landing page when visiting relay in browser: - Shows all three protocol endpoints (gRPC, Connect, WebSocket) - Lists supported NIPs (01, 09, 11) - Displays relay features and info - Responsive design with gradient styling - Serves on GET requests (regular Accept header) - NIP-11 still served for Accept: application/nostr+json
* feat: implement NIP-09 with hard deletebndw3 days4-0/+319
| | | | | | | | | | | Implement event deletion (NIP-09) using hard delete approach: - Kind 5 events trigger deletion but are not stored themselves - ProcessDeletion hard deletes referenced events (DELETE FROM events) - Only authors can delete their own events (pubkey verification) - Support multiple event IDs in single deletion request - No deletions table needed (simpler schema) - Added 4 deletion tests covering various scenarios - All 45 tests passing
* refactor: simplify deletion handling (remove NIP-09 processing)bndw3 days6-288/+3
| | | | | | | | | | Remove deletion processing logic in favor of simpler approach: - Remove deletions table from schema - Delete deletions.go and deletions_test.go - Remove ProcessDeletion from EventStore interface - Kind 5 events now stored like any other event (no special handling) - Update storage test to expect 2 tables instead of 3 - All 41 tests passing
* feat: implement NIP-09 (deletions) and NIP-11 (relay info)bndw3 days6-2/+340
| | | | | | | | | | | | | | | | | | | | | | NIP-11 (Relay Information Document): - Serves relay metadata at GET / with Accept: application/nostr+json - Returns name, description, supported NIPs, limitations - CORS headers for browser compatibility NIP-09 (Event Deletion): - Kind 5 events delete events referenced in 'e' tags - Only authors can delete their own events - Soft delete (marks deleted=1) - Records deletion in deletions table - Works across all protocols (gRPC, Connect, WebSocket) Fixed deletions schema: - deleted_event_id as PRIMARY KEY (not deletion_event_id) - Allows one deletion event to delete multiple events 3 new tests, 44 total tests passing Supported NIPs now: 1, 9, 11
* feat: add Connect (gRPC over HTTP/JSON) supportbndw4 days1-0/+101
| | | | | | | | | | | | | | | | | | | | Connect integration: - Buf Connect codegen added to buf.gen.yaml - Connect handler wraps gRPC server - Serves on same port as WebSocket (:8080) - HTTP/2 with h2c for cleartext HTTP/2 Now serving THREE protocols: 1. gRPC (native) on :50051 - binary, high performance 2. Connect on :8080/nostr.v1.NostrRelay/* - HTTP/JSON, browser compatible 3. WebSocket on :8080/ - Nostr standard protocol All three protocols share: - Same storage layer - Same subscription manager - Same validation logic Browser-friendly! Call gRPC methods with fetch() or curl.
* feat: add WebSocket server with full NIP-01 supportbndw4 days3-0/+326
| | | | | | | | | | | | | | | | | | | WebSocket handler: - NIP-01 protocol (EVENT, REQ, CLOSE, OK, EOSE, NOTICE) - JSON envelope parsing - Shares subscription manager with gRPC (unified event fan-out) - Standard Nostr client compatibility Relay now serves dual protocols: - gRPC on :50051 (binary, high performance) - WebSocket on :8080 (JSON, Nostr standard) Both protocols share: - Same storage layer - Same subscription manager - Same validation logic Compatible with all Nostr clients!
* feat: implement Subscribe with real-time event streamingbndw4 days3-3/+488
| | | | | | | | | | | | | | | | | | | | Subscription manager: - Track active subscriptions across connections - Filter matching with full NIP-01 support - Event fan-out to matching subscribers Subscribe RPC: - Query stored events (past) - Stream them to client - Keep stream open for new events (real-time) - Auto-generate subscription ID if not provided PublishEvent now: - Stores event - Notifies all matching active subscriptions - Streams to gRPC clients in real-time 4 new tests, all 41 tests passing
* feat: add gRPC handler with event validation and publishingbndw4 days4-0/+592
| | | | | | | | | | | Handler implementation: - EventStore interface (consumer-side) - Server with PublishEvent, QueryEvents, CountEvents, PublishBatch - pb.Event <-> nostr.Event conversion helpers - Signature and ID validation using existing nostr package - Canonical JSON generation for storage 9 tests passing
* feat: add query layer with Nostr filter to SQL conversionbndw4 days2-0/+622
| | | | | | | | | | | | | Query implementation: - QueryEvents method with filter support - Full NIP-01 filter support (ids, authors, kinds, tags, since, until, limit) - ID and pubkey prefix matching - Tag filtering using SQLite JSON functions - Multiple filter UNION support - DESC ordering by created_at - Optional canonical JSON inclusion 23 tests passing, 1322 total lines
* feat: add SQLite storage layer with binary-first event persistencebndw4 days4-0/+700
| | | | | | | | | | | | | | | Storage implementation: - Concrete type with constructor (consumer-side interfaces) - Event storage: protobuf + zstd-compressed canonical JSON - Schema: events, deletions, replaceable_events, auth_challenges, rate_limits - WAL mode, STRICT typing, optimized indexes - Methods: StoreEvent, GetEvent, GetEventWithCanonical, DeleteEvent Dependencies: - modernc.org/sqlite v1.45.0 (pure Go SQLite driver) - github.com/klauspost/compress v1.18.4 (zstd compression) 366 lines, 10 tests passing
* feat: add Nostr protocol implementation (internal/nostr, internal/websocket)bndw4 days18-0/+3848