summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* feat: add Prometheus metrics and YAML config file supportbndw3 days8-1/+1720
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## 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 days7-0/+1364
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 days29-62/+54
| | | | | | 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 indexbndw4 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).
* feat: auto-detect TLS in testclientbndw4 days1-1/+16
| | | | | | | | | | | Add automatic TLS detection for testclient: - Use TLS for port 443 - Use TLS for non-localhost addresses - Use insecure for localhost/127.0.0.1 (development) Now works with both: ./bin/testclient # local ./bin/testclient -addr nostr-grpc.x.bdw.to:443 # production
* fix: use port 443 for gRPC when behind reverse proxybndw4 days1-2/+2
| | | | | | When using --public-url, the gRPC endpoint is accessed via the reverse proxy on standard HTTPS port 443, not the internal port 50051. Update display to show correct public-facing port.
* fix: remove duplicate protocol prefix in WebSocket URLbndw4 days2-3/+3
| | | | | | | | | | | 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
* feat: add --public-url flag for reverse proxy deploymentsbndw4 days1-4/+19
| | | | | | | | | | | | | | | | Add flag to specify public-facing domain when relay is behind a reverse proxy that terminates TLS. Usage: ./bin/relay --public-url nostr-grpc.x.bdw.to When set, the index page displays: - gRPC: nostr-grpc.x.bdw.to:50051 - Connect: https://nostr-grpc.x.bdw.to - WebSocket: wss://nostr-grpc.x.bdw.to When not set, falls back to local addresses (:50051, :8080) for development environments.
* redesign: early web minimalism + cypherpunkbndw4 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 aestheticbndw4 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 viewingbndw4 days3-4/+219
| | | | | | | | | | 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 deletebndw4 days5-0/+320
| | | | | | | | | | | 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)bndw4 days7-289/+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)bndw4 days7-2/+342
| | | | | | | | | | | | | | | | | | | | | | 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 days7-10/+575
| | | | | | | | | | | | | | | | | | | | 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 days5-15/+376
| | | | | | | | | | | | | | | | | | | 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!
* docs: update README - Subscribe is now implementedbndw4 days1-5/+6
|
* 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: testclient can accept JSON events from stdinbndw4 days2-18/+57
| | | | | | | | Usage: - Standalone: ./bin/testclient (generates event) - With nak: nak event "hello" | ./bin/testclient Compatible with nak CLI for easy event generation
* docs: add README with quick start guidebndw4 days1-0/+99
|
* feat: add relay server and test clientbndw4 days4-0/+151
| | | | | | | | | | | | | | | | | Server (cmd/relay): - gRPC server on :50051 (configurable) - SQLite database (default: relay.db) - Graceful shutdown on SIGTERM/SIGINT Test client (cmd/testclient): - Generates key - Publishes event - Queries events back Build: - make build (relay) - make build-client (test client) - make build-all (both)
* 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 days6-0/+762
| | | | | | | | | | | | | | | 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
* docs: add design documentation and examplesbndw4 days4-0/+1165
|
* chore: add generated gRPC code (protoc-gen-go v1.36.11)bndw4 days2-0/+1967
|
* feat: add Protocol Buffer definitions and build toolingbndw4 days4-0/+246
|
* feat: add Nostr protocol implementation (internal/nostr, internal/websocket)bndw4 days18-0/+3848
|
* chore: initialize Go module northwest.io/nostr-grpcbndw4 days3-0/+109