
# AGENTS.md - AI Agent Integration Guide for Architect Mode

**Project-Specific Information for AI Agents Working with C-Relay-PG in Architect Mode**

## Critical Architecture Understanding

### System Architecture Overview
C-Relay-PG 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**: `<relay_pubkey>.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-PG:**
```
Traditional:           C-Relay-PG:
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_pg_x86
├── build/<relay_pubkey>.db
└── relay.log
```

### Production SystemD Deployment
```
/opt/c-relay-pg/:
├── c_relay_pg_x86
├── <relay_pubkey>.db
├── systemd service (c-relay-pg.service)
└── c-relay-pg 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-PG
                       ├── 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-PG'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.]