Files
ginxsom/docs/MANAGEMENT_SYSTEM_DESIGN.md
2025-11-20 07:53:58 -04:00

26 KiB

Ginxsom Management System Design

Executive Summary

This document outlines the design for a secure management interface for ginxsom (Blossom media storage server) based on c-relay's proven admin system architecture. The design uses Kind 23456/23457 events with NIP-44 encryption over WebSocket for real-time admin operations.

1. System Architecture

1.1 High-Level Overview

graph TB
    Admin[Admin Client] -->|WebSocket| WS[WebSocket Handler]
    WS -->|Kind 23456| Auth[Admin Authorization]
    Auth -->|Decrypt NIP-44| Decrypt[Command Decryption]
    Decrypt -->|Parse JSON Array| Router[Command Router]
    Router -->|Route by Command Type| Handlers[Unified Handlers]
    Handlers -->|Execute| DB[(Database)]
    Handlers -->|Execute| FS[File System]
    Handlers -->|Generate Response| Encrypt[NIP-44 Encryption]
    Encrypt -->|Kind 23457| WS
    WS -->|WebSocket| Admin
    
    style Admin fill:#e1f5ff
    style Auth fill:#fff3cd
    style Handlers fill:#d4edda
    style DB fill:#f8d7da

1.2 Component Architecture

graph LR
    subgraph "Admin Interface"
        CLI[CLI Tool]
        Web[Web Dashboard]
    end
    
    subgraph "ginxsom FastCGI Process"
        WS[WebSocket Endpoint]
        Auth[Authorization Layer]
        Router[Command Router]
        
        subgraph "Unified Handlers"
            BlobH[Blob Handler]
            StorageH[Storage Handler]
            ConfigH[Config Handler]
            StatsH[Stats Handler]
            SystemH[System Handler]
        end
        
        DB[(SQLite Database)]
        Storage[Blob Storage]
    end
    
    CLI -->|WebSocket| WS
    Web -->|WebSocket| WS
    WS --> Auth
    Auth --> Router
    Router --> BlobH
    Router --> StorageH
    Router --> ConfigH
    Router --> StatsH
    Router --> SystemH
    
    BlobH --> DB
    BlobH --> Storage
    StorageH --> Storage
    ConfigH --> DB
    StatsH --> DB
    SystemH --> DB
    
    style Auth fill:#fff3cd
    style Router fill:#d4edda

1.3 Data Flow for Admin Commands

sequenceDiagram
    participant Admin
    participant WebSocket
    participant Auth
    participant Handler
    participant Database
    
    Admin->>WebSocket: Kind 23456 Event (NIP-44 encrypted)
    WebSocket->>Auth: Verify admin signature
    Auth->>Auth: Check pubkey matches admin_pubkey
    Auth->>Auth: Verify event signature
    Auth->>WebSocket: Authorization OK
    WebSocket->>Handler: Decrypt & parse command array
    Handler->>Handler: Validate command structure
    Handler->>Database: Execute operation
    Database-->>Handler: Result
    Handler->>Handler: Build response JSON
    Handler->>WebSocket: Encrypt response (NIP-44)
    WebSocket->>Admin: Kind 23457 Event (encrypted response)

1.4 Integration with Existing Ginxsom

graph TB
    subgraph "Existing Ginxsom"
        Main[main.c]
        BUD04[bud04.c - Mirror]
        BUD06[bud06.c - Requirements]
        BUD08[bud08.c - NIP-94]
        BUD09[bud09.c - Report]
        AdminAPI[admin_api.c - Basic Admin]
        Validator[request_validator.c]
    end
    
    subgraph "New Management System"
        AdminWS[admin_websocket.c]
        AdminAuth[admin_auth.c]
        AdminHandlers[admin_handlers.c]
        AdminConfig[admin_config.c]
    end
    
    Main -->|Initialize| AdminWS
    AdminWS -->|Use| AdminAuth
    AdminWS -->|Route to| AdminHandlers
    AdminHandlers -->|Query| BUD04
    AdminHandlers -->|Query| BUD06
    AdminHandlers -->|Query| BUD08
    AdminHandlers -->|Query| BUD09
    AdminHandlers -->|Update| AdminConfig
    AdminAuth -->|Use| Validator
    
    style AdminWS fill:#d4edda
    style AdminAuth fill:#fff3cd
    style AdminHandlers fill:#e1f5ff

2. Database Schema

2.1 Core Tables

Following c-relay's minimal approach, we need only two tables for key management:

relay_seckey Table

-- Stores relay's private key (used for signing Kind 23457 responses)
CREATE TABLE relay_seckey (
    private_key_hex TEXT NOT NULL CHECK (length(private_key_hex) = 64),
    created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
);

Note: This table stores the relay's private key as plain hex (no encryption). The key is used to:

  • Sign Kind 23457 response events
  • Encrypt responses using NIP-44 (shared secret with admin pubkey)

config Table (Extended)

-- Existing config table, add admin_pubkey entry
INSERT INTO config (key, value, data_type, description, category, requires_restart)
VALUES (
    'admin_pubkey',
    '<64-char-hex-pubkey>',
    'string',
    'Public key of authorized admin (hex format)',
    'security',
    0
);

Note: Admin public key is stored in the config table, not a separate table. Admin private key is NEVER stored anywhere.

2.2 Schema Comparison with c-relay

c-relay ginxsom Purpose
relay_seckey (private_key_hex, created_at) relay_seckey (private_key_hex, created_at) Relay private key storage
config table entry for admin_pubkey config table entry for admin_pubkey Admin authorization
No audit log No audit log Keep it simple
No processed events tracking No processed events tracking Stateless processing

2.3 Key Storage Strategy

Relay Private Key:

  • Stored in relay_seckey table as plain 64-character hex
  • Generated on first startup or provided via --relay-privkey CLI option
  • Used for signing Kind 23457 responses and NIP-44 encryption
  • Never exposed via API

Admin Public Key:

  • Stored in config table as plain 64-character hex
  • Generated on first startup or provided via --admin-pubkey CLI option
  • Used to verify Kind 23456 command signatures
  • Can be queried via admin API

Admin Private Key:

  • NEVER stored anywhere in the system
  • Kept only by the admin in their client/tool
  • Used to sign Kind 23456 commands and decrypt Kind 23457 responses

3. API Design

3.1 Command Structure

Following c-relay's pattern, all commands use JSON array format:

["command_name", {"param1": "value1", "param2": "value2"}]

3.2 Event Structure

Kind 23456 - Admin Command Event

{
  "kind": 23456,
  "pubkey": "<admin-pubkey-hex>",
  "created_at": 1234567890,
  "tags": [
    ["p", "<relay-pubkey-hex>"]
  ],
  "content": "<nip44-encrypted-command-array>",
  "sig": "<signature>"
}

Content (decrypted):

["blob_list", {"limit": 100, "offset": 0}]

Kind 23457 - Admin Response Event

{
  "kind": 23457,
  "pubkey": "<relay-pubkey-hex>",
  "created_at": 1234567890,
  "tags": [
    ["p", "<admin-pubkey-hex>"],
    ["e", "<original-command-event-id>"]
  ],
  "content": "<nip44-encrypted-response>",
  "sig": "<signature>"
}

Content (decrypted):

{
  "success": true,
  "data": {
    "blobs": [
      {"sha256": "abc123...", "size": 1024, "type": "image/png"},
      {"sha256": "def456...", "size": 2048, "type": "video/mp4"}
    ],
    "total": 2
  }
}

3.3 Command Categories

Blob Operations

  • blob_list - List blobs with pagination
  • blob_info - Get detailed blob information
  • blob_delete - Delete blob(s)
  • blob_mirror - Mirror blob from another server

Storage Management

  • storage_stats - Get storage usage statistics
  • storage_quota - Get/set storage quotas
  • storage_cleanup - Clean up orphaned files

Configuration

  • config_get - Get configuration value(s)
  • config_set - Set configuration value(s)
  • config_list - List all configuration
  • auth_rules_list - List authentication rules
  • auth_rules_add - Add authentication rule
  • auth_rules_remove - Remove authentication rule

Statistics

  • stats_uploads - Upload statistics
  • stats_bandwidth - Bandwidth usage
  • stats_storage - Storage usage over time
  • stats_users - User activity statistics

System

  • system_info - Get system information
  • system_restart - Restart server (graceful)
  • system_backup - Trigger database backup
  • system_restore - Restore from backup

3.4 Command Examples

Example 1: List Blobs

// Command (Kind 23456 content, decrypted)
["blob_list", {
  "limit": 50,
  "offset": 0,
  "type": "image/*",
  "sort": "created_at",
  "order": "desc"
}]

// Response (Kind 23457 content, decrypted)
{
  "success": true,
  "data": {
    "blobs": [
      {
        "sha256": "abc123...",
        "size": 102400,
        "type": "image/png",
        "created": 1234567890,
        "url": "https://blossom.example.com/abc123.png"
      }
    ],
    "total": 150,
    "limit": 50,
    "offset": 0
  }
}

Example 2: Delete Blob

// Command
["blob_delete", {
  "sha256": "abc123...",
  "confirm": true
}]

// Response
{
  "success": true,
  "data": {
    "deleted": true,
    "sha256": "abc123...",
    "freed_bytes": 102400
  }
}

Example 3: Get Storage Stats

// Command
["storage_stats", {}]

// Response
{
  "success": true,
  "data": {
    "total_blobs": 1500,
    "total_bytes": 5368709120,
    "total_bytes_human": "5.0 GB",
    "disk_usage": {
      "used": 5368709120,
      "available": 94631291904,
      "total": 100000000000,
      "percent": 5.4
    },
    "by_type": {
      "image/png": {"count": 500, "bytes": 2147483648},
      "image/jpeg": {"count": 300, "bytes": 1610612736},
      "video/mp4": {"count": 200, "bytes": 1610612736}
    }
  }
}

Example 4: Set Configuration

// Command
["config_set", {
  "max_upload_size": 10485760,
  "allowed_mime_types": ["image/*", "video/mp4"]
}]

// Response
{
  "success": true,
  "data": {
    "updated": ["max_upload_size", "allowed_mime_types"],
    "requires_restart": false
  }
}

3.5 Error Handling

All errors follow consistent format:

{
  "success": false,
  "error": {
    "code": "BLOB_NOT_FOUND",
    "message": "Blob with hash abc123... not found",
    "details": {
      "sha256": "abc123..."
    }
  }
}

Error Codes:

  • UNAUTHORIZED - Invalid admin signature
  • INVALID_COMMAND - Unknown command or malformed structure
  • INVALID_PARAMS - Missing or invalid parameters
  • BLOB_NOT_FOUND - Requested blob doesn't exist
  • STORAGE_FULL - Storage quota exceeded
  • DATABASE_ERROR - Database operation failed
  • SYSTEM_ERROR - Internal server error

4. File Structure

4.1 New Files to Create

src/
├── admin_websocket.c       # WebSocket endpoint for admin commands
├── admin_websocket.h       # WebSocket handler declarations
├── admin_auth.c            # Admin authorization (adapted from c-relay)
├── admin_auth.h            # Authorization function declarations
├── admin_handlers.c        # Unified command handlers
├── admin_handlers.h        # Handler function declarations
├── admin_config.c          # Configuration management
├── admin_config.h          # Config function declarations
└── admin_keys.c            # Key generation and storage
    admin_keys.h            # Key management declarations

include/
└── admin_system.h          # Public admin system interface

4.2 Files to Adapt from c-relay

c-relay File Purpose Adaptation for ginxsom
dm_admin.c Admin event processing admin_websocket.c (WebSocket instead of DM)
api.c (lines 768-838) NIP-44 encryption/response admin_handlers.c (response generation)
config.c (lines 500-583) Key storage/retrieval admin_keys.c (relay key management)
main.c (lines 1389-1556) CLI argument parsing main.c (add admin CLI options)

4.3 Integration with Existing Files

src/main.c:

  • Add CLI options: --admin-pubkey, --relay-privkey
  • Initialize admin WebSocket endpoint
  • Generate keys on first startup

src/admin_api.c (existing):

  • Keep existing basic admin API
  • Add WebSocket admin endpoint
  • Route Kind 23456 events to new handlers

db/schema.sql:

  • Add relay_seckey table
  • Add admin_pubkey to config table

5. Implementation Plan

5.1 Phase 1: Foundation (Week 1)

Goal: Set up key management and database schema

Tasks:

  1. Create relay_seckey table in schema
  2. Add admin_pubkey to config table
  3. Implement admin_keys.c:
    • generate_relay_keypair()
    • generate_admin_keypair()
    • store_relay_private_key()
    • load_relay_private_key()
    • get_admin_pubkey()
  4. Update main.c:
    • Add CLI options (--admin-pubkey, --relay-privkey)
    • Generate keys on first startup
    • Print keys once (like c-relay)
  5. Test key generation and storage

Deliverables:

  • Working key generation
  • Keys stored in database
  • CLI options functional

5.2 Phase 2: Authorization (Week 2)

Goal: Implement admin event authorization

Tasks:

  1. Create admin_auth.c (adapted from c-relay's authorization):
    • verify_admin_event() - Check Kind 23456 signature
    • check_admin_pubkey() - Verify against stored admin_pubkey
    • verify_relay_target() - Check 'p' tag matches relay pubkey
  2. Add NIP-44 crypto functions (use existing nostr_core_lib):
    • decrypt_admin_command() - Decrypt Kind 23456 content
    • encrypt_admin_response() - Encrypt Kind 23457 content
  3. Test authorization flow
  4. Test encryption/decryption

Deliverables:

  • Working authorization layer
  • NIP-44 encryption functional
  • Unit tests for auth

5.3 Phase 3: WebSocket Endpoint (Week 3)

Goal: Create WebSocket handler for admin commands

Tasks:

  1. Create admin_websocket.c:
    • WebSocket endpoint at /admin or similar
    • Receive Kind 23456 events
    • Route to authorization layer
    • Parse command array from decrypted content
    • Route to appropriate handler
    • Build Kind 23457 response
    • Send encrypted response
  2. Integrate with existing FastCGI WebSocket handling
  3. Add connection management
  4. Test WebSocket communication

Deliverables:

  • Working WebSocket endpoint
  • Event routing functional
  • Response generation working

5.4 Phase 4: Command Handlers (Week 4-5)

Goal: Implement unified command handlers

Tasks:

  1. Create admin_handlers.c with unified handler pattern:
    • handle_blob_command() - Blob operations
    • handle_storage_command() - Storage management
    • handle_config_command() - Configuration
    • handle_stats_command() - Statistics
    • handle_system_command() - System operations
  2. Implement each command:
    • Blob: list, info, delete, mirror
    • Storage: stats, quota, cleanup
    • Config: get, set, list, auth_rules
    • Stats: uploads, bandwidth, storage, users
    • System: info, restart, backup, restore
  3. Add validation for each command
  4. Test each command individually

Deliverables:

  • All commands implemented
  • Validation working
  • Integration tests passing

5.5 Phase 5: Testing & Documentation (Week 6)

Goal: Comprehensive testing and documentation

Tasks:

  1. Create test suite:
    • Unit tests for each handler
    • Integration tests for full flow
    • Security tests for authorization
    • Performance tests for WebSocket
  2. Create admin CLI tool (simple Node.js/Python script):
    • Generate Kind 23456 events
    • Send via WebSocket
    • Decrypt Kind 23457 responses
    • Pretty-print results
  3. Write documentation:
    • Admin API reference
    • CLI tool usage guide
    • Security best practices
    • Troubleshooting guide
  4. Create example scripts

Deliverables:

  • Complete test suite
  • Working CLI tool
  • Full documentation
  • Example scripts

5.6 Phase 6: Web Dashboard (Optional, Week 7-8)

Goal: Create web-based admin interface

Tasks:

  1. Design web UI (React/Vue/Svelte)
  2. Implement WebSocket client
  3. Create command forms
  4. Add real-time updates
  5. Deploy dashboard

Deliverables:

  • Working web dashboard
  • User documentation
  • Deployment guide

6. Security Considerations

6.1 Key Security

Relay Private Key:

  • Stored in database as plain hex (following c-relay pattern)
  • Never exposed via API
  • Used only for signing responses
  • Backed up with database

Admin Private Key:

  • NEVER stored on server
  • Kept only by admin
  • Used to sign commands
  • Should be stored securely by admin (password manager, hardware key, etc.)

Admin Public Key:

  • Stored in config table
  • Used for authorization
  • Can be rotated by updating config

6.2 Authorization Flow

  1. Receive Kind 23456 event
  2. Verify event signature (nostr_verify_event_signature)
  3. Check pubkey matches admin_pubkey from config
  4. Verify 'p' tag targets this relay
  5. Decrypt content using NIP-44
  6. Parse and validate command
  7. Execute command
  8. Encrypt response using NIP-44
  9. Sign Kind 23457 response
  10. Send response

6.3 Attack Mitigation

Replay Attacks:

  • Check event timestamp (reject old events)
  • Optional: Track processed event IDs (if needed)

Unauthorized Access:

  • Strict pubkey verification
  • Signature validation
  • Relay targeting check

Command Injection:

  • Validate all command parameters
  • Use parameterized SQL queries
  • Sanitize file paths

DoS Protection:

  • Rate limit admin commands
  • Timeout long-running operations
  • Limit response sizes

7. Command Line Interface

7.1 CLI Options (Following c-relay Pattern)

ginxsom [OPTIONS]

Options:
  -h, --help                Show help message
  -v, --version             Show version information
  -p, --port PORT           Override server port
  --strict-port             Fail if exact port unavailable
  -a, --admin-pubkey KEY    Override admin public key (hex or npub)
  -r, --relay-privkey KEY   Override relay private key (hex or nsec)
  --debug-level=N           Set debug level (0-5)

Examples:
  ginxsom                           # Start server (auto-generate keys on first run)
  ginxsom -p 8080                   # Start on port 8080
  ginxsom -a <npub>                 # Set admin pubkey
  ginxsom -r <nsec>                 # Set relay privkey
  ginxsom --debug-level=3           # Enable info-level debugging

7.2 First Startup Behavior

On first startup (no database exists):

  1. Generate relay keypair
  2. Generate admin keypair
  3. Print keys ONCE to console:
=== Ginxsom First Startup ===

Relay Keys (for server):
  Public Key (npub): npub1...
  Private Key (nsec): nsec1...

Admin Keys (for you):
  Public Key (npub): npub1...
  Private Key (nsec): nsec1...

IMPORTANT: Save these keys securely!
The admin private key will NOT be shown again.
The relay private key is stored in the database.

Database created: <relay-pubkey>.db
  1. Store relay private key in database
  2. Store admin public key in config
  3. Start server

7.3 Subsequent Startups

On subsequent startups:

  1. Find existing database file
  2. Load relay private key from database
  3. Load admin public key from config
  4. Apply CLI overrides if provided
  5. Start server

8. Comparison with c-relay

8.1 Similarities

Feature c-relay ginxsom
Event Types Kind 23456/23457 Kind 23456/23457
Encryption NIP-44 NIP-44
Command Format JSON arrays JSON arrays
Key Storage relay_seckey table relay_seckey table
Admin Auth config table config table
CLI Options --admin-pubkey, --relay-privkey --admin-pubkey, --relay-privkey
Response Format Encrypted JSON Encrypted JSON

8.2 Differences

Aspect c-relay ginxsom
Transport WebSocket (Nostr relay) WebSocket (FastCGI)
Commands Relay-specific (auth, config, stats) Blossom-specific (blob, storage, mirror)
Database SQLite (events) SQLite (blobs + metadata)
File Storage N/A Blob storage on disk
Integration Standalone relay FastCGI + nginx

8.3 Architectural Decisions

Why follow c-relay's pattern?

  1. Proven in production
  2. Simple and secure
  3. No complex key management
  4. Minimal database schema
  5. Easy to understand and maintain

What we're NOT doing (from initial design):

  1. NIP-17 gift wrap (too complex)
  2. Separate admin_keys table (use config)
  3. Audit log table (keep it simple)
  4. Processed events tracking (stateless)
  5. Key encryption before storage (plain hex)
  6. Migration strategy (new project)

9. Testing Strategy

9.1 Unit Tests

admin_keys.c:

  • Key generation produces valid keys
  • Keys can be stored and retrieved
  • Invalid keys are rejected

admin_auth.c:

  • Valid admin events pass authorization
  • Invalid signatures are rejected
  • Wrong pubkeys are rejected
  • Expired events are rejected

admin_handlers.c:

  • Each command handler works correctly
  • Invalid parameters are rejected
  • Error responses are properly formatted

9.2 Integration Tests

Full Flow:

  1. Generate admin keypair
  2. Create Kind 23456 command
  3. Send via WebSocket
  4. Verify authorization
  5. Execute command
  6. Receive Kind 23457 response
  7. Decrypt and verify response

Security Tests:

  • Unauthorized pubkey rejected
  • Invalid signature rejected
  • Replay attack prevented
  • Command injection prevented

9.3 Performance Tests

  • WebSocket connection handling
  • Command processing latency
  • Concurrent admin operations
  • Large response handling

10. Future Enhancements

10.1 Short Term

  1. Command History: Track admin commands for audit
  2. Multi-Admin Support: Multiple authorized admin pubkeys
  3. Role-Based Access: Different permission levels
  4. Batch Operations: Execute multiple commands in one request

10.2 Long Term

  1. Web Dashboard: Full-featured web UI
  2. Monitoring Integration: Prometheus/Grafana metrics
  3. Backup Automation: Scheduled backups
  4. Replication: Multi-server blob replication
  5. Advanced Analytics: Usage patterns, trends, predictions

11. References

11.1 Nostr NIPs

  • NIP-01: Basic protocol flow
  • NIP-04: Encrypted Direct Messages (deprecated, but reference)
  • NIP-19: bech32-encoded entities (npub, nsec)
  • NIP-44: Versioned Encryption (used for admin commands)

11.2 Blossom Specifications

  • BUD-01: Blob Upload/Download
  • BUD-02: Blob Descriptor
  • BUD-04: Mirroring
  • BUD-06: Upload Requirements
  • BUD-08: NIP-94 Integration
  • BUD-09: Blob Reporting

11.3 c-relay Source Files

  • c-relay/src/dm_admin.c - Admin event processing
  • c-relay/src/api.c - NIP-44 encryption
  • c-relay/src/config.c - Key storage
  • c-relay/src/main.c - CLI options
  • c-relay/src/sql_schema.h - Database schema

12. Appendix

12.1 Example Admin CLI Tool (Python)

#!/usr/bin/env python3
"""
Ginxsom Admin CLI Tool
Sends admin commands to ginxsom server via WebSocket
"""

import asyncio
import websockets
import json
from nostr_sdk import Keys, Event, EventBuilder, Kind

class GinxsomAdmin:
    def __init__(self, server_url, admin_nsec, relay_npub):
        self.server_url = server_url
        self.admin_keys = Keys.parse(admin_nsec)
        self.relay_pubkey = Keys.parse(relay_npub).public_key()
        
    async def send_command(self, command, params):
        """Send admin command and wait for response"""
        # Build command array
        command_array = [command, params]
        
        # Encrypt with NIP-44
        encrypted = self.admin_keys.nip44_encrypt(
            self.relay_pubkey,
            json.dumps(command_array)
        )
        
        # Build Kind 23456 event
        event = EventBuilder(
            Kind(23456),
            encrypted,
            [["p", str(self.relay_pubkey)]]
        ).to_event(self.admin_keys)
        
        # Send via WebSocket
        async with websockets.connect(self.server_url) as ws:
            await ws.send(json.dumps(event.as_json()))
            
            # Wait for Kind 23457 response
            response = await ws.recv()
            response_event = Event.from_json(response)
            
            # Decrypt response
            decrypted = self.admin_keys.nip44_decrypt(
                self.relay_pubkey,
                response_event.content()
            )
            
            return json.loads(decrypted)

# Usage
async def main():
    admin = GinxsomAdmin(
        "ws://localhost:8080/admin",
        "nsec1...",  # Admin private key
        "npub1..."   # Relay public key
    )
    
    # List blobs
    result = await admin.send_command("blob_list", {
        "limit": 10,
        "offset": 0
    })
    
    print(json.dumps(result, indent=2))

if __name__ == "__main__":
    asyncio.run(main())

12.2 Database Schema SQL

-- Add to db/schema.sql

-- Relay Private Key Storage
CREATE TABLE relay_seckey (
    private_key_hex TEXT NOT NULL CHECK (length(private_key_hex) = 64),
    created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
);

-- Admin Public Key (add to config table)
INSERT INTO config (key, value, data_type, description, category, requires_restart)
VALUES (
    'admin_pubkey',
    '',  -- Set during first startup
    'string',
    'Public key of authorized admin (64-char hex)',
    'security',
    0
);

-- Relay Public Key (add to config table)
INSERT INTO config (key, value, data_type, description, category, requires_restart)
VALUES (
    'relay_pubkey',
    '',  -- Set during first startup
    'string',
    'Public key of this relay (64-char hex)',
    'server',
    0
);

12.3 Makefile Updates

# Add to Makefile

# Admin system objects
ADMIN_OBJS = build/admin_websocket.o \
             build/admin_auth.o \
             build/admin_handlers.o \
             build/admin_config.o \
             build/admin_keys.o

# Update main target
build/ginxsom-fcgi: $(OBJS) $(ADMIN_OBJS)
	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)

# Admin system rules
build/admin_websocket.o: src/admin_websocket.c
	$(CC) $(CFLAGS) -c $< -o $@

build/admin_auth.o: src/admin_auth.c
	$(CC) $(CFLAGS) -c $< -o $@

build/admin_handlers.o: src/admin_handlers.c
	$(CC) $(CFLAGS) -c $< -o $@

build/admin_config.o: src/admin_config.c
	$(CC) $(CFLAGS) -c $< -o $@

build/admin_keys.o: src/admin_keys.c
	$(CC) $(CFLAGS) -c $< -o $@

Document Version: 2.0
Last Updated: 2025-01-16
Status: Ready for Implementation