1389 lines
35 KiB
Markdown
1389 lines
35 KiB
Markdown
# Ginxsom Management System Design
|
|
|
|
## Executive Summary
|
|
|
|
This document outlines the design for a secure management interface for ginxsom, a Blossom media storage server. The design adapts proven patterns from c-relay's management system while addressing ginxsom's specific requirements for blob storage, authentication, and FastCGI architecture.
|
|
|
|
**Key Design Principles:**
|
|
- **Security First**: NIP-17 gift wrap encryption for all admin commands
|
|
- **Database-Centric**: Configuration and state stored in SQLite
|
|
- **Unified Handler**: Tag-based routing similar to c-relay
|
|
- **Two-Step Confirmation**: Critical operations require explicit confirmation
|
|
- **Backwards Compatible**: Integrates with existing admin API without breaking changes
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [System Architecture](#1-system-architecture)
|
|
2. [Database Schema](#2-database-schema)
|
|
3. [Keypair Management](#3-keypair-management)
|
|
4. [Authentication Architecture](#4-authentication-architecture)
|
|
5. [Management Commands](#5-management-commands)
|
|
6. [API Design](#6-api-design)
|
|
7. [File Structure](#7-file-structure)
|
|
8. [Implementation Plan](#8-implementation-plan)
|
|
9. [Security Considerations](#9-security-considerations)
|
|
10. [Migration Strategy](#10-migration-strategy)
|
|
|
|
---
|
|
|
|
## 1. System Architecture
|
|
|
|
### 1.1 Component Overview
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph Client["Admin Client"]
|
|
CLI[CLI Tool / nak]
|
|
WEB[Web Interface]
|
|
end
|
|
|
|
subgraph Gateway["nginx Gateway"]
|
|
NGINX[nginx]
|
|
end
|
|
|
|
subgraph FastCGI["FastCGI Application"]
|
|
MAIN[main.c]
|
|
VALIDATOR[request_validator.c]
|
|
ADMIN[admin_api.c]
|
|
MGMT[management_handler.c<br/>NEW]
|
|
DM[dm_admin.c<br/>NEW]
|
|
end
|
|
|
|
subgraph Storage["Data Layer"]
|
|
DB[(SQLite Database)]
|
|
BLOBS[Blob Storage]
|
|
KEYS[Key Storage<br/>Memory Only]
|
|
end
|
|
|
|
CLI -->|NIP-17 Gift Wrap| NGINX
|
|
WEB -->|NIP-17 Gift Wrap| NGINX
|
|
NGINX -->|FastCGI| MAIN
|
|
MAIN --> VALIDATOR
|
|
VALIDATOR --> ADMIN
|
|
ADMIN --> MGMT
|
|
MGMT --> DM
|
|
DM --> DB
|
|
DM --> KEYS
|
|
MGMT --> BLOBS
|
|
|
|
style MGMT fill:#ff9
|
|
style DM fill:#ff9
|
|
style KEYS fill:#f99
|
|
```
|
|
|
|
### 1.2 Data Flow for Admin Commands
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Admin
|
|
participant nginx
|
|
participant FastCGI
|
|
participant Validator
|
|
participant DM Handler
|
|
participant Database
|
|
|
|
Admin->>nginx: POST /admin<br/>NIP-17 Gift Wrap
|
|
nginx->>FastCGI: Forward Request
|
|
FastCGI->>Validator: Validate Auth
|
|
Validator->>Validator: Decrypt Gift Wrap
|
|
Validator->>Validator: Verify Admin Pubkey
|
|
Validator-->>FastCGI: Auth Result
|
|
|
|
alt Auth Failed
|
|
FastCGI-->>Admin: 401/403 Error
|
|
else Auth Success
|
|
FastCGI->>DM Handler: Parse Command
|
|
DM Handler->>DM Handler: Extract Tags
|
|
DM Handler->>DM Handler: Route to Handler
|
|
|
|
alt Critical Operation
|
|
DM Handler->>Database: Store Pending Change
|
|
DM Handler-->>Admin: Confirmation Required
|
|
Admin->>nginx: POST /admin<br/>Confirmation Event
|
|
nginx->>FastCGI: Forward Confirmation
|
|
FastCGI->>DM Handler: Execute Pending
|
|
DM Handler->>Database: Apply Changes
|
|
else Non-Critical
|
|
DM Handler->>Database: Execute Directly
|
|
end
|
|
|
|
DM Handler->>DM Handler: Encrypt Response (NIP-44)
|
|
DM Handler-->>Admin: Encrypted Result
|
|
end
|
|
```
|
|
|
|
### 1.3 Integration with Existing System
|
|
|
|
The management system integrates with ginxsom's existing architecture:
|
|
|
|
**Existing Components (Keep):**
|
|
- [`src/main.c`](src/main.c:1): FastCGI request loop and routing
|
|
- [`src/request_validator.c`](src/request_validator.c:1): Centralized authentication
|
|
- [`src/admin_api.c`](src/admin_api.c:1): Current admin API endpoints
|
|
- [`db/schema.sql`](db/schema.sql:1): Base database schema
|
|
|
|
**New Components (Add):**
|
|
- `src/management_handler.c`: Unified command handler
|
|
- `src/dm_admin.c`: NIP-17 gift wrap processing
|
|
- `src/keypair_manager.c`: Server and admin key management
|
|
- `src/pending_changes.c`: Two-step confirmation system
|
|
|
|
**Modified Components:**
|
|
- [`src/main.c`](src/main.c:1640): Add `/admin` endpoint routing
|
|
- [`src/request_validator.c`](src/request_validator.c:683): Add NIP-17 validation
|
|
- [`db/schema.sql`](db/schema.sql:1): Add management tables
|
|
|
|
---
|
|
|
|
## 2. Database Schema
|
|
|
|
### 2.1 New Tables
|
|
|
|
```sql
|
|
-- Server keypair (relay identity)
|
|
CREATE TABLE IF NOT EXISTS server_keys (
|
|
id INTEGER PRIMARY KEY CHECK (id = 1), -- Singleton table
|
|
public_key TEXT NOT NULL CHECK (length(public_key) = 64),
|
|
private_key_encrypted TEXT NOT NULL, -- Encrypted with system key
|
|
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
last_rotated INTEGER,
|
|
UNIQUE(public_key)
|
|
);
|
|
|
|
-- Admin public keys (authorized administrators)
|
|
CREATE TABLE IF NOT EXISTS admin_keys (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
public_key TEXT NOT NULL UNIQUE CHECK (length(public_key) = 64),
|
|
name TEXT, -- Human-readable identifier
|
|
permissions TEXT NOT NULL DEFAULT 'full', -- JSON array of permissions
|
|
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
created_by TEXT, -- Admin pubkey who added this key
|
|
last_used INTEGER,
|
|
enabled INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0, 1))
|
|
);
|
|
|
|
-- Pending changes requiring confirmation
|
|
CREATE TABLE IF NOT EXISTS pending_changes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
change_type TEXT NOT NULL, -- 'delete_blob', 'update_config', 'add_admin', etc.
|
|
change_data TEXT NOT NULL, -- JSON with change details
|
|
requested_by TEXT NOT NULL, -- Admin pubkey
|
|
requested_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
expires_at INTEGER NOT NULL, -- Confirmation deadline
|
|
confirmed INTEGER NOT NULL DEFAULT 0 CHECK (confirmed IN (0, 1)),
|
|
confirmed_at INTEGER,
|
|
executed INTEGER NOT NULL DEFAULT 0 CHECK (executed IN (0, 1)),
|
|
executed_at INTEGER,
|
|
result TEXT -- Execution result or error
|
|
);
|
|
|
|
-- Admin command audit log
|
|
CREATE TABLE IF NOT EXISTS admin_audit_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
admin_pubkey TEXT NOT NULL,
|
|
command TEXT NOT NULL, -- Command tag from event
|
|
parameters TEXT, -- JSON with command parameters
|
|
success INTEGER NOT NULL CHECK (success IN (0, 1)),
|
|
error_message TEXT,
|
|
timestamp INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
client_ip TEXT,
|
|
event_id TEXT -- Nostr event ID for traceability
|
|
);
|
|
|
|
-- NIP-17 gift wrap tracking (prevent replay)
|
|
CREATE TABLE IF NOT EXISTS gift_wrap_tracking (
|
|
event_id TEXT PRIMARY KEY,
|
|
admin_pubkey TEXT NOT NULL,
|
|
processed_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
expires_at INTEGER NOT NULL
|
|
);
|
|
|
|
-- Create indexes for performance
|
|
CREATE INDEX IF NOT EXISTS idx_admin_keys_pubkey ON admin_keys(public_key);
|
|
CREATE INDEX IF NOT EXISTS idx_admin_keys_enabled ON admin_keys(enabled);
|
|
CREATE INDEX IF NOT EXISTS idx_pending_changes_expires ON pending_changes(expires_at);
|
|
CREATE INDEX IF NOT EXISTS idx_pending_changes_requested_by ON pending_changes(requested_by);
|
|
CREATE INDEX IF NOT EXISTS idx_audit_log_timestamp ON admin_audit_log(timestamp);
|
|
CREATE INDEX IF NOT EXISTS idx_audit_log_admin ON admin_audit_log(admin_pubkey);
|
|
CREATE INDEX IF NOT EXISTS idx_gift_wrap_expires ON gift_wrap_tracking(expires_at);
|
|
```
|
|
|
|
### 2.2 Schema Extensions to Existing Tables
|
|
|
|
```sql
|
|
-- Add management-related config keys
|
|
INSERT OR IGNORE INTO config (key, value, description) VALUES
|
|
('server_pubkey', '', 'Server public key (relay identity)'),
|
|
('admin_dm_enabled', 'true', 'Enable NIP-17 DM-based admin commands'),
|
|
('admin_confirmation_timeout', '300', 'Seconds to confirm critical operations'),
|
|
('admin_session_timeout', '3600', 'Admin session timeout in seconds'),
|
|
('admin_rate_limit', '100', 'Max admin commands per hour per admin'),
|
|
('admin_audit_retention', '2592000', 'Audit log retention in seconds (30 days)');
|
|
```
|
|
|
|
### 2.3 Migration from Current Schema
|
|
|
|
The current schema already has:
|
|
- [`config`](db/schema.sql:21) table (unified configuration)
|
|
- [`blobs`](db/schema.sql:8) table (blob metadata)
|
|
- [`auth_rules`](db/schema.sql:47) table (authentication rules)
|
|
|
|
**Migration Strategy:**
|
|
1. Add new tables without modifying existing ones
|
|
2. Populate `admin_keys` from existing `config.admin_pubkey`
|
|
3. Generate server keypair on first startup if not exists
|
|
4. Maintain backwards compatibility with existing admin API
|
|
|
|
---
|
|
|
|
## 3. Keypair Management
|
|
|
|
### 3.1 Server Keypair (Relay Identity)
|
|
|
|
**Purpose:** Identifies the ginxsom server in Nostr ecosystem
|
|
|
|
**Generation:**
|
|
```c
|
|
// On first startup or explicit generation
|
|
int generate_server_keypair(void) {
|
|
unsigned char privkey[32];
|
|
unsigned char pubkey[32];
|
|
|
|
// Generate using nostr_core_lib
|
|
if (nostr_generate_keypair(privkey, pubkey) != NOSTR_SUCCESS) {
|
|
return -1;
|
|
}
|
|
|
|
// Store in database (encrypted)
|
|
char pubkey_hex[65];
|
|
char privkey_hex[65];
|
|
nostr_bytes_to_hex(pubkey, 32, pubkey_hex);
|
|
nostr_bytes_to_hex(privkey, 32, privkey_hex);
|
|
|
|
// Encrypt private key before storage
|
|
char encrypted_privkey[256];
|
|
encrypt_with_system_key(privkey_hex, encrypted_privkey);
|
|
|
|
// Store in database
|
|
return store_server_keypair(pubkey_hex, encrypted_privkey);
|
|
}
|
|
```
|
|
|
|
**Storage:**
|
|
- Public key: Stored in `server_keys.public_key` and `config.server_pubkey`
|
|
- Private key: **NEVER** stored in database - kept in process memory only
|
|
- On startup: Load from database, decrypt, keep in memory
|
|
- On shutdown: Clear from memory securely
|
|
|
|
**Command-Line Options:**
|
|
```bash
|
|
# Generate new server keypair
|
|
ginxsom-fcgi --generate-server-key
|
|
|
|
# Import existing keypair
|
|
ginxsom-fcgi --import-server-key <hex_private_key>
|
|
|
|
# Show server public key
|
|
ginxsom-fcgi --show-server-pubkey
|
|
```
|
|
|
|
### 3.2 Admin Keypair Management
|
|
|
|
**Purpose:** Authorize administrators to manage the server
|
|
|
|
**Initial Setup:**
|
|
```bash
|
|
# Generate admin keypair (done by admin, not server)
|
|
ADMIN_PRIVKEY=$(nak key generate)
|
|
ADMIN_PUBKEY=$(echo "$ADMIN_PRIVKEY" | nak key public)
|
|
|
|
# Add admin to server (requires existing admin or direct DB access)
|
|
sqlite3 db/ginxsom.db << EOF
|
|
INSERT INTO admin_keys (public_key, name, permissions, created_by)
|
|
VALUES ('$ADMIN_PUBKEY', 'Primary Admin', '["full"]', 'system');
|
|
EOF
|
|
```
|
|
|
|
**Runtime Management:**
|
|
```bash
|
|
# Add new admin (via DM command)
|
|
nak event -k 14 --envelope --sec $ADMIN_PRIVKEY \
|
|
--tag command add_admin \
|
|
--tag pubkey $NEW_ADMIN_PUBKEY \
|
|
--tag name "Secondary Admin" \
|
|
--tag permissions '["read","write"]' \
|
|
| curl -X POST http://localhost:9001/admin -d @-
|
|
|
|
# List admins
|
|
nak event -k 14 --envelope --sec $ADMIN_PRIVKEY \
|
|
--tag command list_admins \
|
|
| curl -X POST http://localhost:9001/admin -d @-
|
|
|
|
# Revoke admin
|
|
nak event -k 14 --envelope --sec $ADMIN_PRIVKEY \
|
|
--tag command revoke_admin \
|
|
--tag pubkey $ADMIN_TO_REVOKE \
|
|
| curl -X POST http://localhost:9001/admin -d @-
|
|
```
|
|
|
|
### 3.3 Key Rotation
|
|
|
|
**Server Key Rotation:**
|
|
- Generate new keypair
|
|
- Update database
|
|
- Announce new pubkey via NIP-11 relay info
|
|
- Keep old key for 30 days for transition
|
|
|
|
**Admin Key Rotation:**
|
|
- Admin generates new keypair
|
|
- Uses old key to authorize new key
|
|
- Old key remains valid during transition period
|
|
- Explicit revocation of old key after confirmation
|
|
|
|
---
|
|
|
|
## 4. Authentication Architecture
|
|
|
|
### 4.1 NIP-17 Gift Wrap Overview
|
|
|
|
**Why NIP-17?**
|
|
- End-to-end encryption between admin and server
|
|
- Prevents eavesdropping on admin commands
|
|
- Provides forward secrecy
|
|
- Standard Nostr protocol (interoperable)
|
|
|
|
**Gift Wrap Structure:**
|
|
```json
|
|
{
|
|
"kind": 1059,
|
|
"content": "<encrypted_seal>",
|
|
"tags": [
|
|
["p", "<server_pubkey>"]
|
|
],
|
|
"pubkey": "<random_ephemeral_key>",
|
|
"created_at": 1234567890,
|
|
"sig": "<signature>"
|
|
}
|
|
```
|
|
|
|
**Seal Structure (encrypted in gift wrap):**
|
|
```json
|
|
{
|
|
"kind": 13,
|
|
"content": "<encrypted_rumor>",
|
|
"tags": [
|
|
["p", "<admin_pubkey>"]
|
|
],
|
|
"pubkey": "<admin_pubkey>",
|
|
"created_at": 1234567890
|
|
}
|
|
```
|
|
|
|
**Rumor Structure (encrypted in seal):**
|
|
```json
|
|
{
|
|
"kind": 14,
|
|
"content": "",
|
|
"tags": [
|
|
["command", "list_blobs"],
|
|
["limit", "50"],
|
|
["offset", "0"]
|
|
],
|
|
"pubkey": "<admin_pubkey>",
|
|
"created_at": 1234567890
|
|
}
|
|
```
|
|
|
|
### 4.2 Authentication Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Admin
|
|
participant Server
|
|
participant DB
|
|
|
|
Admin->>Admin: Create Kind 14 Rumor<br/>(command + params)
|
|
Admin->>Admin: Wrap in Kind 13 Seal<br/>(encrypt with server pubkey)
|
|
Admin->>Admin: Wrap in Kind 1059 Gift<br/>(encrypt with ephemeral key)
|
|
|
|
Admin->>Server: POST /admin<br/>Gift Wrap Event
|
|
|
|
Server->>Server: Unwrap Gift<br/>(decrypt with server privkey)
|
|
Server->>Server: Unwrap Seal<br/>(decrypt with admin pubkey)
|
|
Server->>Server: Extract Rumor<br/>(Kind 14 command)
|
|
|
|
Server->>DB: Check admin_pubkey authorized
|
|
|
|
alt Not Authorized
|
|
Server-->>Admin: 403 Forbidden
|
|
else Authorized
|
|
Server->>DB: Check gift wrap not replayed
|
|
|
|
alt Replayed
|
|
Server-->>Admin: 409 Conflict (Replay)
|
|
else Fresh
|
|
Server->>DB: Store gift wrap ID
|
|
Server->>Server: Parse command tags
|
|
Server->>Server: Execute command
|
|
Server->>DB: Log to audit_log
|
|
Server->>Server: Encrypt response (NIP-44)
|
|
Server-->>Admin: Encrypted Response
|
|
end
|
|
end
|
|
```
|
|
|
|
### 4.3 Validation Rules
|
|
|
|
**Gift Wrap Validation:**
|
|
1. Event kind must be 1059
|
|
2. Must have `p` tag with server pubkey
|
|
3. Signature must be valid
|
|
4. Created_at within acceptable time window (±5 minutes)
|
|
|
|
**Seal Validation:**
|
|
1. Decryption must succeed with server private key
|
|
2. Event kind must be 13
|
|
3. Must have `p` tag with admin pubkey
|
|
|
|
**Rumor Validation:**
|
|
1. Decryption must succeed with admin public key
|
|
2. Event kind must be 14
|
|
3. Admin pubkey must be in `admin_keys` table with `enabled=1`
|
|
4. Must have `command` tag
|
|
5. Event ID not in `gift_wrap_tracking` (prevent replay)
|
|
6. Created_at within acceptable time window
|
|
|
|
**Integration with Existing Validator:**
|
|
|
|
Add to [`src/request_validator.c`](src/request_validator.c:1):
|
|
|
|
```c
|
|
// Add to event kind routing (around line 438)
|
|
else if (event_kind == 1059) {
|
|
// NIP-17 Gift Wrap for admin commands
|
|
int gift_wrap_result = validate_gift_wrap_admin(event);
|
|
if (gift_wrap_result != NOSTR_SUCCESS) {
|
|
result->valid = 0;
|
|
result->error_code = gift_wrap_result;
|
|
strcpy(result->reason, "Gift wrap validation failed");
|
|
cJSON_Delete(event);
|
|
return NOSTR_SUCCESS;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Management Commands
|
|
|
|
### 5.1 Command Categories
|
|
|
|
**Blob Operations:**
|
|
- `list_blobs` - List blobs with filters
|
|
- `get_blob_info` - Get detailed blob metadata
|
|
- `delete_blob` - Delete blob (requires confirmation)
|
|
- `mirror_blob` - Mirror blob from another server
|
|
- `verify_blob` - Verify blob integrity
|
|
|
|
**Storage Management:**
|
|
- `get_storage_stats` - Get storage usage statistics
|
|
- `get_disk_usage` - Get disk space information
|
|
- `cleanup_orphans` - Remove orphaned files
|
|
- `set_quota` - Set storage quota for user
|
|
|
|
**Configuration:**
|
|
- `get_config` - Get configuration values
|
|
- `set_config` - Set configuration value (requires confirmation)
|
|
- `list_auth_rules` - List authentication rules
|
|
- `add_auth_rule` - Add authentication rule
|
|
- `remove_auth_rule` - Remove authentication rule (requires confirmation)
|
|
|
|
**Statistics:**
|
|
- `get_stats` - Get server statistics
|
|
- `get_upload_stats` - Get upload statistics by time period
|
|
- `get_user_stats` - Get per-user statistics
|
|
- `get_bandwidth_stats` - Get bandwidth usage
|
|
|
|
**System:**
|
|
- `get_health` - Get system health status
|
|
- `get_version` - Get server version info
|
|
- `backup_database` - Create database backup
|
|
- `restore_database` - Restore from backup (requires confirmation)
|
|
- `rotate_logs` - Rotate log files
|
|
|
|
**Admin Management:**
|
|
- `list_admins` - List admin keys
|
|
- `add_admin` - Add new admin key (requires confirmation)
|
|
- `revoke_admin` - Revoke admin key (requires confirmation)
|
|
- `get_audit_log` - Get admin audit log
|
|
|
|
### 5.2 Command Structure
|
|
|
|
**Request Format (Kind 14 Rumor):**
|
|
```json
|
|
{
|
|
"kind": 14,
|
|
"content": "",
|
|
"tags": [
|
|
["command", "list_blobs"],
|
|
["limit", "50"],
|
|
["offset", "0"],
|
|
["filter_type", "image/*"],
|
|
["since", "1234567890"]
|
|
],
|
|
"pubkey": "<admin_pubkey>",
|
|
"created_at": 1234567890
|
|
}
|
|
```
|
|
|
|
**Response Format (NIP-44 Encrypted):**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"command": "list_blobs",
|
|
"data": {
|
|
"blobs": [...],
|
|
"total": 1234,
|
|
"limit": 50,
|
|
"offset": 0
|
|
},
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
**Error Response:**
|
|
```json
|
|
{
|
|
"status": "error",
|
|
"command": "list_blobs",
|
|
"error": {
|
|
"code": "INVALID_PARAMETER",
|
|
"message": "Invalid limit value",
|
|
"details": "Limit must be between 1 and 1000"
|
|
},
|
|
"timestamp": 1234567890
|
|
}
|
|
```
|
|
|
|
### 5.3 Two-Step Confirmation
|
|
|
|
**Critical Operations Requiring Confirmation:**
|
|
- `delete_blob` - Permanent data loss
|
|
- `set_config` - System behavior changes
|
|
- `add_admin` - Security implications
|
|
- `revoke_admin` - Access control changes
|
|
- `restore_database` - Data integrity risk
|
|
|
|
**Confirmation Flow:**
|
|
|
|
**Step 1: Request**
|
|
```json
|
|
{
|
|
"kind": 14,
|
|
"tags": [
|
|
["command", "delete_blob"],
|
|
["sha256", "abc123..."]
|
|
]
|
|
}
|
|
```
|
|
|
|
**Step 1: Response**
|
|
```json
|
|
{
|
|
"status": "confirmation_required",
|
|
"command": "delete_blob",
|
|
"pending_id": "42",
|
|
"details": {
|
|
"sha256": "abc123...",
|
|
"size": 1048576,
|
|
"type": "image/jpeg",
|
|
"uploaded_at": 1234567890
|
|
},
|
|
"expires_at": 1234568190,
|
|
"message": "This will permanently delete the blob. Send confirmation within 5 minutes."
|
|
}
|
|
```
|
|
|
|
**Step 2: Confirmation**
|
|
```json
|
|
{
|
|
"kind": 14,
|
|
"tags": [
|
|
["command", "confirm"],
|
|
["pending_id", "42"]
|
|
]
|
|
}
|
|
```
|
|
|
|
**Step 2: Response**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"command": "delete_blob",
|
|
"data": {
|
|
"sha256": "abc123...",
|
|
"deleted": true
|
|
},
|
|
"timestamp": 1234567900
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. API Design
|
|
|
|
### 6.1 Endpoint Routing
|
|
|
|
**New Endpoint:**
|
|
- `POST /admin` - Unified admin command endpoint (NIP-17 gift wrap)
|
|
|
|
**Existing Endpoints (Keep):**
|
|
- `GET /api/stats` - Statistics (existing admin API)
|
|
- `GET /api/config` - Configuration (existing admin API)
|
|
- `PUT /api/config` - Update config (existing admin API)
|
|
- `GET /api/files` - File listing (existing admin API)
|
|
- `GET /api/health` - Health check (existing admin API)
|
|
|
|
**Integration Strategy:**
|
|
- New `/admin` endpoint for NIP-17 DM-based commands
|
|
- Existing `/api/*` endpoints remain for backwards compatibility
|
|
- Both systems share same database and authentication
|
|
- Gradual migration path for clients
|
|
|
|
### 6.2 Request Handling
|
|
|
|
**Handler Registration in [`src/main.c`](src/main.c:1640):**
|
|
|
|
```c
|
|
// Add to main request loop (around line 1640)
|
|
else if (strcmp(request_method, "POST") == 0 &&
|
|
strcmp(request_uri, "/admin") == 0) {
|
|
// Handle NIP-17 gift wrap admin commands
|
|
handle_admin_dm_request();
|
|
}
|
|
```
|
|
|
|
**Unified Handler Pattern:**
|
|
|
|
```c
|
|
// src/management_handler.c
|
|
void handle_admin_dm_request(void) {
|
|
// 1. Read gift wrap event from request body
|
|
char *event_json = read_request_body();
|
|
|
|
// 2. Validate and unwrap gift wrap
|
|
admin_command_t cmd;
|
|
int result = unwrap_admin_gift_wrap(event_json, &cmd);
|
|
if (result != SUCCESS) {
|
|
send_admin_error(result, "Failed to unwrap gift wrap");
|
|
return;
|
|
}
|
|
|
|
// 3. Check admin authorization
|
|
if (!is_admin_authorized(cmd.admin_pubkey)) {
|
|
send_admin_error(ERROR_UNAUTHORIZED, "Not authorized");
|
|
return;
|
|
}
|
|
|
|
// 4. Check for replay
|
|
if (is_gift_wrap_replayed(cmd.event_id)) {
|
|
send_admin_error(ERROR_REPLAY, "Gift wrap already processed");
|
|
return;
|
|
}
|
|
|
|
// 5. Route to command handler
|
|
admin_response_t response;
|
|
result = route_admin_command(&cmd, &response);
|
|
|
|
// 6. Log to audit log
|
|
log_admin_command(&cmd, result);
|
|
|
|
// 7. Encrypt and send response
|
|
send_admin_response(&response, cmd.admin_pubkey);
|
|
}
|
|
```
|
|
|
|
### 6.3 Tag-Based Routing
|
|
|
|
**Command Router:**
|
|
|
|
```c
|
|
int route_admin_command(admin_command_t *cmd, admin_response_t *response) {
|
|
const char *command = get_tag_value(cmd->tags, "command");
|
|
|
|
if (!command) {
|
|
return ERROR_MISSING_COMMAND;
|
|
}
|
|
|
|
// Blob operations
|
|
if (strcmp(command, "list_blobs") == 0) {
|
|
return handle_list_blobs(cmd, response);
|
|
} else if (strcmp(command, "get_blob_info") == 0) {
|
|
return handle_get_blob_info(cmd, response);
|
|
} else if (strcmp(command, "delete_blob") == 0) {
|
|
return handle_delete_blob(cmd, response);
|
|
}
|
|
|
|
// Storage management
|
|
else if (strcmp(command, "get_storage_stats") == 0) {
|
|
return handle_get_storage_stats(cmd, response);
|
|
} else if (strcmp(command, "cleanup_orphans") == 0) {
|
|
return handle_cleanup_orphans(cmd, response);
|
|
}
|
|
|
|
// Configuration
|
|
else if (strcmp(command, "get_config") == 0) {
|
|
return handle_get_config(cmd, response);
|
|
} else if (strcmp(command, "set_config") == 0) {
|
|
return handle_set_config(cmd, response);
|
|
}
|
|
|
|
// Admin management
|
|
else if (strcmp(command, "list_admins") == 0) {
|
|
return handle_list_admins(cmd, response);
|
|
} else if (strcmp(command, "add_admin") == 0) {
|
|
return handle_add_admin(cmd, response);
|
|
}
|
|
|
|
// Confirmation
|
|
else if (strcmp(command, "confirm") == 0) {
|
|
return handle_confirm_pending(cmd, response);
|
|
}
|
|
|
|
else {
|
|
return ERROR_UNKNOWN_COMMAND;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. File Structure
|
|
|
|
### 7.1 New Files
|
|
|
|
**Core Management:**
|
|
```
|
|
src/management_handler.c - Unified command handler and routing
|
|
src/management_handler.h - Handler interface definitions
|
|
src/dm_admin.c - NIP-17 gift wrap processing
|
|
src/dm_admin.h - Gift wrap interface
|
|
src/keypair_manager.c - Server and admin key management
|
|
src/keypair_manager.h - Key management interface
|
|
src/pending_changes.c - Two-step confirmation system
|
|
src/pending_changes.h - Pending changes interface
|
|
```
|
|
|
|
**Command Handlers:**
|
|
```
|
|
src/commands/blob_commands.c - Blob operation handlers
|
|
src/commands/storage_commands.c - Storage management handlers
|
|
src/commands/config_commands.c - Configuration handlers
|
|
src/commands/stats_commands.c - Statistics handlers
|
|
src/commands/admin_commands.c - Admin management handlers
|
|
src/commands/system_commands.c - System operation handlers
|
|
```
|
|
|
|
**Utilities:**
|
|
```
|
|
src/utils/encryption.c - NIP-44 encryption utilities
|
|
src/utils/audit_log.c - Audit logging utilities
|
|
src/utils/response_builder.c - Response formatting
|
|
```
|
|
|
|
### 7.2 Modified Files
|
|
|
|
**[`src/main.c`](src/main.c:1):**
|
|
- Add `/admin` endpoint routing (line ~1640)
|
|
- Initialize management system on startup
|
|
- Add cleanup on shutdown
|
|
|
|
**[`src/request_validator.c`](src/request_validator.c:1):**
|
|
- Add Kind 1059 (gift wrap) validation (line ~438)
|
|
- Add gift wrap unwrapping logic
|
|
- Add replay prevention checks
|
|
|
|
**[`src/admin_api.c`](src/admin_api.c:1):**
|
|
- Keep existing endpoints for backwards compatibility
|
|
- Add integration hooks for new management system
|
|
- Share database access with new handlers
|
|
|
|
**[`db/schema.sql`](db/schema.sql:1):**
|
|
- Add new tables (server_keys, admin_keys, pending_changes, etc.)
|
|
- Add indexes for performance
|
|
- Add default configuration values
|
|
|
|
**[`Makefile`](Makefile):**
|
|
- Add new source files to build
|
|
- Add dependencies for new modules
|
|
- Update clean targets
|
|
|
|
### 7.3 Integration Points
|
|
|
|
**With Existing Admin API:**
|
|
```c
|
|
// src/admin_api.c - Add integration function
|
|
void admin_api_notify_config_change(const char *key, const char *value) {
|
|
// Called by management system when config changes
|
|
// Invalidates cache, triggers reload
|
|
nostr_request_validator_force_cache_refresh();
|
|
}
|
|
```
|
|
|
|
**With Request Validator:**
|
|
```c
|
|
// src/request_validator.c - Add gift wrap validation
|
|
int validate_gift_wrap_admin(cJSON *event) {
|
|
// Validate Kind 1059 structure
|
|
// Unwrap and validate seal
|
|
// Unwrap and validate rumor
|
|
// Check admin authorization
|
|
// Check replay prevention
|
|
return NOSTR_SUCCESS;
|
|
}
|
|
```
|
|
|
|
**With Database:**
|
|
```c
|
|
// All handlers use shared database connection
|
|
// Consistent error handling
|
|
// Transaction support for atomic operations
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Implementation Plan
|
|
|
|
### 8.1 Phase 1: Foundation (Week 1-2)
|
|
|
|
**Goals:**
|
|
- Database schema extensions
|
|
- Keypair management
|
|
- Basic gift wrap processing
|
|
|
|
**Tasks:**
|
|
1. Create database migration script
|
|
2. Implement `keypair_manager.c`
|
|
- Server keypair generation
|
|
- Admin keypair storage
|
|
- Key loading on startup
|
|
3. Implement `dm_admin.c`
|
|
- Gift wrap unwrapping
|
|
- Seal decryption
|
|
- Rumor extraction
|
|
4. Add gift wrap validation to `request_validator.c`
|
|
5. Create test suite for gift wrap processing
|
|
|
|
**Deliverables:**
|
|
- Working keypair management
|
|
- Gift wrap unwrap/validation
|
|
- Database schema updated
|
|
- Unit tests passing
|
|
|
|
### 8.2 Phase 2: Command Infrastructure (Week 3-4)
|
|
|
|
**Goals:**
|
|
- Unified command handler
|
|
- Tag-based routing
|
|
- Response encryption
|
|
|
|
**Tasks:**
|
|
1. Implement `management_handler.c`
|
|
- Request parsing
|
|
- Command routing
|
|
- Response building
|
|
2. Implement `pending_changes.c`
|
|
- Two-step confirmation
|
|
- Timeout handling
|
|
- Execution tracking
|
|
3. Add `/admin` endpoint to `main.c`
|
|
4. Implement audit logging
|
|
5. Create command handler templates
|
|
|
|
**Deliverables:**
|
|
- Working command routing
|
|
- Two-step confirmation system
|
|
- Audit logging functional
|
|
- Integration tests passing
|
|
|
|
### 8.3 Phase 3: Core Commands (Week 5-6)
|
|
|
|
**Goals:**
|
|
- Implement essential management commands
|
|
- Integration with existing systems
|
|
|
|
**Tasks:**
|
|
1. Implement blob commands
|
|
- `list_blobs`
|
|
- `get_blob_info`
|
|
- `delete_blob` (with confirmation)
|
|
2. Implement storage commands
|
|
- `get_storage_stats`
|
|
- `get_disk_usage`
|
|
- `cleanup_orphans`
|
|
3. Implement config commands
|
|
- `get_config`
|
|
- `set_config` (with confirmation)
|
|
4. Implement admin commands
|
|
- `list_admins`
|
|
- `add_admin` (with confirmation)
|
|
- `revoke_admin` (with confirmation)
|
|
5. Integration testing with existing admin API
|
|
|
|
**Deliverables:**
|
|
- Core commands functional
|
|
- Integration with existing API
|
|
- End-to-end tests passing
|
|
|
|
### 8.4 Phase 4: Advanced Features (Week 7-8)
|
|
|
|
**Goals:**
|
|
- Statistics and monitoring
|
|
- System operations
|
|
- CLI tooling
|
|
|
|
**Tasks:**
|
|
1. Implement stats commands
|
|
- `get_stats`
|
|
- `get_upload_stats`
|
|
- `get_user_stats`
|
|
2. Implement system commands
|
|
- `backup_database`
|
|
- `restore_database`
|
|
- `rotate_logs`
|
|
3. Create CLI tool for admin operations
|
|
4. Create web interface (optional)
|
|
5. Performance optimization
|
|
6. Security audit
|
|
|
|
**Deliverables:**
|
|
- All commands implemented
|
|
- CLI tool functional
|
|
- Performance benchmarks
|
|
- Security review complete
|
|
|
|
### 8.5 Phase 5: Documentation & Deployment (Week 9-10)
|
|
|
|
**Goals:**
|
|
- Complete documentation
|
|
- Deployment guides
|
|
- Migration tools
|
|
|
|
**Tasks:**
|
|
1. Write admin documentation
|
|
2. Create setup guides
|
|
3. Create migration scripts
|
|
4. Write troubleshooting guide
|
|
5. Create example scripts
|
|
6. Production deployment testing
|
|
|
|
**Deliverables:**
|
|
- Complete documentation
|
|
- Migration tools
|
|
- Deployment guides
|
|
- Production-ready release
|
|
|
|
---
|
|
|
|
## 9. Security Considerations
|
|
|
|
### 9.1 Threat Model
|
|
|
|
**Threats:**
|
|
1. **Unauthorized Access**: Attacker gains admin privileges
|
|
2. **Replay Attacks**: Reuse of captured gift wrap events
|
|
3. **Man-in-the-Middle**: Interception of admin commands
|
|
4. **Privilege Escalation**: Regular user gains admin access
|
|
5. **Data Exfiltration**: Unauthorized access to blob data
|
|
6. **Denial of Service**: Resource exhaustion via admin commands
|
|
|
|
**Mitigations:**
|
|
1. **NIP-17 Encryption**: End-to-end encryption prevents MITM
|
|
2. **Gift Wrap Tracking**: Prevents replay attacks
|
|
3. **Admin Key Management**: Strict authorization checks
|
|
4. **Two-Step Confirmation**: Prevents accidental critical operations
|
|
5. **Audit Logging**: Tracks all admin actions
|
|
6. **Rate Limiting**: Prevents DoS via admin commands
|
|
|
|
### 9.2 Key Security
|
|
|
|
**Server Private Key:**
|
|
- **NEVER** stored in database
|
|
- Loaded into memory on startup
|
|
- Cleared on shutdown
|
|
- Protected by OS memory protection
|
|
- Consider using secure enclave if available
|
|
|
|
**Admin Private Keys:**
|
|
- **NEVER** stored on server
|
|
- Managed by admin clients only
|
|
- Rotated regularly
|
|
- Revoked immediately if compromised
|
|
|
|
**Database Encryption:**
|
|
- Consider encrypting sensitive config values
|
|
- Use system keyring for encryption keys
|
|
- Implement key rotation mechanism
|
|
|
|
### 9.3 Access Control
|
|
|
|
**Permission Levels:**
|
|
```json
|
|
{
|
|
"full": ["*"],
|
|
"read": ["list_*", "get_*"],
|
|
"write": ["list_*", "get_*", "set_*", "add_*"],
|
|
"admin": ["list_*", "get_*", "set_*", "add_*", "delete_*", "revoke_*"]
|
|
}
|
|
```
|
|
|
|
**Permission Checks:**
|
|
```c
|
|
int check_admin_permission(const char *admin_pubkey, const char *command) {
|
|
// Load admin permissions from database
|
|
cJSON *permissions = get_admin_permissions(admin_pubkey);
|
|
|
|
// Check if command is allowed
|
|
if (has_permission(permissions, command)) {
|
|
return 1;
|
|
}
|
|
|
|
// Check wildcard permissions
|
|
if (has_permission(permissions, "*")) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
### 9.4 Audit Trail
|
|
|
|
**What to Log:**
|
|
- All admin commands (success and failure)
|
|
- Admin key additions/revocations
|
|
- Configuration changes
|
|
- Critical operations (delete, restore, etc.)
|
|
- Authentication failures
|
|
- Suspicious activity
|
|
|
|
**Log Format:**
|
|
```json
|
|
{
|
|
"timestamp": 1234567890,
|
|
"admin_pubkey": "abc123...",
|
|
"command": "delete_blob",
|
|
"parameters": {"sha256": "def456..."},
|
|
"success": true,
|
|
"client_ip": "192.168.1.100",
|
|
"event_id": "ghi789..."
|
|
}
|
|
```
|
|
|
|
**Log Retention:**
|
|
- Keep audit logs for 30 days minimum
|
|
- Archive older logs to separate storage
|
|
- Implement log rotation
|
|
- Protect logs from tampering
|
|
|
|
---
|
|
|
|
## 10. Migration Strategy
|
|
|
|
### 10.1 Backwards Compatibility
|
|
|
|
**Existing Admin API:**
|
|
- Keep all existing `/api/*` endpoints
|
|
- No breaking changes to current API
|
|
- Gradual deprecation over 6 months
|
|
- Clear migration documentation
|
|
|
|
**Database:**
|
|
- Additive schema changes only
|
|
- No modifications to existing tables
|
|
- Migration script handles upgrades
|
|
- Rollback capability
|
|
|
|
**Configuration:**
|
|
- Existing config keys remain valid
|
|
- New config keys added with defaults
|
|
- No changes to config file format
|
|
|
|
### 10.2 Migration Steps
|
|
|
|
**Step 1: Database Migration**
|
|
```bash
|
|
# Backup existing database
|
|
cp db/ginxsom.db db/ginxsom.db.backup
|
|
|
|
# Run migration script
|
|
sqlite3 db/ginxsom.db < db/migrations/002_add_management_system.sql
|
|
|
|
# Verify migration
|
|
sqlite3 db/ginxsom.db "SELECT name FROM sqlite_master WHERE type='table';"
|
|
```
|
|
|
|
**Step 2: Generate Server Keypair**
|
|
```bash
|
|
# Generate server keypair
|
|
./build/ginxsom-fcgi --generate-server-key
|
|
|
|
# Verify keypair
|
|
./build/ginxsom-fcgi --show-server-pubkey
|
|
```
|
|
|
|
**Step 3: Add Initial Admin**
|
|
```bash
|
|
# Generate admin keypair
|
|
ADMIN_PRIVKEY=$(nak key generate)
|
|
ADMIN_PUBKEY=$(echo "$ADMIN_PRIVKEY" | nak key public)
|
|
|
|
# Add to database
|
|
sqlite3 db/ginxsom.db << EOF
|
|
INSERT INTO admin_keys (public_key, name, permissions, created_by)
|
|
VALUES ('$ADMIN_PUBKEY', 'Primary Admin', '["full"]', 'system');
|
|
EOF
|
|
|
|
# Save admin private key securely
|
|
echo "$ADMIN_PRIVKEY" > ~/.config/ginxsom/admin.key
|
|
chmod 600 ~/.config/ginxsom/admin.key
|
|
```
|
|
|
|
**Step 4: Test New System**
|
|
```bash
|
|
# Test gift wrap command
|
|
nak event -k 14 --envelope --sec $ADMIN_PRIVKEY \
|
|
--tag command list_admins \
|
|
| curl -X POST http://localhost:9001/admin -d @-
|
|
|
|
# Verify response
|
|
```
|
|
|
|
**Step 5: Update Clients**
|
|
- Update admin scripts to use new `/admin` endpoint
|
|
- Migrate from `/api/*` to NIP-17 commands
|
|
- Test thoroughly before production
|
|
|
|
### 10.3 Rollback Plan
|
|
|
|
**If Issues Occur:**
|
|
1. Stop ginxsom service
|
|
2. Restore database backup
|
|
3. Revert to previous version
|
|
4. Investigate issues
|
|
5. Fix and retry migration
|
|
|
|
**Database Rollback:**
|
|
```bash
|
|
# Stop service
|
|
systemctl stop ginxsom
|
|
|
|
# Restore backup
|
|
cp db/ginxsom.db.backup db/ginxsom.db
|
|
|
|
# Restart service
|
|
systemctl start ginxsom
|
|
```
|
|
|
|
---
|
|
|
|
## Appendix A: Command Reference
|
|
|
|
### Blob Commands
|
|
|
|
**list_blobs**
|
|
```json
|
|
{
|
|
"command": "list_blobs",
|
|
"limit": "50",
|
|
"offset": "0",
|
|
"filter_type": "image/*",
|
|
"since": "1234567890"
|
|
}
|
|
```
|
|
|
|
**get_blob_info**
|
|
```json
|
|
{
|
|
"command": "get_blob_info",
|
|
"sha256": "abc123..."
|
|
}
|
|
```
|
|
|
|
**delete_blob** (requires confirmation)
|
|
```json
|
|
{
|
|
"command": "delete_blob",
|
|
"sha256": "abc123..."
|
|
}
|
|
```
|
|
|
|
### Storage Commands
|
|
|
|
**get_storage_stats**
|
|
```json
|
|
{
|
|
"command": "get_storage_stats"
|
|
}
|
|
```
|
|
|
|
**cleanup_orphans**
|
|
```json
|
|
{
|
|
"command": "cleanup_orphans",
|
|
"dry_run": "true"
|
|
}
|
|
```
|
|
|
|
### Configuration Commands
|
|
|
|
**get_config**
|
|
```json
|
|
{
|
|
"command": "get_config",
|
|
"key": "max_file_size"
|
|
}
|
|
```
|
|
|
|
**set_config** (requires confirmation)
|
|
```json
|
|
{
|
|
"command": "set_config",
|
|
"key": "max_file_size",
|
|
"value": "209715200"
|
|
}
|
|
```
|
|
|
|
### Admin Commands
|
|
|
|
**list_admins**
|
|
```json
|
|
{
|
|
"command": "list_admins"
|
|
}
|
|
```
|
|
|
|
**add_admin** (requires confirmation)
|
|
```json
|
|
{
|
|
"command": "add_admin",
|
|
"pubkey": "def456...",
|
|
"name": "Secondary Admin",
|
|
"permissions": "[\"read\",\"write\"]"
|
|
}
|
|
```
|
|
|
|
**revoke_admin** (requires confirmation)
|
|
```json
|
|
{
|
|
"command": "revoke_admin",
|
|
"pubkey": "def456..."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Appendix B: Example Scripts
|
|
|
|
### Setup Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# setup_admin.sh - Initial admin setup
|
|
|
|
set -e
|
|
|
|
echo "Ginxsom Admin Setup"
|
|
echo "==================="
|
|
|
|
# Generate admin keypair
|
|
echo "Generating admin keypair..."
|
|
ADMIN_PRIVKEY=$(nak key generate)
|
|
ADMIN_PUBKEY=$(echo "$ADMIN_PRIVKEY" | nak key public)
|
|
|
|
echo "Admin Public Key: $ADMIN_PUBKEY"
|
|
|
|
# Save private key
|
|
mkdir -p ~/.config/ginxsom
|
|
echo "$ADMIN_PRIVKEY" > ~/.config/ginxsom/admin.key
|
|
chmod 600 ~/.config/ginxsom/admin.key
|
|
|
|
echo "Private key saved to ~/.config/ginxsom/admin.key"
|
|
|
|
# Add to database
|
|
echo "Adding admin to database..."
|
|
sqlite3 db/ginxsom.db << EOF
|
|
INSERT INTO admin_keys (public_key, name, permissions, created_by)
|
|
VALUES ('$ADMIN_PUBKEY', 'Primary Admin', '["full"]', 'system');
|
|
EOF
|
|
|
|
echo "Admin setup complete!"
|
|
echo "Test with: ./admin_command.sh list_admins"
|
|
```
|
|
|
|
### Admin Command Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# admin_command.sh - Send admin command
|
|
|
|
ADMIN_PRIVKEY=$(cat ~/.config/ginxsom/admin.key)
|
|
COMMAND=$1
|
|
shift
|
|
|
|
# Build tags
|
|
TAGS=""
|
|
for arg in "$@"; do
|
|
KEY=$(echo "$arg" | cut -d= -f1)
|
|
VALUE=$(echo "$arg" | cut -d= -f2-)
|
|
TAGS="$TAGS --tag $KEY \"$VALUE\""
|
|
done
|
|
|
|
# Send command
|
|
eval nak event -k 14 --envelope --sec "$ADMIN_PRIVKEY" \
|
|
--tag command "$COMMAND" \
|
|
$TAGS \
|
|
| curl -s -X POST http://localhost:9001/admin -d @- \
|
|
| jq .
|
|
```
|
|
|
|
### Usage Examples
|
|
|
|
```bash
|
|
# List admins
|
|
./admin_command.sh list_admins
|
|
|
|
# Get storage stats
|
|
./admin_command.sh get_storage_stats
|
|
|
|
# List blobs
|
|
./admin_command.sh list_blobs limit=10 offset=0
|
|
|
|
# Delete blob (with confirmation)
|
|
./admin_command.sh delete_blob sha256=abc123...
|
|
# Then confirm
|
|
./admin_command.sh confirm pending_id=42
|
|
```
|
|
|
|
---
|
|
|
|
## Conclusion
|
|
|
|
This design provides a secure, scalable management system for ginxsom that:
|
|
|
|
1. **Leverages Proven Patterns**: Adapts c-relay's successful architecture
|
|
2. **Maintains Security**: NIP-17 encryption and two-step confirmation
|
|
3. **Ensures Compatibility**: Integrates with existing admin API
|
|
4. **Enables Growth**: Extensible command system for future features
|
|
5. **Provides Auditability**: Complete audit trail of admin actions
|
|
|
|
The phased implementation plan allows for incremental development and testing, while the migration strategy ensures smooth transition from the current system.
|
|
|
|
**Next Steps:**
|
|
1. Review and approve design
|
|
2. Begin Phase 1 implementation
|
|
3. Set up development environment
|
|
4. Create test infrastructure
|
|
5. Start coding! |