# AGENTS.md - AI Agent Integration Guide for Architect Mode **Project-Specific Information for AI Agents Working with C-Relay in Architect Mode** ## Critical Architecture Understanding ### System Architecture Overview C-Relay implements a **unique event-based configuration architecture** that fundamentally differs from traditional Nostr relays: ``` ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ WebSocket │ │ Configuration │ │ Database │ │ + HTTP │◄──►│ Event System │◄──►│ (SQLite) │ │ (Port 8888) │ │ (Kind 33334) │ │ Schema v4 │ └─────────────────┘ └──────────────────┘ └─────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ nostr_core_lib │ │ Admin Key │ │ Event Storage │ │ (Crypto/Sigs) │ │ Management │ │ + Subscriptions │ └─────────────────┘ └──────────────────┘ └─────────────────┘ ``` ### Core Architectural Principles #### 1. Event-Driven Configuration **Design Philosophy**: Configuration as cryptographically signed events rather than files - **Benefits**: Auditability, remote management, tamper-evidence - **Trade-offs**: Complexity in configuration changes, admin key management burden - **Implementation**: Kind 33334 events stored in same database as relay events #### 2. Identity-Based Database Naming **Design Philosophy**: Database file named by relay's generated public key - **Benefits**: Prevents database conflicts, enables multi-relay deployments - **Trade-offs**: Cannot predict database filename, complicates backup strategies - **Implementation**: `.db` created in build/ directory #### 3. Single-Binary Deployment **Design Philosophy**: All functionality embedded in one executable - **Benefits**: Simple deployment, no external dependencies to manage - **Trade-offs**: Larger binary size, harder to modularize - **Implementation**: SQL schema embedded as header file, nostr_core_lib as submodule #### 4. Dual-Protocol Support **Design Philosophy**: WebSocket (Nostr) and HTTP (NIP-11) on same port - **Benefits**: Simplified port management, reduced infrastructure complexity - **Trade-offs**: Protocol detection overhead, libwebsockets dependency - **Implementation**: Request routing based on HTTP headers and upgrade requests ## Architectural Decision Analysis ### Configuration System Design **Traditional Approach vs C-Relay:** ``` Traditional: C-Relay: config.json → kind 33334 events ENV variables → cryptographically signed tags File watching → database polling/restart ``` **Implications for Extensions:** - Configuration changes require event signing capabilities - No hot-reloading without architectural changes - Admin key loss = complete database reset required ### Database Architecture Decisions **Schema Design Philosophy:** - **Event Tags as JSON**: Separate table with JSON column instead of normalized relations - **Application-Level Filtering**: NIP-40 expiration handled in C, not SQL - **Embedded Schema**: Version 4 schema compiled into binary **Scaling Considerations:** - SQLite suitable for small-to-medium relays (< 10k concurrent connections) - Single-writer limitation of SQLite affects write-heavy workloads - JSON tag storage optimizes for read performance over write normalization ### Memory Management Architecture **Thread Safety Model:** - Global subscription manager with mutex protection - Per-client subscription limits enforced in memory - WebSocket connection state managed by libwebsockets **Resource Management:** - JSON objects use reference counting (jansson library) - String duplication pattern for configuration values - Automatic cleanup on client disconnect ## Architectural Extension Points ### Adding New Configuration Options **Required Changes:** 1. Update [`default_config_event.h`](src/default_config_event.h) template 2. Add parsing logic in [`config.c`](src/config.c) `load_config_from_database()` 3. Add global config struct field in [`config.h`](src/config.h) 4. Update documentation in [`docs/configuration_guide.md`](docs/configuration_guide.md) ### Adding New NIP Support **Integration Pattern:** 1. Event validation in [`request_validator.c`](src/request_validator.c) 2. Protocol handling in [`main.c`](src/main.c) WebSocket callback 3. Database storage considerations in schema 4. Add test in `tests/` directory ### Scaling Architecture **Current Limitations:** - Single process, no horizontal scaling - SQLite single-writer bottleneck - Memory-based subscription management **Potential Extensions:** - Redis for subscription state sharing - PostgreSQL for better concurrent write performance - Load balancer for read scaling with multiple instances ## Deployment Architecture Patterns ### Development Deployment ``` Developer Machine: ├── ./make_and_restart_relay.sh ├── build/c_relay_x86 ├── build/.db └── relay.log ``` ### Production SystemD Deployment ``` /opt/c-relay/: ├── c_relay_x86 ├── .db ├── systemd service (c-relay.service) └── c-relay user isolation ``` ### Container Deployment Architecture ``` Container: ├── Multi-stage build (deps + binary) ├── Volume mount for database persistence ├── Health checks via NIP-11 endpoint └── Signal handling for graceful shutdown ``` ### Reverse Proxy Architecture ``` Internet → Nginx/HAProxy → C-Relay ├── WebSocket upgrade handling ├── SSL termination └── Rate limiting ``` ## Security Architecture Considerations ### Key Management Design **Admin Key Security Model:** - Generated once, displayed once, never stored - Required for all configuration changes - Loss requires complete database reset **Relay Identity Model:** - Separate keypair for relay identity - Public key used for database naming - Private key never exposed to clients ### Event Validation Pipeline ``` WebSocket Input → JSON Parse → Schema Validate → Signature Verify → Store ↓ ↓ ↓ reject reject reject success ``` ### Attack Surface Analysis **Network Attack Vectors:** - WebSocket connection flooding (mitigated by libwebsockets limits) - JSON parsing attacks (handled by jansson library bounds checking) - SQLite injection (prevented by prepared statements) **Configuration Attack Vectors:** - Admin key compromise (complete relay control) - Event signature forgery (prevented by nostr_core_lib validation) - Replay attacks (event timestamp validation required) ## Non-Obvious Architectural Considerations ### Database Evolution Strategy **Current Limitations:** - Schema changes require database recreation - No migration system for configuration events - Version 4 schema embedded in binary **Future Architecture Needs:** - Schema versioning and migration system - Backward compatibility for configuration events - Database backup/restore procedures ### Configuration Event Lifecycle **Event Flow:** ``` Admin Signs Event → WebSocket Submit → Validate → Store → Restart Required ↓ ↓ ↓ Signature Check Database Config Reload ``` **Architectural Implications:** - No hot configuration reloading - Configuration changes require planned downtime - Event ordering matters for multiple simultaneous changes ### Cross-Architecture Deployment **Build System Architecture:** - Auto-detection of host architecture - Cross-compilation support for ARM64 - Architecture-specific binary outputs **Deployment Implications:** - Binary must match target architecture - Dependencies must be available for target architecture - Debug tooling architecture-specific ### Performance Architecture Characteristics **Bottlenecks:** 1. **SQLite Write Performance**: Single writer limitation 2. **JSON Parsing**: Per-event parsing overhead 3. **Signature Validation**: Cryptographic operations per event 4. **Memory Management**: JSON object lifecycle management **Optimization Points:** - Prepared statement reuse - Connection pooling for concurrent reads - Event batching for bulk operations - Subscription indexing strategies ### Integration Architecture Patterns **Monitoring Integration:** - NIP-11 endpoint for health checks - Log file monitoring for operational metrics - Database query monitoring for performance - Process monitoring for resource usage **Backup Architecture:** - Database file backup (SQLite file copy) - Configuration event export/import - Admin key secure storage (external to relay) ### Future Extension Architectures **Multi-Relay Coordination:** - Database sharding by event kind - Cross-relay event synchronization - Distributed configuration management **Plugin Architecture Possibilities:** - Event processing pipeline hooks - Custom validation plugins - External authentication providers **Scaling Architecture Options:** - Read replicas with PostgreSQL migration - Event stream processing with message queues - Microservice decomposition (auth, storage, validation) ## Architectural Anti-Patterns to Avoid 1. **Configuration File Addition**: Breaks event-based config paradigm 2. **Direct Database Modification**: Bypasses signature validation 3. **Hard-Coded Ports**: Conflicts with auto-fallback system 4. **Schema Modifications**: Requires database recreation 5. **Admin Key Storage**: Violates security model 6. **Blocking Operations**: Interferes with WebSocket event loop 7. **Memory Leaks**: JSON objects must be properly reference counted 8. **Thread Unsafe Operations**: Global state requires proper synchronization ## Architecture Decision Records (Implicit) ### Decision: Event-Based Configuration **Context**: Traditional config files vs. cryptographic auditability **Decision**: Store configuration as signed Nostr events **Consequences**: Complex configuration changes, enhanced security, remote management capability ### Decision: SQLite Database **Context**: Database choice for relay storage **Decision**: Embedded SQLite with JSON tag storage **Consequences**: Simple deployment, single-writer limitation, application-level filtering ### Decision: Single Binary Deployment **Context**: Dependency management vs. deployment simplicity **Decision**: Embed all dependencies and schema in binary **Consequences**: Larger binary, simple deployment, version coupling ### Decision: Dual Protocol Support **Context**: WebSocket for Nostr, HTTP for NIP-11 **Decision**: Same port serves both protocols **Consequences**: Simplified deployment, protocol detection overhead, libwebsockets dependency These architectural decisions form the foundation of C-Relay's unique approach to Nostr relay implementation and should be carefully considered when planning extensions or modifications. ** [Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.]