From 35b1461ff6fc4e24a2224424246728a0f377ccb6 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 23 Jan 2026 06:58:14 -0400 Subject: [PATCH] v1.1.0 - Documentation restructure: New README.md and comprehensive API.md --- API.md | 995 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 619 ++++++++++++--------------------- src/main.h | 6 +- 3 files changed, 1213 insertions(+), 407 deletions(-) create mode 100644 API.md diff --git a/API.md b/API.md new file mode 100644 index 0000000..2c57c52 --- /dev/null +++ b/API.md @@ -0,0 +1,995 @@ +# C-Relay API Documentation + +Complete API reference for the C-Relay event-based administration system and advanced features. + +## Table of Contents + +- [Overview](#overview) +- [Authentication](#authentication) +- [Admin API](#admin-api) + - [Event Structure](#event-structure) + - [Configuration Management](#configuration-management) + - [Auth Rules Management](#auth-rules-management) + - [System Commands](#system-commands) + - [Database Queries](#database-queries) +- [Configuration Reference](#configuration-reference) +- [Real-time Monitoring](#real-time-monitoring) +- [Direct Message Admin](#direct-message-admin) +- [Response Formats](#response-formats) +- [Error Handling](#error-handling) +- [Examples](#examples) + +## Overview + +C-Relay uses an innovative **event-based administration system** where all configuration and management commands are sent as cryptographically signed Nostr events. This provides: + +- **Cryptographic security**: All commands must be signed with the admin private key +- **Audit trail**: Complete history of all administrative actions +- **Real-time updates**: Configuration changes applied instantly +- **Standard protocol**: Uses Nostr events, no custom protocols +- **NIP-44 encryption**: All admin commands and responses are encrypted + +### Key Concepts + +1. **Admin Keypair**: Generated on first startup, used to sign all admin commands +2. **Relay Keypair**: The relay's identity on the Nostr network +3. **Admin Events**: Kind 23456 events with NIP-44 encrypted commands +4. **Response Events**: Kind 23457 events with NIP-44 encrypted responses +5. **Event-Based Config**: All settings stored as events in the database + +## Authentication + +### Admin Private Key + +The admin private key is displayed **only once** during first startup: + +``` +======================================== +IMPORTANT: SAVE THIS ADMIN PRIVATE KEY +======================================== +Admin Private Key: nsec1abc123... +Admin Public Key: npub1def456... +======================================== +``` + +**Critical**: Save this key immediately. It cannot be recovered and is required for all administrative operations. + +### Secure Storage + +Store the admin private key securely: + +```bash +# Environment variable +export C_RELAY_ADMIN_KEY="nsec1abc123..." + +# Secure file +echo "nsec1abc123..." > ~/.c-relay-admin +chmod 600 ~/.c-relay-admin + +# Password manager (recommended) +# Store in 1Password, Bitwarden, etc. +``` + +### Key Loss Recovery + +If you lose the admin private key: + +1. Stop the relay +2. Delete the database file (`*.db`) +3. Restart the relay (generates new keys) +4. **Note**: This deletes all events and configuration + +## Admin API + +### Event Structure + +All admin commands use the same event structure with NIP-44 encrypted content. + +#### Admin Command Event (Kind 23456) + +```json +{ + "id": "computed_event_id", + "pubkey": "admin_public_key_hex", + "created_at": 1234567890, + "kind": 23456, + "content": "AqHBUgcM7dXFYLQuDVzGwMST1G8jtWYyVvYxXhVGEu4nAb4LVw...", + "tags": [ + ["p", "relay_public_key_hex"] + ], + "sig": "event_signature" +} +``` + +**Fields**: +- `kind`: Must be `23456` for admin commands +- `pubkey`: Admin public key (hex format) +- `content`: NIP-44 encrypted JSON array containing the command +- `tags`: Must include `["p", "relay_pubkey"]` tag +- `sig`: Valid signature from admin private key + +#### Encrypted Content Format + +The `content` field contains a NIP-44 encrypted JSON array: + +```json +["command_name", "param1", "param2", ...] +``` + +Examples: +```json +["config_query", "all"] +["config_update", [{"key": "relay_name", "value": "My Relay", ...}]] +["blacklist", "pubkey", "abc123..."] +["auth_query", "all"] +["sql_query", "SELECT * FROM events LIMIT 10"] +``` + +#### Admin Response Event (Kind 23457) + +```json +{ + "id": "response_event_id", + "pubkey": "relay_public_key_hex", + "created_at": 1234567890, + "kind": 23457, + "content": "BpKCVhfN8eYtRmPqSvWxZnMkL2gHjUiOp3rTyEwQaS5dFg...", + "tags": [ + ["p", "admin_public_key_hex"], + ["e", "request_event_id"] + ], + "sig": "response_signature" +} +``` + +**Fields**: +- `kind`: Always `23457` for admin responses +- `pubkey`: Relay public key (hex format) +- `content`: NIP-44 encrypted JSON response object +- `tags`: Includes `["p", "admin_pubkey"]` and optionally `["e", "request_id"]` +- `sig`: Valid signature from relay private key + +### Configuration Management + +#### Query All Configuration + +**Command**: +```json +["config_query", "all"] +``` + +**Response** (decrypted): +```json +{ + "query_type": "config_all", + "total_results": 27, + "timestamp": 1234567890, + "data": [ + { + "key": "relay_name", + "value": "C-Relay", + "data_type": "string", + "category": "relay", + "description": "Relay name displayed in NIP-11" + }, + { + "key": "auth_enabled", + "value": "false", + "data_type": "boolean", + "category": "auth", + "description": "Enable whitelist/blacklist authentication" + } + ] +} +``` + +#### Update Configuration + +**Command**: +```json +["config_update", [ + { + "key": "relay_name", + "value": "My Awesome Relay", + "data_type": "string", + "category": "relay" + }, + { + "key": "max_subscriptions_per_client", + "value": "50", + "data_type": "integer", + "category": "limits" + } +]] +``` + +**Response** (decrypted): +```json +{ + "query_type": "config_update", + "status": "success", + "total_results": 2, + "timestamp": 1234567890, + "data": [ + { + "key": "relay_name", + "value": "My Awesome Relay", + "status": "updated" + }, + { + "key": "max_subscriptions_per_client", + "value": "50", + "status": "updated" + } + ] +} +``` + +### Auth Rules Management + +#### Add Blacklist Rule + +**Command**: +```json +["blacklist", "pubkey", "abc123def456..."] +``` + +**Response** (decrypted): +```json +{ + "query_type": "auth_add", + "status": "success", + "message": "Blacklist rule added successfully", + "timestamp": 1234567890 +} +``` + +#### Add Whitelist Rule + +**Command**: +```json +["whitelist", "pubkey", "def456abc123..."] +``` + +#### Delete Auth Rule + +**Command**: +```json +["delete_auth_rule", "blacklist", "pubkey", "abc123def456..."] +``` + +**Response** (decrypted): +```json +{ + "query_type": "auth_delete", + "status": "success", + "message": "Auth rule deleted successfully", + "timestamp": 1234567890 +} +``` + +#### Query All Auth Rules + +**Command**: +```json +["auth_query", "all"] +``` + +**Response** (decrypted): +```json +{ + "query_type": "auth_rules_all", + "total_results": 5, + "timestamp": 1234567890, + "data": [ + { + "rule_type": "blacklist", + "pattern_type": "pubkey", + "pattern_value": "abc123...", + "action": "deny" + }, + { + "rule_type": "whitelist", + "pattern_type": "pubkey", + "pattern_value": "def456...", + "action": "allow" + } + ] +} +``` + +#### Query Specific Rule Type + +**Command**: +```json +["auth_query", "whitelist"] +``` + +#### Query Specific Pattern + +**Command**: +```json +["auth_query", "pattern", "abc123..."] +``` + +### System Commands + +#### System Status + +**Command**: +```json +["system_command", "system_status"] +``` + +**Response** (decrypted): +```json +{ + "query_type": "system_status", + "timestamp": 1234567890, + "status": "running", + "uptime_seconds": 86400, + "version": "0.6.0", + "relay_pubkey": "relay_public_key_hex", + "database_size_bytes": 10485760, + "total_events": 15432, + "active_connections": 42, + "active_subscriptions": 156 +} +``` + +#### Clear All Auth Rules + +**Command**: +```json +["system_command", "clear_all_auth_rules"] +``` + +**Response** (decrypted): +```json +{ + "query_type": "system_command", + "status": "success", + "message": "All auth rules cleared", + "timestamp": 1234567890 +} +``` + +#### Database Statistics + +**Command**: +```json +["stats_query"] +``` + +**Response** (decrypted): +```json +{ + "query_type": "stats_query", + "timestamp": 1234567890, + "database_size_bytes": 10485760, + "total_events": 15432, + "database_created_at": 1234567800, + "latest_event_at": 1234567890, + "event_kinds": [ + { + "kind": 1, + "count": 12000, + "percentage": 77.8 + }, + { + "kind": 0, + "count": 2500, + "percentage": 16.2 + } + ], + "time_stats": { + "total": 15432, + "last_24h": 234, + "last_7d": 1456, + "last_30d": 5432 + }, + "top_pubkeys": [ + { + "pubkey": "abc123...", + "event_count": 1234, + "percentage": 8.0 + } + ] +} +``` + +### Database Queries + +#### SQL Query Command + +Execute read-only SQL queries against the relay database. + +**Command**: +```json +["sql_query", "SELECT * FROM events ORDER BY created_at DESC LIMIT 10"] +``` + +**Response** (decrypted): +```json +{ + "query_type": "sql_query", + "request_id": "request_event_id", + "timestamp": 1234567890, + "query": "SELECT * FROM events ORDER BY created_at DESC LIMIT 10", + "execution_time_ms": 45, + "row_count": 10, + "columns": ["id", "pubkey", "created_at", "kind", "content", "tags", "sig"], + "rows": [ + ["abc123...", "def456...", 1234567890, 1, "Hello world", "[]", "sig123..."], + ["ghi789...", "jkl012...", 1234567880, 0, "{\"name\":\"Alice\"}", "[]", "sig456..."] + ] +} +``` + +#### Security Features + +- **Read-only**: Only SELECT statements allowed +- **Query timeout**: 5 seconds maximum +- **Result limit**: 1000 rows maximum +- **Logging**: All queries logged with execution time +- **Validation**: SQL injection protection + +#### Available Tables and Views + +**Core Tables**: +- `events` - All Nostr events +- `config` - Configuration parameters +- `auth_rules` - Authentication rules +- `subscription_events` - Subscription lifecycle log +- `event_broadcasts` - Event broadcast log + +**Views**: +- `recent_events` - Last 1000 events +- `event_stats` - Event statistics by type +- `subscription_analytics` - Subscription metrics +- `active_subscriptions_log` - Currently active subscriptions +- `event_kinds_view` - Event distribution by kind +- `top_pubkeys_view` - Top 10 pubkeys by event count +- `time_stats_view` - Time-based statistics + +#### Example Queries + +**Recent events**: +```sql +SELECT id, pubkey, created_at, kind +FROM events +ORDER BY created_at DESC +LIMIT 20 +``` + +**Event distribution**: +```sql +SELECT * FROM event_kinds_view +ORDER BY count DESC +``` + +**Active subscriptions**: +```sql +SELECT * FROM active_subscriptions_log +ORDER BY created_at DESC +``` + +**Database statistics**: +```sql +SELECT + (SELECT COUNT(*) FROM events) as total_events, + (SELECT COUNT(*) FROM subscription_events) as total_subscriptions, + (SELECT COUNT(DISTINCT pubkey) FROM events) as unique_pubkeys +``` + +**Events by specific pubkey**: +```sql +SELECT id, created_at, kind, content +FROM events +WHERE pubkey = 'abc123...' +ORDER BY created_at DESC +LIMIT 50 +``` + +**Events in time range**: +```sql +SELECT COUNT(*) as count, kind +FROM events +WHERE created_at BETWEEN 1234567000 AND 1234567890 +GROUP BY kind +ORDER BY count DESC +``` + +## Configuration Reference + +### Basic Relay Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `relay_name` | string | "C-Relay" | Relay name (NIP-11) | +| `relay_description` | string | "C Nostr Relay" | Relay description | +| `relay_contact` | string | "" | Admin contact info | +| `relay_software` | string | "c-relay" | Software identifier | +| `relay_version` | string | auto | Software version | +| `supported_nips` | string | "1,9,11,13,15,20,33,40,42,45,50,70" | Supported NIPs | +| `language_tags` | string | "*" | Supported languages | +| `relay_countries` | string | "*" | Supported countries | +| `posting_policy` | string | "" | Posting policy URL | +| `payments_url` | string | "" | Payment URL | + +### Connection & Limits + +| Key | Type | Default | Range | Restart Required | +|-----|------|---------|-------|------------------| +| `max_connections` | integer | 1000 | 1-10000 | Yes | +| `max_subscriptions_per_client` | integer | 25 | 1-100 | No | +| `max_total_subscriptions` | integer | 5000 | 100-50000 | No | +| `max_message_length` | integer | 65536 | 1024-1048576 | No | +| `max_event_tags` | integer | 2000 | 10-10000 | No | +| `max_content_length` | integer | 65536 | 1-1048576 | No | + +### Authentication & Access Control + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `auth_enabled` | boolean | false | Enable whitelist/blacklist | +| `nip42_auth_required` | boolean | false | Require NIP-42 auth | +| `nip42_auth_required_kinds` | string | "" | Kinds requiring NIP-42 | +| `nip42_challenge_timeout` | integer | 300 | Challenge timeout (seconds) | + +### Proof of Work (NIP-13) + +| Key | Type | Default | Values | Description | +|-----|------|---------|--------|-------------| +| `pow_min_difficulty` | integer | 0 | 0-40 | Minimum PoW difficulty | +| `pow_mode` | string | "optional" | disabled/optional/required | PoW enforcement mode | + +### Event Expiration (NIP-40) + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `nip40_expiration_enabled` | boolean | true | Enable expiration support | +| `nip40_expiration_strict` | boolean | false | Reject expired events | +| `nip40_expiration_filter` | boolean | true | Filter expired from results | +| `nip40_expiration_grace_period` | integer | 300 | Grace period (seconds) | + +### Monitoring + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `kind_24567_reporting_throttle_sec` | integer | 5 | Monitoring event throttle | + +### Dynamic vs Restart-Required + +**Dynamic (No Restart)**: +- All NIP-11 relay information +- Authentication settings +- Subscription limits +- Event validation limits +- Proof of Work settings +- Expiration settings + +**Restart Required**: +- `max_connections` +- `relay_port` +- Database settings + +## Real-time Monitoring + +C-Relay provides subscription-based real-time monitoring using ephemeral events (kind 24567). + +### Activation + +Subscribe to kind 24567 events to activate monitoring: + +```json +["REQ", "monitoring-sub", {"kinds": [24567]}] +``` + +### Monitoring Event Types + +Subscribe to specific monitoring types using d-tag filters: + +```json +["REQ", "event-kinds", {"kinds": [24567], "#d": ["event_kinds"]}] +["REQ", "time-stats", {"kinds": [24567], "#d": ["time_stats"]}] +["REQ", "top-pubkeys", {"kinds": [24567], "#d": ["top_pubkeys"]}] +["REQ", "cpu-metrics", {"kinds": [24567], "#d": ["cpu_metrics"]}] +``` + +### Event Structure + +```json +{ + "kind": 24567, + "pubkey": "relay_pubkey", + "created_at": 1234567890, + "content": "{\"data_type\":\"event_kinds\",\"timestamp\":1234567890,...}", + "tags": [ + ["d", "event_kinds"] + ] +} +``` + +### Monitoring Types + +#### Event Distribution (`event_kinds`) + +```json +{ + "data_type": "event_kinds", + "timestamp": 1234567890, + "total_events": 15432, + "kinds": [ + {"kind": 1, "count": 12000, "percentage": 77.8}, + {"kind": 0, "count": 2500, "percentage": 16.2} + ] +} +``` + +#### Time Statistics (`time_stats`) + +```json +{ + "data_type": "time_stats", + "timestamp": 1234567890, + "total_events": 15432, + "last_24h": 234, + "last_7d": 1456, + "last_30d": 5432 +} +``` + +#### Top Publishers (`top_pubkeys`) + +```json +{ + "data_type": "top_pubkeys", + "timestamp": 1234567890, + "top_pubkeys": [ + {"pubkey": "abc123...", "count": 1234, "percentage": 8.0}, + {"pubkey": "def456...", "count": 987, "percentage": 6.4} + ] +} +``` + +#### CPU Metrics (`cpu_metrics`) + +```json +{ + "data_type": "cpu_metrics", + "timestamp": 1234567890, + "cpu_percent": 12.5, + "memory_mb": 45.2, + "uptime_seconds": 86400 +} +``` + +#### Active Subscriptions (`active_subscriptions`) - Admin Only + +```json +{ + "data_type": "active_subscriptions", + "timestamp": 1234567890, + "total_subscriptions": 156, + "subscriptions_by_client": [ + {"client_id": "client1", "count": 12}, + {"client_id": "client2", "count": 8} + ] +} +``` + +### Configuration + +Control monitoring frequency: + +```json +["config_update", [{ + "key": "kind_24567_reporting_throttle_sec", + "value": "10", + "data_type": "integer", + "category": "monitoring" +}]] +``` + +### Performance + +- Events are ephemeral (not stored) +- Automatic activation/deactivation based on subscriptions +- Throttling prevents excessive event generation +- Minimal overhead when no clients monitoring + +## Direct Message Admin + +Control your relay by sending direct messages from any Nostr client. + +### Setup + +1. The relay has its own keypair (shown on startup) +2. The relay knows the admin public key +3. Send NIP-17 direct messages to the relay + +### Available Commands + +Send a DM containing any of these keywords: + +| Command | Aliases | Response | +|---------|---------|----------| +| Statistics | stats, statistics | Database statistics | +| Configuration | config, configuration | Current configuration | + +### Example + +Using any Nostr client that supports NIP-17: + +1. Find the relay's public key (shown on startup) +2. Send a DM: "stats" +3. Receive a DM with current relay statistics + +### Response Format + +The relay responds with a NIP-17 DM containing: + +**Stats Response**: +``` +Relay Statistics +================ +Total Events: 15,432 +Database Size: 10.5 MB +Active Connections: 42 +Active Subscriptions: 156 +Uptime: 1 day, 2 hours +``` + +**Config Response**: +``` +Relay Configuration +=================== +Name: My Awesome Relay +Description: Community relay +Max Subscriptions: 25 +Auth Enabled: false +PoW Difficulty: 0 +``` + +## Response Formats + +### Success Response + +```json +{ + "query_type": "command_name", + "status": "success", + "message": "Operation completed successfully", + "timestamp": 1234567890, + "data": [...] +} +``` + +### Error Response + +```json +{ + "query_type": "command_name", + "status": "error", + "error": "Error description", + "timestamp": 1234567890 +} +``` + +### Query Response + +```json +{ + "query_type": "query_name", + "total_results": 10, + "timestamp": 1234567890, + "data": [...] +} +``` + +## Error Handling + +### Common Errors + +| Error | Cause | Solution | +|-------|-------|----------| +| `invalid_signature` | Event signature invalid | Check admin private key | +| `unauthorized` | Wrong admin pubkey | Use correct admin key | +| `invalid_command` | Unknown command | Check command format | +| `validation_failed` | Invalid parameter value | Check parameter ranges | +| `database_error` | Database operation failed | Check database integrity | +| `timeout` | Query took too long | Simplify query or increase timeout | + +### Error Response Example + +```json +{ + "query_type": "config_update", + "status": "error", + "error": "field validation failed: invalid port number '99999' (must be 1-65535)", + "timestamp": 1234567890 +} +``` + +## Examples + +### JavaScript/TypeScript Example + +```javascript +import { SimplePool, nip44, getPublicKey, finalizeEvent } from 'nostr-tools'; + +const adminPrivkey = 'your_admin_privkey_hex'; +const adminPubkey = getPublicKey(adminPrivkey); +const relayPubkey = 'relay_pubkey_hex'; +const relayUrl = 'ws://localhost:8888'; + +// Create admin command +async function sendAdminCommand(command) { + const pool = new SimplePool(); + + // Encrypt command with NIP-44 + const encryptedContent = await nip44.encrypt( + adminPrivkey, + relayPubkey, + JSON.stringify(command) + ); + + // Create event + const event = finalizeEvent({ + kind: 23456, + created_at: Math.floor(Date.now() / 1000), + tags: [['p', relayPubkey]], + content: encryptedContent + }, adminPrivkey); + + // Publish event + await pool.publish([relayUrl], event); + + // Subscribe to response + const sub = pool.sub([relayUrl], [{ + kinds: [23457], + '#p': [adminPubkey], + since: Math.floor(Date.now() / 1000) + }]); + + return new Promise((resolve) => { + sub.on('event', async (event) => { + // Decrypt response + const decrypted = await nip44.decrypt( + adminPrivkey, + relayPubkey, + event.content + ); + resolve(JSON.parse(decrypted)); + sub.unsub(); + }); + }); +} + +// Query configuration +const config = await sendAdminCommand(['config_query', 'all']); +console.log(config); + +// Update configuration +const result = await sendAdminCommand(['config_update', [ + { + key: 'relay_name', + value: 'My Relay', + data_type: 'string', + category: 'relay' + } +]]); +console.log(result); + +// Add blacklist rule +const blacklist = await sendAdminCommand([ + 'blacklist', + 'pubkey', + 'abc123...' +]); +console.log(blacklist); + +// Execute SQL query +const query = await sendAdminCommand([ + 'sql_query', + 'SELECT * FROM events ORDER BY created_at DESC LIMIT 10' +]); +console.log(query); +``` + +### Python Example + +```python +from nostr_sdk import Keys, Client, EventBuilder, Filter, nip44 + +admin_privkey = "your_admin_privkey_hex" +relay_pubkey = "relay_pubkey_hex" +relay_url = "ws://localhost:8888" + +# Initialize +keys = Keys.parse(admin_privkey) +client = Client(keys) +client.add_relay(relay_url) +client.connect() + +# Send admin command +async def send_admin_command(command): + # Encrypt command + encrypted = nip44.encrypt( + keys.secret_key(), + relay_pubkey, + json.dumps(command) + ) + + # Create event + event = EventBuilder.new( + kind=23456, + content=encrypted, + tags=[["p", relay_pubkey]] + ).to_event(keys) + + # Publish + await client.send_event(event) + + # Wait for response + filter = Filter().kind(23457).pubkey(relay_pubkey).since(int(time.time())) + events = await client.get_events_of([filter], timeout=5) + + if events: + # Decrypt response + decrypted = nip44.decrypt( + keys.secret_key(), + relay_pubkey, + events[0].content() + ) + return json.loads(decrypted) + +# Query configuration +config = await send_admin_command(["config_query", "all"]) +print(config) +``` + +### Bash/curl Example + +```bash +#!/bin/bash + +# Note: This is a simplified example. Real implementation requires: +# - NIP-44 encryption +# - Event signing +# - WebSocket connection + +RELAY_URL="ws://localhost:8888" +ADMIN_PRIVKEY="your_admin_privkey" +RELAY_PUBKEY="relay_pubkey" + +# Use nostrtool or similar for proper event creation +nostrtool event \ + --kind 23456 \ + --content "$(echo '["config_query","all"]' | nip44-encrypt)" \ + --tag p "$RELAY_PUBKEY" \ + --private-key "$ADMIN_PRIVKEY" \ + | nostrtool send "$RELAY_URL" +``` + +--- + +## Additional Resources + +- **[Configuration Guide](docs/configuration_guide.md)** - Detailed configuration options +- **[Deployment Guide](docs/deployment_guide.md)** - Production deployment +- **[NIP-42 Authentication](docs/NIP-42_Authentication.md)** - Authentication setup +- **[User Guide](docs/user_guide.md)** - End-user documentation + +## Support + +For API questions or issues: +- Open an issue on GitHub +- Check existing documentation +- Join the Nostr community + +--- + +**API Version**: 0.6.0 +**Last Updated**: 2026-01-23 diff --git a/README.md b/README.md index 5f90809..b76d785 100644 --- a/README.md +++ b/README.md @@ -1,474 +1,285 @@ -# C-Nostr Relay +# C-Relay: High-Performance Nostr Relay -A high-performance Nostr relay implemented in C with SQLite backend, featuring nostr event-based management. +A blazingly fast, production-ready Nostr relay implemented in C with an innovative event-based configuration system. Built for performance, security, and ease of deployment. -## Supported NIPs +## ๐Ÿš€ Why C-Relay? - +### Event-Based Configuration +Unlike traditional relays that require config files, C-Relay uses **cryptographically signed Nostr events** for all configuration. This means: +- **Zero config files** - Everything stored in the database +- **Real-time updates** - Changes applied instantly without restart +- **Cryptographic security** - All changes must be signed by admin +- **Complete audit trail** - Every configuration change is timestamped and signed +- **Version control built-in** - Configuration history is part of the event stream -- [x] NIP-01: Basic protocol flow implementation -- [x] NIP-09: Event deletion -- [x] NIP-11: Relay information document -- [x] NIP-13: Proof of Work -- [x] NIP-15: End of Stored Events Notice -- [x] NIP-20: Command Results -- [x] NIP-33: Parameterized Replaceable Events -- [x] NIP-40: Expiration Timestamp -- [x] NIP-42: Authentication of clients to relays -- [x] NIP-45: Counting results -- [x] NIP-50: Keywords filter -- [x] NIP-70: Protected Events +### Built-in Web Admin Interface +Access a full-featured web dashboard at `http://localhost:8888/api/` with: +- Real-time configuration management +- Database statistics and analytics +- Auth rules management (whitelist/blacklist) +- NIP-42 authentication for secure access +- No external dependencies - all files embedded in the binary -## Quick Start +### Direct Message Admin System +Control your relay by sending direct messages from any Nostr client: +- Send "stats" to get relay statistics +- Send "config" to view current configuration +- Full Nostr citizen with its own keypair +- Works with any NIP-17 compatible client -Get your C-Relay up and running in minutes with a static binary (no dependencies required): +### Performance & Efficiency +- **Written in C** - Maximum performance and minimal resource usage +- **SQLite backend** - Reliable, fast, and self-contained +- **Static binary available** - Single file deployment with zero dependencies +- **Efficient memory management** - Optimized for long-running operation +- **WebSocket native** - Built on libwebsockets for optimal protocol support -### 1. Download Static Binary +## ๐Ÿ“‹ Supported NIPs -Download the latest static release from the [releases page](https://git.laantungir.net/laantungir/c-relay/releases): +C-Relay implements a comprehensive set of Nostr Improvement Proposals: + +- โœ… **NIP-01**: Basic protocol flow implementation +- โœ… **NIP-09**: Event deletion +- โœ… **NIP-11**: Relay information document +- โœ… **NIP-13**: Proof of Work +- โœ… **NIP-15**: End of Stored Events Notice +- โœ… **NIP-20**: Command Results +- โœ… **NIP-33**: Parameterized Replaceable Events +- โœ… **NIP-40**: Expiration Timestamp +- โœ… **NIP-42**: Authentication of clients to relays +- โœ… **NIP-45**: Counting results +- โœ… **NIP-50**: Keywords filter +- โœ… **NIP-70**: Protected Events + +## ๐ŸŽฏ Key Features + +### Security +- **NIP-42 Authentication** - Cryptographic client authentication +- **Proof of Work** - Configurable PoW requirements (NIP-13) +- **Protected Events** - Support for encrypted/protected content (NIP-70) +- **Whitelist/Blacklist** - Flexible access control by pubkey +- **Admin key security** - Private key shown only once, never stored + +### Flexibility +- **Dynamic configuration** - Most settings update without restart +- **Subscription management** - Configurable limits per client and globally +- **Event expiration** - Automatic cleanup of expired events (NIP-40) +- **Parameterized events** - Full support for replaceable events (NIP-33) +- **Keyword search** - Built-in full-text search (NIP-50) + +### Monitoring +- **Real-time statistics** - Live event distribution and metrics +- **Subscription-based monitoring** - Ephemeral events (kind 24567) for dashboards +- **SQL query API** - Direct database queries for advanced analytics +- **Resource tracking** - CPU, memory, and database size monitoring +- **Event broadcast logging** - Complete audit trail of all operations + +### Developer-Friendly +- **Comprehensive test suite** - Automated tests for all NIPs +- **Clear documentation** - Detailed guides for deployment and configuration +- **SystemD integration** - Production-ready service files included +- **Docker support** - Container deployment with Alpine Linux +- **Cross-platform** - Builds on Linux, macOS, and Windows (WSL) + +## ๐Ÿš€ Quick Start + +### Option 1: Static Binary (Recommended) + +Download and run - no dependencies required: ```bash -# Static binary - works on all Linux distributions (no dependencies) +# Download the latest static release wget https://git.laantungir.net/laantungir/c-relay/releases/download/v0.6.0/c-relay-v0.6.0-linux-x86_64-static chmod +x c-relay-v0.6.0-linux-x86_64-static mv c-relay-v0.6.0-linux-x86_64-static c-relay -``` -### 2. Start the Relay - -Simply run the binary - no configuration files needed: - -```bash +# Run the relay ./c-relay ``` -On first startup, you'll see: -- **Admin Private Key**: Save this securely! You'll need it for administration -- **Relay Public Key**: Your relay's identity on the Nostr network -- **Port Information**: Default is 8888, or the next available port +**Important**: On first startup, save the **Admin Private Key** displayed in the console. You'll need it for all administrative operations. -### 3. Access the Web Interface +### Option 2: Build from Source + +```bash +# Install dependencies (Ubuntu/Debian) +sudo apt install -y build-essential git sqlite3 libsqlite3-dev \ + libwebsockets-dev libssl-dev libsecp256k1-dev libcurl4-openssl-dev zlib1g-dev + +# Clone and build +git clone https://github.com/your-org/c-relay.git +cd c-relay +git submodule update --init --recursive +./make_and_restart_relay.sh +``` + +The relay will start on port 8888 (or the next available port). + +## ๐ŸŒ Access the Web Interface + +Once running, open your browser to: -Open your browser and navigate to: ``` http://localhost:8888/api/ ``` The web interface provides: -- Real-time configuration management -- Database statistics dashboard -- Auth rules management -- Secure admin authentication with your Nostr identity +- Configuration management with live updates +- Database statistics and event distribution charts +- Auth rules management (whitelist/blacklist) +- SQL query interface for advanced analytics +- Real-time monitoring dashboard -### 4. Test Your Relay +## ๐Ÿ“ฆ Installation Options + +### Production Deployment (SystemD) -Test basic connectivity: ```bash -# Test WebSocket connection -curl -H "Accept: application/nostr+json" http://localhost:8888 +# Clone repository +git clone https://github.com/your-org/c-relay.git +cd c-relay +git submodule update --init --recursive -# Test with a Nostr client -# Add ws://localhost:8888 to your client's relay list +# Build +make clean && make + +# Install as system service +sudo systemd/install-service.sh + +# Start and enable +sudo systemctl start c-relay +sudo systemctl enable c-relay + +# Capture admin keys from logs +sudo journalctl -u c-relay | grep "Admin Private Key" ``` -### 5. Configure Your Relay (Optional) +### Docker Deployment -Use the web interface or send admin commands to customize: -- Relay name and description -- Authentication rules (whitelist/blacklist) -- Connection limits -- Proof-of-work requirements +```bash +# Build Docker image +docker build -f Dockerfile.alpine-musl -t c-relay . -**That's it!** Your relay is now running with zero configuration required. The event-based configuration system means you can adjust all settings through the web interface or admin API without editing config files. - - -## Web Admin Interface - -C-Relay includes a **built-in web-based administration interface** accessible at `http://localhost:8888/api/`. The interface provides: - -- **Real-time Configuration Management**: View and edit all relay settings through a web UI -- **Database Statistics Dashboard**: Monitor event counts, storage usage, and performance metrics -- **Auth Rules Management**: Configure whitelist/blacklist rules for pubkeys -- **NIP-42 Authentication**: Secure access using your Nostr identity -- **Event-Based Updates**: All changes are applied as cryptographically signed Nostr events - -The web interface serves embedded static files with no external dependencies and includes proper CORS headers for browser compatibility. - - -## Administrator API - -C-Relay uses an innovative **event-based administration system** where all configuration and management commands are sent as signed Nostr events using the admin private key generated during first startup. All admin commands use **NIP-44 encrypted command arrays** for security and compatibility. - -### Authentication - -All admin commands require signing with the admin private key displayed during first-time startup. **Save this key securely** - it cannot be recovered and is needed for all administrative operations. - -### Event Structure - -All admin commands use the same unified event structure with NIP-44 encrypted content: - -**Admin Command Event:** -```json -{ - "id": "event_id", - "pubkey": "admin_public_key", - "created_at": 1234567890, - "kind": 23456, - "content": "AqHBUgcM7dXFYLQuDVzGwMST1G8jtWYyVvYxXhVGEu4nAb4LVw...", - "tags": [ - ["p", "relay_public_key"] - ], - "sig": "event_signature" -} +# Run container +docker run -d \ + --name c-relay \ + -p 8888:8888 \ + -v /path/to/data:/data \ + c-relay ``` -The `content` field contains a NIP-44 encrypted JSON array representing the command. +### Cloud Deployment -**Admin Response Event:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "BpKCVhfN8eYtRmPqSvWxZnMkL2gHjUiOp3rTyEwQaS5dFg...", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] +Quick deployment scripts for popular cloud providers: + +```bash +# AWS, GCP, DigitalOcean, etc. +sudo examples/deployment/simple-vps/deploy.sh ``` -The `content` field contains a NIP-44 encrypted JSON response object. +See [`docs/deployment_guide.md`](docs/deployment_guide.md) for detailed deployment instructions. -### Admin Commands +## ๐Ÿ”ง Configuration -All commands are sent as NIP-44 encrypted JSON arrays in the event content. The following table lists all available commands: +C-Relay uses an innovative event-based configuration system. All settings are managed through signed Nostr events. -| Command Type | Command Format | Description | -|--------------|----------------|-------------| -| **Configuration Management** | -| `config_update` | `["config_update", [{"key": "auth_enabled", "value": "true", "data_type": "boolean", "category": "auth"}, {"key": "relay_description", "value": "My Relay", "data_type": "string", "category": "relay"}, ...]]` | Update relay configuration parameters (supports multiple updates) | -| `config_query` | `["config_query", "all"]` | Query all configuration parameters | -| **Auth Rules Management** | -| `auth_add_blacklist` | `["blacklist", "pubkey", "abc123..."]` | Add pubkey to blacklist | -| `auth_add_whitelist` | `["whitelist", "pubkey", "def456..."]` | Add pubkey to whitelist | -| `auth_delete_rule` | `["delete_auth_rule", "blacklist", "pubkey", "abc123..."]` | Delete specific auth rule | -| `auth_query_all` | `["auth_query", "all"]` | Query all auth rules | -| `auth_query_type` | `["auth_query", "whitelist"]` | Query specific rule type | -| `auth_query_pattern` | `["auth_query", "pattern", "abc123..."]` | Query specific pattern | -| **System Commands** | -| `system_clear_auth` | `["system_command", "clear_all_auth_rules"]` | Clear all auth rules | -| `system_status` | `["system_command", "system_status"]` | Get system status | -| `stats_query` | `["stats_query"]` | Get comprehensive database statistics | -| **Database Queries** | -| `sql_query` | `["sql_query", "SELECT * FROM events LIMIT 10"]` | Execute read-only SQL query against relay database | +### Basic Configuration -### Available Configuration Keys +Use the web interface at `http://localhost:8888/api/` or send admin commands via the API. -**Basic Relay Settings:** -- `relay_name`: Relay name (displayed in NIP-11) -- `relay_description`: Relay description text -- `relay_contact`: Contact information -- `relay_software`: Software URL -- `relay_version`: Software version -- `supported_nips`: Comma-separated list of supported NIP numbers (e.g., "1,2,4,9,11,12,13,15,16,20,22,33,40,42") -- `language_tags`: Comma-separated list of supported language tags (e.g., "en,es,fr" or "*" for all) -- `relay_countries`: Comma-separated list of supported country codes (e.g., "US,CA,MX" or "*" for all) -- `posting_policy`: Posting policy URL or text -- `payments_url`: Payment URL for premium features -- `max_connections`: Maximum concurrent connections -- `max_subscriptions_per_client`: Max subscriptions per client -- `max_event_tags`: Maximum tags per event -- `max_content_length`: Maximum event content length +### Common Settings -**Authentication & Access Control:** -- `auth_enabled`: Enable whitelist/blacklist auth rules (`true`/`false`) -- `nip42_auth_required`: Enable NIP-42 cryptographic authentication (`true`/`false`) -- `nip42_auth_required_kinds`: Event kinds requiring NIP-42 auth (comma-separated) -- `nip42_challenge_timeout`: NIP-42 challenge expiration seconds +- **Relay Information**: Name, description, contact info +- **Connection Limits**: Max subscriptions per client, total subscriptions +- **Authentication**: Enable/disable NIP-42, whitelist/blacklist rules +- **Proof of Work**: Minimum difficulty, enforcement mode +- **Event Validation**: Max tags, content length, message size +- **Expiration**: Enable/disable NIP-40 event expiration -**Proof of Work & Validation:** -- `pow_min_difficulty`: Minimum proof-of-work difficulty -- `nip40_expiration_enabled`: Enable event expiration (`true`/`false`) +### Dynamic Updates -**Monitoring Settings:** -- `kind_24567_reporting_throttle_sec`: Minimum seconds between monitoring events (default: 5) +Most configuration changes take effect immediately without restart: +- Relay information (NIP-11) +- Authentication settings +- Subscription limits +- Event validation rules +- Proof of Work settings -### Dynamic Configuration Updates +See [`docs/configuration_guide.md`](docs/configuration_guide.md) for complete configuration reference. -C-Relay supports **dynamic configuration updates** without requiring a restart for most settings. Configuration parameters are categorized as either **dynamic** (can be updated immediately) or **restart-required** (require relay restart to take effect). +## ๐Ÿ“š Documentation -**Dynamic Configuration Parameters (No Restart Required):** -- All relay information (NIP-11) settings: `relay_name`, `relay_description`, `relay_contact`, `relay_software`, `relay_version`, `supported_nips`, `language_tags`, `relay_countries`, `posting_policy`, `payments_url` -- Authentication settings: `auth_enabled`, `nip42_auth_required`, `nip42_auth_required_kinds`, `nip42_challenge_timeout` -- Subscription limits: `max_subscriptions_per_client`, `max_total_subscriptions` -- Event validation limits: `max_event_tags`, `max_content_length`, `max_message_length` -- Proof of Work settings: `pow_min_difficulty`, `pow_mode` -- Event expiration settings: `nip40_expiration_enabled`, `nip40_expiration_strict`, `nip40_expiration_filter`, `nip40_expiration_grace_period` +- **[API Documentation](API.md)** - Complete API reference and advanced features +- **[Configuration Guide](docs/configuration_guide.md)** - Detailed configuration options +- **[Deployment Guide](docs/deployment_guide.md)** - Production deployment instructions +- **[User Guide](docs/user_guide.md)** - End-user documentation +- **[NIP-42 Authentication](docs/NIP-42_Authentication.md)** - Authentication setup guide -**Restart-Required Configuration Parameters:** -- Connection settings: `max_connections`, `relay_port` -- Database and core system settings +## ๐Ÿงช Testing -When updating configuration, the admin API response will indicate whether a restart is required for each parameter. Dynamic updates take effect immediately and are reflected in NIP-11 relay information documents without restart. +Run the comprehensive test suite: -### Response Format +```bash +# Run all tests +./tests/run_all_tests.sh -All admin commands return **signed EVENT responses** via WebSocket following standard Nostr protocol. Responses use JSON content with structured data. +# Run NIP-specific tests +./tests/run_nip_tests.sh -#### Response Examples - -**Success Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"config_update\", \"status\": \"success\", \"message\": \"Operation completed successfully\", \"timestamp\": 1234567890}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] +# Test specific NIPs +./tests/42_nip_test.sh # NIP-42 authentication +./tests/13_nip_test.sh # NIP-13 proof of work ``` -**Error Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"config_update\", \"status\": \"error\", \"error\": \"invalid configuration value\", \"timestamp\": 1234567890}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] +## ๐Ÿ”’ Security + +### Admin Key Management + +The admin private key is displayed **only once** during first startup. Store it securely: + +```bash +# Save to secure location +echo "ADMIN_PRIVKEY=your_admin_private_key" > ~/.c-relay-admin +chmod 600 ~/.c-relay-admin ``` -**Auth Rules Query Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"auth_rules_all\", \"total_results\": 2, \"timestamp\": 1234567890, \"data\": [{\"rule_type\": \"blacklist\", \"pattern_type\": \"pubkey\", \"pattern_value\": \"abc123...\", \"action\": \"allow\"}]}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] -``` +### Production Security -**Configuration Query Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"config_all\", \"total_results\": 27, \"timestamp\": 1234567890, \"data\": [{\"key\": \"auth_enabled\", \"value\": \"false\", \"data_type\": \"boolean\", \"category\": \"auth\", \"description\": \"Enable NIP-42 authentication\"}, {\"key\": \"relay_description\", \"value\": \"My Relay\", \"data_type\": \"string\", \"category\": \"relay\", \"description\": \"Relay description text\"}]}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] -``` +- Use HTTPS/WSS with reverse proxy (nginx/Apache) +- Enable NIP-42 authentication for client verification +- Configure whitelist/blacklist for access control +- Set up firewall rules to restrict access +- Enable Proof of Work to prevent spam +- Regular database backups -**Configuration Update Success Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"config_update\", \"total_results\": 2, \"timestamp\": 1234567890, \"status\": \"success\", \"data\": [{\"key\": \"auth_enabled\", \"value\": \"true\", \"status\": \"updated\"}, {\"key\": \"relay_description\", \"value\": \"My Updated Relay\", \"status\": \"updated\"}]}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] -``` +See [`docs/deployment_guide.md`](docs/deployment_guide.md#security-hardening) for security hardening guide. -**Configuration Update Error Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"config_update\", \"status\": \"error\", \"error\": \"field validation failed: invalid port number '99999' (must be 1-65535)\", \"timestamp\": 1234567890}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] -``` +## ๐Ÿค Contributing -**Database Statistics Query Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"stats_query\", \"timestamp\": 1234567890, \"database_size_bytes\": 1048576, \"total_events\": 15432, \"database_created_at\": 1234567800, \"latest_event_at\": 1234567890, \"event_kinds\": [{\"kind\": 1, \"count\": 12000, \"percentage\": 77.8}, {\"kind\": 0, \"count\": 2500, \"percentage\": 16.2}], \"time_stats\": {\"total\": 15432, \"last_24h\": 234, \"last_7d\": 1456, \"last_30d\": 5432}, \"top_pubkeys\": [{\"pubkey\": \"abc123...\", \"event_count\": 1234, \"percentage\": 8.0}, {\"pubkey\": \"def456...\", \"event_count\": 987, \"percentage\": 6.4}]}", - "tags": [ - ["p", "admin_public_key"] - ], - "sig": "response_event_signature" -}] -``` +Contributions are welcome! Please: -**SQL Query Response:** -```json -["EVENT", "temp_sub_id", { - "id": "response_event_id", - "pubkey": "relay_public_key", - "created_at": 1234567890, - "kind": 23457, - "content": "nip44 encrypted:{\"query_type\": \"sql_query\", \"request_id\": \"request_event_id\", \"timestamp\": 1234567890, \"query\": \"SELECT * FROM events LIMIT 10\", \"execution_time_ms\": 45, \"row_count\": 10, \"columns\": [\"id\", \"pubkey\", \"created_at\", \"kind\", \"content\"], \"rows\": [[\"abc123...\", \"def456...\", 1234567890, 1, \"Hello world\"], ...]}", - "tags": [ - ["p", "admin_public_key"], - ["e", "request_event_id"] - ], - "sig": "response_event_signature" -}] -``` +1. Fork the repository +2. Create a feature branch +3. Make your changes with tests +4. Submit a pull request -### SQL Query Command +## ๐Ÿ“„ License -The `sql_query` command allows administrators to execute read-only SQL queries against the relay database. This provides powerful analytics and debugging capabilities through the admin API. +[Add your license here] -**Request/Response Correlation:** -- Each response includes the request event ID in both the `tags` array (`["e", "request_event_id"]`) and the decrypted content (`"request_id": "request_event_id"`) -- This allows proper correlation when multiple queries are submitted concurrently -- Frontend can track pending queries and match responses to requests +## ๐Ÿ”— Links -**Security Features:** -- Only SELECT statements allowed (INSERT, UPDATE, DELETE, DROP, etc. are blocked) -- Query timeout: 5 seconds (configurable) -- Result row limit: 1000 rows (configurable) -- All queries logged with execution time +- **Repository**: [https://github.com/your-org/c-relay](https://github.com/your-org/c-relay) +- **Releases**: [https://git.laantungir.net/laantungir/c-relay/releases](https://git.laantungir.net/laantungir/c-relay/releases) +- **Issues**: [https://github.com/your-org/c-relay/issues](https://github.com/your-org/c-relay/issues) +- **Nostr Protocol**: [https://github.com/nostr-protocol/nostr](https://github.com/nostr-protocol/nostr) -**Available Tables and Views:** -- `events` - All Nostr events -- `config` - Configuration parameters -- `auth_rules` - Authentication rules -- `subscription_events` - Subscription lifecycle log -- `event_broadcasts` - Event broadcast log -- `recent_events` - Last 1000 events (view) -- `event_stats` - Event statistics by type (view) -- `subscription_analytics` - Subscription metrics (view) -- `active_subscriptions_log` - Currently active subscriptions (view) -- `event_kinds_view` - Event distribution by kind (view) -- `top_pubkeys_view` - Top 10 pubkeys by event count (view) -- `time_stats_view` - Time-based statistics (view) +## ๐Ÿ’ฌ Support -**Example Queries:** -```sql --- Recent events -SELECT id, pubkey, created_at, kind FROM events ORDER BY created_at DESC LIMIT 20 - --- Event distribution by kind -SELECT * FROM event_kinds_view ORDER BY count DESC - --- Active subscriptions -SELECT * FROM active_subscriptions_log ORDER BY created_at DESC - --- Database statistics -SELECT - (SELECT COUNT(*) FROM events) as total_events, - (SELECT COUNT(*) FROM subscription_events) as total_subscriptions -``` - - - - - - -## Real-time Monitoring System - -C-Relay includes a subscription-based monitoring system that broadcasts real-time relay statistics using ephemeral events (kind 24567). - -### Activation - -The monitoring system activates automatically when clients subscribe to kind 24567 events: - -```json -["REQ", "monitoring-sub", {"kinds": [24567]}] -``` - -For specific monitoring types, use d-tag filters: - -```json -["REQ", "event-kinds-sub", {"kinds": [24567], "#d": ["event_kinds"]}] -["REQ", "time-stats-sub", {"kinds": [24567], "#d": ["time_stats"]}] -["REQ", "top-pubkeys-sub", {"kinds": [24567], "#d": ["top_pubkeys"]}] -``` - -When no subscriptions exist, monitoring is dormant to conserve resources. - -### Monitoring Event Types - -| Type | d Tag | Description | -|------|-------|-------------| -| Event Distribution | `event_kinds` | Event count by kind with percentages | -| Time Statistics | `time_stats` | Events in last 24h, 7d, 30d | -| Top Publishers | `top_pubkeys` | Top 10 pubkeys by event count | -| Active Subscriptions | `active_subscriptions` | Current subscription details (admin only) | -| Subscription Details | `subscription_details` | Detailed subscription info (admin only) | -| CPU Metrics | `cpu_metrics` | Process CPU and memory usage | - -### Event Structure - -```json -{ - "kind": 24567, - "pubkey": "", - "created_at": , - "content": "{\"data_type\":\"event_kinds\",\"timestamp\":1234567890,...}", - "tags": [ - ["d", "event_kinds"] - ] -} -``` - -### Configuration - -- `kind_24567_reporting_throttle_sec`: Minimum seconds between monitoring events (default: 5) - -### Web Dashboard Integration - -The built-in web dashboard (`/api/`) automatically subscribes to monitoring events and displays real-time statistics. - -### Performance Considerations - -- Monitoring events are ephemeral (not stored in database) -- Throttling prevents excessive event generation -- Automatic activation/deactivation based on subscriptions -- Minimal overhead when no clients are monitoring - -## Direct Messaging Admin System - -In addition to the above admin API, c-relay allows the administrator to direct message the relay to get information or control some settings. As long as the administrator is signed in with any nostr client that allows sending nip-17 direct messages (DMs), they can control the relay. - -The is possible because the relay is a full nostr citizen with it's own private and public key, and it knows the administrator's public key. - - - -**Available DM commands** - -The intent is not to be strict in the formatting of the DM. So for example if the relay receives any DM from the administrator with the words "stats" or "statistics" in it, it will respond to the administrator with a reply DM with the current relay statistics. - -- `stats`|`statistics`: Relay statistics -- `config`|`configuration`: Relay configuration +- Open an issue on GitHub +- Join the Nostr community +- Contact via Nostr DM (relay pubkey shown on startup) +--- +**Built with โค๏ธ for the Nostr protocol** diff --git a/src/main.h b/src/main.h index c5138e7..86db098 100644 --- a/src/main.h +++ b/src/main.h @@ -11,9 +11,9 @@ // Version information (auto-updated by build system) #define VERSION_MAJOR 1 -#define VERSION_MINOR 0 -#define VERSION_PATCH 9 -#define VERSION "v1.0.9" +#define VERSION_MINOR 1 +#define VERSION_PATCH 0 +#define VERSION "v1.1.0" // Avoid VERSION_MAJOR redefinition warning from nostr_core_lib #undef VERSION_MAJOR