From f1f3236196b9269db0f74c19bc12ea510207e160 Mon Sep 17 00:00:00 2001 From: mleku Date: Thu, 9 Oct 2025 19:31:38 +0100 Subject: [PATCH] revise readme.adoc --- readme.adoc | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 272 insertions(+), 3 deletions(-) diff --git a/readme.adoc b/readme.adoc index db2dfd9..2a14e49 100644 --- a/readme.adoc +++ b/readme.adoc @@ -49,7 +49,7 @@ To build with the embedded web interface: [source,bash] ---- -# Build the React web application +# Build the Svelte web application cd app/web bun install bun run build @@ -59,13 +59,25 @@ cd ../../ go build -o orly ---- -You can automate this process with a build script: +The recommended way to build and embed the web UI is using the provided script: + +[source,bash] +---- +./scripts/update-embedded-web.sh +---- + +This script will: +- Build the Svelte app in `app/web` to `app/web/dist` using Bun (preferred) or fall back to npm/yarn/pnpm +- Run `go install` from the repository root so the binary picks up the new embedded assets +- Automatically detect and use the best available JavaScript package manager + +For manual builds, you can also use: [source,bash] ---- #!/bin/bash # build.sh -echo "Building React app..." +echo "Building Svelte app..." cd app/web bun install bun run build @@ -79,6 +91,263 @@ echo "Build complete!" Make it executable with `chmod +x build.sh` and run with `./build.sh`. +== web UI + +ORLY includes a modern web-based user interface built with link:https://svelte.dev/[Svelte] that provides comprehensive relay management capabilities. + +=== features + +The web UI offers: + +* **Authentication**: Secure login using Nostr key pairs with challenge-response authentication +* **Event Management**: View, export, and import Nostr events with advanced filtering and search +* **User Administration**: Manage user permissions and roles (admin/owner) +* **Sprocket Management**: Configure and manage external event processing scripts +* **Real-time Updates**: Live event streaming and status updates +* **Dark/Light Theme**: Toggle between themes with persistent preferences +* **Responsive Design**: Works on desktop and mobile devices + +=== authentication + +The web UI uses Nostr-native authentication: + +1. **Challenge Generation**: Server generates a cryptographic challenge +2. **Signature Verification**: Client signs the challenge with their private key +3. **Session Management**: Authenticated sessions with role-based permissions + +Supported authentication methods: +- Direct private key input +- Nostr extension integration +- Hardware wallet support + +=== user roles + +* **Guest**: Read-only access to public events +* **User**: Can publish events and manage their own content +* **Admin**: Full relay management except sprocket configuration +* **Owner**: Complete control including sprocket management and system configuration + +=== event management + +The interface provides comprehensive event management: + +* **Event Browser**: Paginated view of all events with filtering by kind, author, and content +* **Export Functionality**: Export events in JSON format with configurable date ranges +* **Import Capability**: Bulk import events (admin/owner only) +* **Search**: Full-text search across event content and metadata +* **Event Details**: Expandable view showing full event JSON and metadata + +=== sprocket integration + +The web UI includes a dedicated sprocket management interface: + +* **Status Monitoring**: Real-time status of sprocket scripts +* **Script Upload**: Upload and manage sprocket scripts +* **Version Control**: Track and manage multiple script versions +* **Configuration**: Configure sprocket parameters and settings +* **Logs**: View sprocket execution logs and errors + +=== development mode + +For development, the web UI supports hot-reloading: + +[source,bash] +---- +# Enable development proxy +export ORLY_WEB_DISABLE_EMBEDDED=true +export ORLY_WEB_DEV_PROXY_URL=localhost:5000 + +# Start relay +./orly + +# In another terminal, start Svelte dev server +cd app/web +bun run dev +---- + +This allows for rapid development with automatic reloading of changes. + +== sprocket event sifter interface + +The sprocket system provides a powerful interface for external event processing scripts, allowing you to implement custom filtering, validation, and processing logic for Nostr events before they are stored in the relay. + +=== overview + +Sprocket scripts receive events via stdin and respond with JSONL (JSON Lines) format, enabling real-time event processing with three possible actions: + +* **accept**: Continue with normal event processing +* **reject**: Return OK false to client with rejection message +* **shadowReject**: Return OK true to client but abort processing (useful for spam filtering) + +=== how it works + +1. **Event Reception**: Events are sent to the sprocket script as JSON objects via stdin +2. **Processing**: Script analyzes the event and applies custom logic +3. **Response**: Script responds with JSONL containing the decision and optional message +4. **Action**: Relay processes the response and either accepts, rejects, or shadow rejects the event + +=== script protocol + +==== input format + +Events are sent as JSON objects, one per line: + +```json +{ + "id": "event_id_here", + "kind": 1, + "content": "Hello, world!", + "pubkey": "author_pubkey", + "tags": [["t", "hashtag"], ["p", "reply_pubkey"]], + "created_at": 1640995200, + "sig": "signature_here" +} +``` + +==== output format + +Scripts must respond with JSONL format: + +```json +{"id": "event_id", "action": "accept", "msg": ""} +{"id": "event_id", "action": "reject", "msg": "reason for rejection"} +{"id": "event_id", "action": "shadowReject", "msg": ""} +``` + +=== configuration + +Enable sprocket processing: + +[source,bash] +---- +export ORLY_SPROCKET_ENABLED=true +export ORLY_APP_NAME="ORLY" +---- + +The sprocket script should be placed at: +`~/.config/{ORLY_APP_NAME}/sprocket.sh` + +=== example script + +Here's a Python example that implements various filtering criteria: + +[source,python] +---- +#!/usr/bin/env python3 +import json +import sys + +def process_event(event_json): + event_id = event_json.get('id', '') + event_content = event_json.get('content', '') + event_kind = event_json.get('kind', 0) + + # Reject spam content + if 'spam' in event_content.lower(): + return { + 'id': event_id, + 'action': 'reject', + 'msg': 'Content contains spam' + } + + # Shadow reject test events + if event_kind == 9999: + return { + 'id': event_id, + 'action': 'shadowReject', + 'msg': '' + } + + # Accept all other events + return { + 'id': event_id, + 'action': 'accept', + 'msg': '' + } + +# Main processing loop +for line in sys.stdin: + if line.strip(): + try: + event = json.loads(line) + response = process_event(event) + print(json.dumps(response)) + sys.stdout.flush() + except json.JSONDecodeError: + continue +---- + +=== bash example + +A simple bash script example: + +[source,bash] +---- +#!/bin/bash +while read -r line; do + if [[ -n "$line" ]]; then + # Extract event ID + event_id=$(echo "$line" | jq -r '.id') + + # Check for spam content + if echo "$line" | jq -r '.content' | grep -qi "spam"; then + echo "{\"id\":\"$event_id\",\"action\":\"reject\",\"msg\":\"Spam detected\"}" + else + echo "{\"id\":\"$event_id\",\"action\":\"accept\",\"msg\":\"\"}" + fi + fi +done +---- + +=== testing + +Test your sprocket script directly: + +[source,bash] +---- +# Test with sample event +echo '{"id":"test","kind":1,"content":"spam test"}' | python3 sprocket.py + +# Expected output: +# {"id": "test", "action": "reject", "msg": "Content contains spam"} +---- + +Run the comprehensive test suite: + +[source,bash] +---- +./test-sprocket-complete.sh +---- + +=== web UI management + +The web UI provides a complete sprocket management interface: + +* **Status Monitoring**: View real-time sprocket status and health +* **Script Upload**: Upload new sprocket scripts via the web interface +* **Version Management**: Track and manage multiple script versions +* **Configuration**: Configure sprocket parameters and settings +* **Logs**: View execution logs and error messages +* **Restart**: Restart sprocket scripts without relay restart + +=== use cases + +Common sprocket use cases include: + +* **Spam Filtering**: Detect and reject spam content +* **Content Moderation**: Implement custom content policies +* **Rate Limiting**: Control event publishing rates +* **Event Validation**: Additional validation beyond Nostr protocol +* **Analytics**: Log and analyze event patterns +* **Integration**: Connect with external services and APIs + +=== performance considerations + +* Sprocket scripts run synchronously and can impact relay performance +* Keep processing logic efficient and fast +* Use appropriate timeouts to prevent blocking +* Consider using shadow reject for non-critical filtering to maintain user experience + == secp256k1 dependency ORLY uses the optimized `libsecp256k1` C library from Bitcoin Core for schnorr signatures, providing 4x faster signing and ECDH operations compared to pure Go implementations.