v0.1.9 - program generates it's own private keys.

This commit is contained in:
Your Name
2025-11-20 07:53:58 -04:00
parent c1b615de32
commit e693fe3caa
36 changed files with 4542 additions and 188 deletions

View File

@@ -0,0 +1,994 @@
# 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
```mermaid
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
```mermaid
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
```mermaid
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
```mermaid
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
```sql
-- 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)
```sql
-- 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:
```json
["command_name", {"param1": "value1", "param2": "value2"}]
```
### 3.2 Event Structure
#### Kind 23456 - Admin Command Event
```json
{
"kind": 23456,
"pubkey": "<admin-pubkey-hex>",
"created_at": 1234567890,
"tags": [
["p", "<relay-pubkey-hex>"]
],
"content": "<nip44-encrypted-command-array>",
"sig": "<signature>"
}
```
**Content (decrypted)**:
```json
["blob_list", {"limit": 100, "offset": 0}]
```
#### Kind 23457 - Admin Response Event
```json
{
"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)**:
```json
{
"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
```json
// 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
```json
// Command
["blob_delete", {
"sha256": "abc123...",
"confirm": true
}]
// Response
{
"success": true,
"data": {
"deleted": true,
"sha256": "abc123...",
"freed_bytes": 102400
}
}
```
#### Example 3: Get Storage Stats
```json
// 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
```json
// 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:
```json
{
"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)
```bash
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
```
4. Store relay private key in database
5. Store admin public key in config
6. 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)
```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
```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
```makefile
# 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